PY-76865 Fix Conformance test failure: generics_typevartuple_args.py

Fix the situations when two tuples passed as function arguments were not matched correctly

GitOrigin-RevId: fae271e16ed0933343e9e00a77f9f316c6f99798
This commit is contained in:
Daniil Kalinin
2025-04-13 14:34:58 +00:00
committed by intellij-monorepo-bot
parent 62c154a0b2
commit f977a01dfa
3 changed files with 10 additions and 11 deletions
@@ -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 {
@@ -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
@@ -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,), <warning descr="Expected type 'tuple[int]' (matched generic type 'tuple[*Ts]'), got 'tuple[int, int]' instead">(1, 2)</warning>)
# *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,), <warning descr="Expected type 'tuple[int]' (matched generic type 'tuple[*Ts]'), got 'tuple[str]' instead">('1',)</warning>)
""");
}