diff --git a/python/src/com/jetbrains/python/pyi/PyiTypeProvider.java b/python/src/com/jetbrains/python/pyi/PyiTypeProvider.java index 03207e585b5e..f6c2df5f8923 100644 --- a/python/src/com/jetbrains/python/pyi/PyiTypeProvider.java +++ b/python/src/com/jetbrains/python/pyi/PyiTypeProvider.java @@ -27,10 +27,7 @@ import com.jetbrains.python.psi.types.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import static com.jetbrains.python.psi.PyUtil.as; @@ -119,9 +116,7 @@ public class PyiTypeProvider extends PyTypeProviderBase { for (PyFunction overload : overloads) { final PyType returnType = context.getReturnType(overload); - if (!PyTypeChecker.hasGenerics(returnType, context)) { - allReturnTypes.add(returnType); - } + allReturnTypes.add(PyTypeChecker.substitute(returnType, new HashMap<>(), context)); final PyExpression receiver = PyTypeChecker.getReceiver(callSite, overload); final PyCallExpressionHelper.ArgumentMappingResults mapping = mapArguments(callSite, overload, context); @@ -129,11 +124,11 @@ public class PyiTypeProvider extends PyTypeProviderBase { continue; } final Map substitutions = PyTypeChecker.unifyGenericCall(receiver, mapping.getMappedParameters(), context); - - final PyType unifiedType = substitutions != null ? PyTypeChecker.substitute(returnType, substitutions, context) : null; - if (unifiedType != null) { - matchedReturnTypes.add(unifiedType); + if (substitutions == null) { + continue; } + final PyType unifiedType = PyTypeChecker.substitute(returnType, substitutions, context); + matchedReturnTypes.add(unifiedType); } return Ref.create(PyUnionType.union(matchedReturnTypes.isEmpty() ? allReturnTypes : matchedReturnTypes)); diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/listIndexedByUnknownType.py b/python/testData/inspections/PyUnresolvedReferencesInspection/listIndexedByUnknownType.py new file mode 100644 index 000000000000..d736117e174f --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/listIndexedByUnknownType.py @@ -0,0 +1,8 @@ +def f(i): + xs = [] + xs[i].items() + + +def g(index): + x = [][index] + x['foo'] diff --git a/python/testData/pyi/type/overloadedNotMatchedType/OverloadedNotMatchedType.py b/python/testData/pyi/type/overloadedNotMatchedType/OverloadedNotMatchedType.py new file mode 100644 index 000000000000..974ecfa18e0a --- /dev/null +++ b/python/testData/pyi/type/overloadedNotMatchedType/OverloadedNotMatchedType.py @@ -0,0 +1,6 @@ +from typing import Any +from m1 import C + +def f(x: Any): + c = C() + expr = c.foo(x) diff --git a/python/testData/pyi/type/overloadedNotMatchedType/m1.pyi b/python/testData/pyi/type/overloadedNotMatchedType/m1.pyi new file mode 100644 index 000000000000..24f62bb4c2d8 --- /dev/null +++ b/python/testData/pyi/type/overloadedNotMatchedType/m1.pyi @@ -0,0 +1,9 @@ +from typing import TypeVar, Generic, overload, List + +_T = TypeVar('_T') + +class C(Generic[_T]): + @overload + def foo(self, i: int) -> _T: ... + @overload + def foo(self, s: slice) -> List[_T]: ... diff --git a/python/testSrc/com/jetbrains/python/PyTypingTest.java b/python/testSrc/com/jetbrains/python/PyTypingTest.java index 12420ba99c6e..d869af1d0ee4 100644 --- a/python/testSrc/com/jetbrains/python/PyTypingTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypingTest.java @@ -892,6 +892,23 @@ public class PyTypingTest extends PyTestCase { "expr = xs.pop()"); } + public void testGenericUserFunctionWithManyParamsAndNestedCall() { + doTest("Tuple[bool, int, str]", + "from typing import TypeVar\n" + + "\n" + + "T = TypeVar('T')\n" + + "U = TypeVar('U')\n" + + "V = TypeVar('V')\n" + + "\n" + + "def myid(x: T) -> T:\n" + + " pass\n" + + "\n" + + "def f(x: T, y: U, z: V):\n" + + " return myid(x), myid(y), myid(z)\n" + + "\n" + + "expr = f(True, 1, 'foo')\n"); + } + private void doTestNoInjectedText(@NotNull String text) { myFixture.configureByText(PythonFileType.INSTANCE, text); final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(myFixture.getProject()); diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index e26d550b25ed..7a19faa97ffe 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -768,6 +768,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doTest(); } + // PY-22741, PY-22808 + public void testListIndexedByUnknownType() { + doTest(); + } + @NotNull @Override protected Class getInspectionClass() { diff --git a/python/testSrc/com/jetbrains/python/pyi/PyiTypeTest.java b/python/testSrc/com/jetbrains/python/pyi/PyiTypeTest.java index 0349ee5cee7f..33d3dfdbffcb 100644 --- a/python/testSrc/com/jetbrains/python/pyi/PyiTypeTest.java +++ b/python/testSrc/com/jetbrains/python/pyi/PyiTypeTest.java @@ -113,4 +113,9 @@ public class PyiTypeTest extends PyTestCase { public void testOverloadedReturnType() { doTest("str"); } + + // PY-22808 + public void testOverloadedNotMatchedType() { + doTest("Union[list, Any]"); + } }