diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java index 68aef3c6cdbb..8613eab64a96 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java @@ -271,6 +271,7 @@ public class PyNamedParameterImpl extends PyBaseElementImpl parameterWasReassigned = Ref.create(false); final Ref noneComparison = Ref.create(false); + final PyResolveContext resolveContext = PyResolveContext.defaultContext(context); if (owner != null && name != null) { owner.accept(new PyRecursiveElementVisitor() { @@ -378,8 +379,10 @@ public class PyNamedParameterImpl extends PyBaseElementImpl false") private boolean isReferenceToParameter(@Nullable PsiElement element) { if (element == null) return false; - final PsiReference reference = element.getReference(); - return reference != null && reference.isReferenceTo(PyNamedParameterImpl.this); + if (!(element instanceof PyReferenceExpression || element instanceof PyTargetExpression)) return false; + if (((PyQualifiedExpression)element).isQualified()) return false; + List<@Nullable PsiElement> definitions = PyUtil.multiResolveTopPriority(element, resolveContext); + return ContainerUtil.all(definitions, e -> e == PyNamedParameterImpl.this); } }); } diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/unionContainingUnknownType.py b/python/testData/inspections/PyUnresolvedReferencesInspection/unionContainingUnknownType.py index e816b67e8945..daf7c3c598f7 100644 --- a/python/testData/inspections/PyUnresolvedReferencesInspection/unionContainingUnknownType.py +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/unionContainingUnknownType.py @@ -1,4 +1,4 @@ def foo(smth, param): if smth: param = "" - print(param.smth()) \ No newline at end of file + print(param.smth()) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/Py3TypeTest.java b/python/testSrc/com/jetbrains/python/Py3TypeTest.java index c83e803469a1..9e70a7af5f92 100644 --- a/python/testSrc/com/jetbrains/python/Py3TypeTest.java +++ b/python/testSrc/com/jetbrains/python/Py3TypeTest.java @@ -4676,6 +4676,17 @@ public class Py3TypeTest extends PyTestCase { """); } + // PY-85030 + public void testStructuralTypesAttributeAccessAfterTypeNarrowingAndReassignmentInIf() { + doTest("(p: Any) -> None", """ + def f(p): + if isinstance(p, int): + p = "foo" + x = p.lower() + expr = f + """); + } + private void doTest(final String expectedType, final String text) { myFixture.configureByText(PythonFileType.INSTANCE, text); final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class); diff --git a/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java index 83f33d822696..94b28be35535 100644 --- a/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java @@ -4125,5 +4125,37 @@ public class Py3TypeCheckerInspectionTest extends PyInspectionTestCase { _: C2 = c1 """); } + + // PY-85030 + public void testStructuralTypeAndStrictUnion() { + doTestByText(""" + responses = { + 100: "abc", + } + + def process(status): + if isinstance(status, int): + status = responses[status] + return status.lower().replace(" ", "-") + + def do(arg): + title = "abc" if arg else 100 + return process(title) + """); + } + + // PY-85030 + public void testStructuralTypeAndDefiniteReassignmentUnderCondition() { + doTestByText(""" + def f(p): + if p: + p = "foo" + else: + p = "bar" + return p.lower() + + f(42) + """); + } }