diff --git a/mypy/semanal_shared.py b/mypy/semanal_shared.py index bdd01ef6a6f3..e94604b66381 100644 --- a/mypy/semanal_shared.py +++ b/mypy/semanal_shared.py @@ -46,6 +46,7 @@ TypeVarLikeType, TypeVarTupleType, UnpackType, + flatten_nested_tuples, get_proper_type, ) @@ -290,7 +291,7 @@ def calculate_tuple_fallback(typ: TupleType) -> None: fallback = typ.partial_fallback assert fallback.type.fullname == "builtins.tuple" items = [] - for item in typ.items: + for item in flatten_nested_tuples(typ.items): # TODO: this duplicates some logic in typeops.tuple_fallback(). if isinstance(item, UnpackType): unpacked_type = get_proper_type(item.type) diff --git a/mypy/semanal_typeargs.py b/mypy/semanal_typeargs.py index 435abb78ca43..be39a8259c2e 100644 --- a/mypy/semanal_typeargs.py +++ b/mypy/semanal_typeargs.py @@ -102,6 +102,8 @@ def visit_type_alias_type(self, t: TypeAliasType) -> None: # If there was already an error for the alias itself, there is no point in checking # the expansion, most likely it will result in the same kind of error. get_proper_type(t).accept(self) + if t.alias is not None: + t.alias.accept(self) def visit_tuple_type(self, t: TupleType) -> None: t.items = flatten_nested_tuples(t.items) @@ -254,6 +256,10 @@ def visit_unpack_type(self, typ: UnpackType) -> None: def check_type_var_values( self, name: str, actuals: list[Type], arg_name: str, valids: list[Type], context: Context ) -> bool: + if self.in_type_alias_expr: + # See testValidTypeAliasValues - we do not enforce typevar compatibility + # at the definition site. We check instantiation validity later. + return False is_error = False for actual in get_proper_types(actuals): # We skip UnboundType here, since they may appear in defn.bases, diff --git a/test-data/unit/check-typevar-tuple.test b/test-data/unit/check-typevar-tuple.test index f44758f7b51b..bc483cc58ad1 100644 --- a/test-data/unit/check-typevar-tuple.test +++ b/test-data/unit/check-typevar-tuple.test @@ -2666,3 +2666,30 @@ def identity(smth: _FT) -> _FT: class S(tuple[Unpack[Ts]], Generic[T, Unpack[Ts]]): def f(self, x: T, /) -> T: ... [builtins fixtures/tuple.pyi] + +[case testNoCrashSubclassingTupleWithTrivialUnpack] +# https://github.com/python/mypy/issues/19105 +from typing import Unpack + +class A(tuple[Unpack[tuple[int]]]): ... +class B(tuple[Unpack[tuple[()]]]): ... + +a: A +reveal_type(tuple(a)) # N: Revealed type is "builtins.tuple[builtins.int, ...]" +(x,) = a + +b: B +(_,) = b # E: Need more than 0 values to unpack (1 expected) +[builtins fixtures/tuple.pyi] + +[case testNoCrashSubclassingTupleWithVariadicUnpack] +# https://github.com/python/mypy/issues/19105 +from typing import Unpack + +class A(tuple[Unpack[tuple[int, ...]]]): ... + +a: A +tuple(a) +(x,) = a +(_,) = a +[builtins fixtures/tuple.pyi]