diff --git a/python/python-psi-impl/resources/messages/PyPsiBundle.properties b/python/python-psi-impl/resources/messages/PyPsiBundle.properties
index a60c48492c8a..558d920217d0 100644
--- a/python/python-psi-impl/resources/messages/PyPsiBundle.properties
+++ b/python/python-psi-impl/resources/messages/PyPsiBundle.properties
@@ -374,6 +374,7 @@ QFIX.NAME.add.field.to.class=Add field to class
QFIX.add.field.to.class=Add field ''{0}'' to class {1}
QFIX.add.field.to.class.popup.content.added.init=Added a __init__ to class {0}
to accommodate new field {1}
QFIX.NAME.remove.parameter=Remove parameter
+QFIX.NAME.remove.type.parameter=Remove type parameter
QFIX.NAME.rename.parameter=Rename parameter
QFIX.rename.parameter=Rename to ''{0}''
QFIX.NAME.remove.statement=Remove statement
diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/quickfix/PyRemoveTypeParameterQuickFix.kt b/python/python-psi-impl/src/com/jetbrains/python/inspections/quickfix/PyRemoveTypeParameterQuickFix.kt
new file mode 100644
index 000000000000..1badc467e2ab
--- /dev/null
+++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/quickfix/PyRemoveTypeParameterQuickFix.kt
@@ -0,0 +1,49 @@
+package com.jetbrains.python.inspections.quickfix
+
+import com.intellij.modcommand.ModPsiUpdater
+import com.intellij.modcommand.PsiUpdateModCommandQuickFix
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiWhiteSpace
+import com.intellij.psi.util.PsiTreeUtil
+import com.jetbrains.python.PyPsiBundle
+import com.jetbrains.python.PyTokenTypes
+import com.jetbrains.python.psi.PyElement
+import com.jetbrains.python.psi.PyTypeParameter
+import com.jetbrains.python.psi.PyTypeParameterList
+
+/**
+ * Removes a single type parameter from a type parameter list.
+ * If the list becomes empty, removes the brackets as well.
+ */
+class PyRemoveTypeParameterQuickFix : PsiUpdateModCommandQuickFix() {
+ override fun getFamilyName(): String = PyPsiBundle.message("QFIX.NAME.remove.type.parameter")
+
+ override fun applyFix(project: Project, element: PsiElement, updater: ModPsiUpdater) {
+ val typeParameter = PsiTreeUtil.getParentOfType(element, PyTypeParameter::class.java, false) ?: return
+ val list = PsiTreeUtil.getParentOfType(typeParameter, PyTypeParameterList::class.java, false) ?: return
+
+ var prev: PsiElement? = typeParameter.prevSibling
+ var next: PsiElement? = typeParameter.nextSibling
+
+ if (prev is PsiWhiteSpace) prev = prev.prevSibling
+ if (next is PsiWhiteSpace) next = next.nextSibling
+
+ if (prev != null && prev.node.elementType == PyTokenTypes.COMMA) {
+ prev.delete()
+ val afterComma = typeParameter.prevSibling
+ if (afterComma is PsiWhiteSpace) afterComma.delete()
+ }
+ else if (next != null && next.node.elementType == PyTokenTypes.COMMA) {
+ val ws = next.nextSibling
+ next.delete()
+ if (ws is PsiWhiteSpace) ws.delete()
+ }
+
+ typeParameter.delete()
+
+ if (list.typeParameters.isEmpty()) {
+ (list as PyElement).delete()
+ }
+ }
+}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/unusedLocal/PyUnusedLocalInspectionVisitor.java b/python/python-psi-impl/src/com/jetbrains/python/inspections/unusedLocal/PyUnusedLocalInspectionVisitor.java
index 542a71cda9f3..370ff0173931 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/inspections/unusedLocal/PyUnusedLocalInspectionVisitor.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/unusedLocal/PyUnusedLocalInspectionVisitor.java
@@ -362,7 +362,7 @@ public final class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
final PsiElement name = typeParameter.getNameIdentifier();
registerWarning(name != null ? name : element,
PyPsiBundle.message("INSP.unused.locals.type.parameter.isnot.used", typeParameter.getName()),
- new PyRemoveStatementQuickFix());
+ new PyRemoveTypeParameterQuickFix());
}
else {
// Local variable or parameter
diff --git a/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInFunction.py b/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInFunction.py
new file mode 100644
index 000000000000..eeab21762d95
--- /dev/null
+++ b/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInFunction.py
@@ -0,0 +1,4 @@
+from typing import Callable
+
+def foo[T, U](fn: Callable[..., T]) -> T:
+ return fn()
diff --git a/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInFunction_after.py b/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInFunction_after.py
new file mode 100644
index 000000000000..fa57b53569be
--- /dev/null
+++ b/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInFunction_after.py
@@ -0,0 +1,4 @@
+from typing import Callable
+
+def foo[T](fn: Callable[..., T]) -> T:
+ return fn()
diff --git a/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInTypeAlias.py b/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInTypeAlias.py
new file mode 100644
index 000000000000..91899a8a6bef
--- /dev/null
+++ b/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInTypeAlias.py
@@ -0,0 +1,3 @@
+from typing import Callable
+
+type Alias[T, U] = Callable[..., T]
diff --git a/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInTypeAlias_after.py b/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInTypeAlias_after.py
new file mode 100644
index 000000000000..2ff4f0f682c0
--- /dev/null
+++ b/python/testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/removeUnusedTypeParameterInTypeAlias_after.py
@@ -0,0 +1,3 @@
+from typing import Callable
+
+type Alias[T] = Callable[..., T]
diff --git a/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveUnusedLocalQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveUnusedLocalQuickFixTest.java
index 0a7c255f4e67..903f8eb36da0 100644
--- a/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveUnusedLocalQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveUnusedLocalQuickFixTest.java
@@ -103,4 +103,16 @@ public class PyRemoveUnusedLocalQuickFixTest extends PyQuickFixTestCase {
public void testComprehensionIterator() {
doQuickFixTest(PyUnusedLocalInspection.class, PyPsiBundle.message("INSP.unused.locals.replace.with.wildcard"));
}
+
+ // PY-85080
+ public void testRemoveUnusedTypeParameterInFunction() {
+ runWithLanguageLevel(LanguageLevel.PYTHON312,
+ () -> doQuickFixTest(PyUnusedLocalInspection.class, PyPsiBundle.message("QFIX.NAME.remove.type.parameter")));
+ }
+
+ // PY-85080
+ public void testRemoveUnusedTypeParameterInTypeAlias() {
+ runWithLanguageLevel(LanguageLevel.PYTHON312,
+ () -> doQuickFixTest(PyUnusedLocalInspection.class, PyPsiBundle.message("QFIX.NAME.remove.type.parameter")));
+ }
}