diff --git a/python/python-psi-impl/resources/inspectionDescriptions/PyTypeAliasRedeclarationInspection.html b/python/python-psi-impl/resources/inspectionDescriptions/PyTypeAliasRedeclarationInspection.html
new file mode 100644
index 000000000000..a81b16744bbe
--- /dev/null
+++ b/python/python-psi-impl/resources/inspectionDescriptions/PyTypeAliasRedeclarationInspection.html
@@ -0,0 +1,10 @@
+
+
+Reports redeclarations of type aliases.
+Example:
+
+type A = int
+type A = str
+
+
+
diff --git a/python/python-psi-impl/resources/intellij.python.psi.impl.xml b/python/python-psi-impl/resources/intellij.python.psi.impl.xml
index 6b2cbe9f9e5d..80092c77feb9 100644
--- a/python/python-psi-impl/resources/intellij.python.psi.impl.xml
+++ b/python/python-psi-impl/resources/intellij.python.psi.impl.xml
@@ -205,6 +205,7 @@
+
diff --git a/python/python-psi-impl/resources/messages/PyPsiBundle.properties b/python/python-psi-impl/resources/messages/PyPsiBundle.properties
index b4b281cb7a5e..c66d14466b89 100644
--- a/python/python-psi-impl/resources/messages/PyPsiBundle.properties
+++ b/python/python-psi-impl/resources/messages/PyPsiBundle.properties
@@ -594,6 +594,10 @@ INSP.decorator.receives.unexpected.builtin=This decorator will not receive the c
INSP.NAME.redeclaration=Redeclared names without usages
INSP.redeclared.name=Redeclared ''{0}'' defined above without usage
+# PyTypeAliasRedeclarationInspection
+INSP.NAME.type.alias.redeclaration=Redeclared type alias
+INSP.redeclared.type.alias=Name ''{0}'' already defined
+
# PyInterpreterInspection
INSP.NAME.invalid.interpreter=An invalid interpreter
INSP.interpreter.pipenv.interpreter.associated.with.another.project=Pipenv interpreter is associated with another project: ''{0}''
diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeAliasRedeclarationInspection.kt b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeAliasRedeclarationInspection.kt
new file mode 100644
index 000000000000..56150f3583a1
--- /dev/null
+++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeAliasRedeclarationInspection.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.inspections
+
+import com.intellij.codeInsight.controlflow.ControlFlowUtil
+import com.intellij.codeInsight.controlflow.Instruction
+import com.intellij.codeInspection.LocalInspectionToolSession
+import com.intellij.codeInspection.LocalQuickFix
+import com.intellij.codeInspection.ProblemHighlightType
+import com.intellij.codeInspection.ProblemsHolder
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiElementVisitor
+import com.intellij.psi.PsiNameIdentifierOwner
+import com.jetbrains.python.PyPsiBundle
+import com.jetbrains.python.PythonUiService
+import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache
+import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction
+import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil
+import com.jetbrains.python.psi.PyTypeAliasStatement
+import com.jetbrains.python.psi.types.TypeEvalContext
+
+/**
+ * Annotates type alias re-declarations
+ */
+class PyTypeAliasRedeclarationInspection : PyInspection() {
+ override fun buildVisitor(
+ holder: ProblemsHolder,
+ isOnTheFly: Boolean,
+ session: LocalInspectionToolSession
+ ): PsiElementVisitor {
+ return Visitor(holder, PyInspectionVisitor.getContext(session))
+ }
+
+ private class Visitor(holder: ProblemsHolder?, context: TypeEvalContext) : PyInspectionVisitor(holder, context) {
+ override fun visitPyTypeAliasStatement(node: PyTypeAliasStatement) {
+ reportRedeclaration(node)
+ }
+
+ fun reportRedeclaration(element: PsiNameIdentifierOwner) {
+ val name = element.getName()
+ var writeElement: PsiElement? = null
+ if (name != null) {
+ val owner = ScopeUtil.getScopeOwner(element)
+ if (owner != null) {
+ val instructions = ControlFlowCache.getControlFlow(owner).getInstructions()
+ val startInstruction = ControlFlowUtil.findInstructionNumberByElement(instructions, element)
+ if (startInstruction >= 0) {
+ ControlFlowUtil.iteratePrev(startInstruction, instructions) { instruction: Instruction? ->
+ if (instruction is ReadWriteInstruction && instruction.num() != startInstruction) {
+ if (name == instruction.name) {
+ val originalElement = instruction.element
+ if (originalElement != null) {
+ if (instruction.access.isWriteAccess && originalElement !== element) {
+ writeElement = originalElement
+ return@iteratePrev ControlFlowUtil.Operation.BREAK
+ }
+ }
+ }
+ }
+ ControlFlowUtil.Operation.NEXT
+ }
+ }
+ }
+ }
+
+ if (writeElement == null) {
+ return
+ }
+ val quickFixes: MutableList = ArrayList()
+ val quickFix = PythonUiService.getInstance().createPyRenameElementQuickFix(element)
+ if (quickFix != null) {
+ quickFixes.add(quickFix)
+ }
+ val identifier = element.getNameIdentifier()
+ registerProblem(identifier ?: element,
+ PyPsiBundle.message("INSP.redeclared.type.alias", name),
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
+ null,
+ *quickFixes.toTypedArray())
+ }
+ }
+}
diff --git a/python/testData/inspections/PyRedeclarationInspection/redeclaredTopLevel.py b/python/testData/inspections/PyRedeclarationInspection/redeclaredTopLevel.py
index c5f73954cc89..f251bb5daf78 100644
--- a/python/testData/inspections/PyRedeclarationInspection/redeclaredTopLevel.py
+++ b/python/testData/inspections/PyRedeclarationInspection/redeclaredTopLevel.py
@@ -7,4 +7,4 @@ def TopLevelBoo():
class TopLevelBoo:
- pass
\ No newline at end of file
+ pass
diff --git a/python/testData/inspections/PyTypeAliasRedeclarationInspection/typeAliasRedeclaration.py b/python/testData/inspections/PyTypeAliasRedeclarationInspection/typeAliasRedeclaration.py
new file mode 100644
index 000000000000..695d4c9000d7
--- /dev/null
+++ b/python/testData/inspections/PyTypeAliasRedeclarationInspection/typeAliasRedeclaration.py
@@ -0,0 +1,6 @@
+type UnusedAlias = str
+type UnusedAlias = str
+
+type UsedAlias = int
+print(UsedAlias)
+type UsedAlias = int
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypeAliasRedeclarationInspectionTest.kt b/python/testSrc/com/jetbrains/python/inspections/PyTypeAliasRedeclarationInspectionTest.kt
new file mode 100644
index 000000000000..0d322c7922c6
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/inspections/PyTypeAliasRedeclarationInspectionTest.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.inspections
+
+import com.jetbrains.python.fixtures.PyInspectionTestCase
+
+class PyTypeAliasRedeclarationInspectionTest : PyInspectionTestCase() {
+ // PY-76851
+ fun testTypeAliasRedeclaration() {
+ doTest()
+ }
+
+ override fun getInspectionClass(): Class {
+ return PyTypeAliasRedeclarationInspection::class.java
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypingConformanceTest.kt b/python/testSrc/com/jetbrains/python/inspections/PyTypingConformanceTest.kt
index 5c990067b5af..77038f9e0814 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyTypingConformanceTest.kt
+++ b/python/testSrc/com/jetbrains/python/inspections/PyTypingConformanceTest.kt
@@ -42,6 +42,7 @@ private val inspections
PyTypeCheckerInspection(),
PyTypeHintsInspection(),
PyUnresolvedReferencesInspection(),
+ PyTypeAliasRedeclarationInspection(),
)
@RunWith(Parameterized::class)