Skip to content

Commit 7a746c4

Browse files
authored
Consider TypeVarTuple to be invariant (#16759)
The TypeVarTuple equality checks mentioned in PEP 646 assume TypeVarTuple to be `invariant`. https://peps.python.org/pep-0646/#type-variable-tuple-equality Fixes: #16739
1 parent 4183778 commit 7a746c4

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

mypy/constraints.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -894,8 +894,9 @@ def visit_instance(self, template: Instance) -> list[Constraint]:
894894
res.append(Constraint(template_arg, SUBTYPE_OF, suffix))
895895
res.append(Constraint(template_arg, SUPERTYPE_OF, suffix))
896896
elif isinstance(tvar, TypeVarTupleType):
897-
# Handle variadic type variables covariantly for consistency.
898-
res.extend(infer_constraints(template_arg, mapped_arg, self.direction))
897+
# Consider variadic type variables to be invariant.
898+
res.extend(infer_constraints(template_arg, mapped_arg, SUBTYPE_OF))
899+
res.extend(infer_constraints(template_arg, mapped_arg, SUPERTYPE_OF))
899900
return res
900901
if (
901902
template.type.is_protocol

mypy/test/testconstraints.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,18 @@ def test_basic_type_var_tuple_subtype(self) -> None:
3030

3131
def test_basic_type_var_tuple(self) -> None:
3232
fx = self.fx
33-
assert infer_constraints(
34-
Instance(fx.gvi, [UnpackType(fx.ts)]), Instance(fx.gvi, [fx.a, fx.b]), SUPERTYPE_OF
35-
) == [
33+
assert set(
34+
infer_constraints(
35+
Instance(fx.gvi, [UnpackType(fx.ts)]), Instance(fx.gvi, [fx.a, fx.b]), SUPERTYPE_OF
36+
)
37+
) == {
3638
Constraint(
3739
type_var=fx.ts, op=SUPERTYPE_OF, target=TupleType([fx.a, fx.b], fx.std_tuple)
38-
)
39-
]
40+
),
41+
Constraint(
42+
type_var=fx.ts, op=SUBTYPE_OF, target=TupleType([fx.a, fx.b], fx.std_tuple)
43+
),
44+
}
4045

4146
def test_type_var_tuple_with_prefix_and_suffix(self) -> None:
4247
fx = self.fx
@@ -51,6 +56,9 @@ def test_type_var_tuple_with_prefix_and_suffix(self) -> None:
5156
Constraint(
5257
type_var=fx.ts, op=SUPERTYPE_OF, target=TupleType([fx.b, fx.c], fx.std_tuple)
5358
),
59+
Constraint(
60+
type_var=fx.ts, op=SUBTYPE_OF, target=TupleType([fx.b, fx.c], fx.std_tuple)
61+
),
5462
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.d),
5563
}
5664

@@ -64,7 +72,9 @@ def test_unpack_homogenous_tuple(self) -> None:
6472
)
6573
) == {
6674
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.a),
75+
Constraint(type_var=fx.t, op=SUBTYPE_OF, target=fx.a),
6776
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.b),
77+
Constraint(type_var=fx.t, op=SUBTYPE_OF, target=fx.b),
6878
}
6979

7080
def test_unpack_homogenous_tuple_with_prefix_and_suffix(self) -> None:
@@ -78,7 +88,9 @@ def test_unpack_homogenous_tuple_with_prefix_and_suffix(self) -> None:
7888
) == {
7989
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.a),
8090
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.b),
91+
Constraint(type_var=fx.s, op=SUBTYPE_OF, target=fx.b),
8192
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.c),
93+
Constraint(type_var=fx.s, op=SUBTYPE_OF, target=fx.c),
8294
Constraint(type_var=fx.u, op=SUPERTYPE_OF, target=fx.d),
8395
}
8496

@@ -93,7 +105,9 @@ def test_unpack_with_prefix_and_suffix(self) -> None:
93105
) == {
94106
Constraint(type_var=fx.u, op=SUPERTYPE_OF, target=fx.a),
95107
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.b),
108+
Constraint(type_var=fx.t, op=SUBTYPE_OF, target=fx.b),
96109
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.c),
110+
Constraint(type_var=fx.s, op=SUBTYPE_OF, target=fx.c),
97111
Constraint(type_var=fx.u, op=SUPERTYPE_OF, target=fx.d),
98112
}
99113

test-data/unit/check-typevar-tuple.test

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,3 +2277,30 @@ higher_order(bad2) # E: Argument 1 to "higher_order" has incompatible type "Cal
22772277
higher_order(bad3) # E: Argument 1 to "higher_order" has incompatible type "Callable[[NamedArg(str, 'd')], int]"; expected "Callable[[int, str, VarArg(Unpack[Tuple[Unpack[Tuple[Any, ...]], int]])], Any]"
22782278
higher_order(bad4) # E: Argument 1 to "higher_order" has incompatible type "Callable[[KwArg(None)], None]"; expected "Callable[[int, str, VarArg(Unpack[Tuple[Unpack[Tuple[Any, ...]], int]])], Any]"
22792279
[builtins fixtures/tuple.pyi]
2280+
2281+
[case testTypeVarTupleInvariant]
2282+
from typing import Generic, Tuple
2283+
from typing_extensions import Unpack, TypeVarTuple
2284+
Ts = TypeVarTuple("Ts")
2285+
2286+
class Array(Generic[Unpack[Ts]]): ...
2287+
2288+
def pointwise_multiply(x: Array[Unpack[Ts]], y: Array[Unpack[Ts]]) -> Array[Unpack[Ts]]: ...
2289+
2290+
def a1(x: Array[int], y: Array[str], z: Array[int, str]) -> None:
2291+
reveal_type(pointwise_multiply(x, x)) # N: Revealed type is "__main__.Array[builtins.int]"
2292+
reveal_type(pointwise_multiply(x, y)) # E: Cannot infer type argument 1 of "pointwise_multiply" \
2293+
# N: Revealed type is "__main__.Array[Unpack[builtins.tuple[Any, ...]]]"
2294+
reveal_type(pointwise_multiply(x, z)) # E: Cannot infer type argument 1 of "pointwise_multiply" \
2295+
# N: Revealed type is "__main__.Array[Unpack[builtins.tuple[Any, ...]]]"
2296+
2297+
def func(x: Array[Unpack[Ts]], *args: Unpack[Ts]) -> Tuple[Unpack[Ts]]:
2298+
...
2299+
2300+
def a2(x: Array[int, str]) -> None:
2301+
reveal_type(func(x, 2, "Hello")) # N: Revealed type is "Tuple[builtins.int, builtins.str]"
2302+
reveal_type(func(x, 2)) # E: Cannot infer type argument 1 of "func" \
2303+
# N: Revealed type is "builtins.tuple[Any, ...]"
2304+
reveal_type(func(x, 2, "Hello", True)) # E: Cannot infer type argument 1 of "func" \
2305+
# N: Revealed type is "builtins.tuple[Any, ...]"
2306+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)