diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
index 2d2e61438948..94c2abbb36e9 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
@@ -542,15 +542,17 @@ public class PyTypeCheckerInspection extends PyInspection {
// For an expected type with generics we have to match all the actual types against it in order to do proper generic unification
if (PyTypeChecker.hasGenerics(expected, myTypeEvalContext)) {
- // First collect type parameter substitutions by matching the expected type with the union.
- PyType actualJoin = PyUnionType.union(ContainerUtil.map(arguments, myTypeEvalContext::getType));
- matchParameterAndArgument(expected, actualJoin, null, substitutions);
- PyType expectedWithSubstitutions = substituteGenerics(expected, substitutions);
+ // First collect type parameter substitutions by matching the expected type with the union, if it's a keyword container
+ // otherwise, match as usual arguments, passed to a function
+ if (container.isKeywordContainer()) {
+ PyType actualJoin = PyUnionType.union(ContainerUtil.map(arguments, myTypeEvalContext::getType));
+ matchParameterAndArgument(expected, actualJoin, null, substitutions);
+ }
return ContainerUtil.map(arguments, argument -> {
// Then match each argument type against the expected type after these substitutions.
PyType actual = myTypeEvalContext.getType(argument);
boolean matched = matchParameterAndArgument(expected, actual, argument, substitutions);
- return new AnalyzeArgumentResult(argument, expected, expectedWithSubstitutions, actual, matched);
+ return new AnalyzeArgumentResult(argument, expected, substituteGenerics(expected, substitutions), actual, matched);
});
}
else {
diff --git a/python/testData/typing/conformance/tests/_ignored.txt b/python/testData/typing/conformance/tests/_ignored.txt
index 7b5dca2bd0c4..ea150f804aeb 100644
--- a/python/testData/typing/conformance/tests/_ignored.txt
+++ b/python/testData/typing/conformance/tests/_ignored.txt
@@ -37,7 +37,6 @@ generics_self_usage.py
generics_syntax_declarations.py
generics_syntax_infer_variance.py
generics_syntax_scoping.py
-generics_typevartuple_args.py
generics_typevartuple_basic.py
generics_typevartuple_overloads.py
generics_typevartuple_specialization.py
diff --git a/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java
index aa28c5c448d6..651fc92cb035 100644
--- a/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/Py3TypeCheckerInspectionTest.java
@@ -1916,21 +1916,19 @@ public class Py3TypeCheckerInspectionTest extends PyInspectionTestCase {
""");
}
- // PY-53105
+ // PY-53105, PY-76865
public void testVariadicGenericStarArgsOfVariadicGeneric() {
doTestByText("""
from typing import Tuple, TypeVarTuple
Ts = TypeVarTuple('Ts')
-
def foo(*args: Tuple[*Ts]): ...
-
foo((0,), (1,))
foo((0,), (1, 2))
- # *tuple[int | str] is inferred for *Ts
- foo((0,), ('1',))
+ # Should fail according to https://typing.python.org/en/latest/spec/generics.html#type-variable-tuple-equality
+ foo((0,), ('1',))
""");
}