Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,10 @@ def analyze_type_with_type_info(
return AnyType(TypeOfAny.from_error)

# Check type argument count.
old_args = instance.args
instance.args = tuple(flatten_nested_tuples(instance.args))
if old_args and not instance.args:
empty_tuple_index = True
if not (self.defining_alias and self.nesting_level == 0) and not validate_instance(
instance, self.fail, empty_tuple_index
):
Expand Down Expand Up @@ -2192,7 +2195,10 @@ def instantiate_type_alias(
# Type aliases are special, since they can be expanded during semantic analysis,
# so we need to normalize them as soon as possible.
# TODO: can this cause an infinite recursion?
old_args = args
args = flatten_nested_tuples(args)
if old_args and not args:
empty_tuple_index = True
if any(unknown_unpack(a) for a in args):
# This type is not ready to be validated, because of unknown total count.
# Note that we keep the kind of Any for consistency.
Expand Down
29 changes: 29 additions & 0 deletions test-data/unit/check-python313.test
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,32 @@ reveal_type(a) # N: Revealed type is "builtins.list[builtins.list[Any]]"
type A[T = A] = int
a: A
reveal_type(a) # N: Revealed type is "builtins.int"

[case testPEP695VariadicGenericClassEmptyTupleUnpackIndex]
class Blah[*Ts]:
pass

x: Blah[()]
y: Blah[*tuple[()]]

type Empty = tuple[()]
z: Blah[*Empty]

reveal_type(x) # N: Revealed type is "__main__.Blah[()]"
reveal_type(y) # N: Revealed type is "__main__.Blah[()]"
reveal_type(z) # N: Revealed type is "__main__.Blah[()]"
[builtins fixtures/tuple.pyi]

[case testPEP695VariadicGenericAliasEmptyTupleUnpackIndex]
type Blah[*Ts] = list[tuple[*Ts]]

x: Blah[()]
y: Blah[*tuple[()]]

type Empty = tuple[()]
z: Blah[*Empty]

reveal_type(x) # N: Revealed type is "builtins.list[tuple[()]]"
reveal_type(y) # N: Revealed type is "builtins.list[tuple[()]]"
reveal_type(z) # N: Revealed type is "builtins.list[tuple[()]]"
[builtins fixtures/tuple.pyi]
35 changes: 35 additions & 0 deletions test-data/unit/check-typevar-tuple.test
Original file line number Diff line number Diff line change
Expand Up @@ -2838,3 +2838,38 @@ def test(t: tuple[int, ...]) -> None: ...
test(x)
test(y)
[builtins fixtures/tuple.pyi]

[case testVariadicGenericClassEmptyTupleUnpackIndex]
from typing import Generic, TypeVarTuple, Unpack

Ts = TypeVarTuple("Ts")
class Blah(Generic[Unpack[Ts]]):
pass

x: Blah[()]
y: Blah[Unpack[tuple[()]]]

Empty = tuple[()]
z: Blah[Unpack[Empty]]

reveal_type(x) # N: Revealed type is "__main__.Blah[()]"
reveal_type(y) # N: Revealed type is "__main__.Blah[()]"
reveal_type(z) # N: Revealed type is "__main__.Blah[()]"
[builtins fixtures/tuple.pyi]

[case testVariadicGenericAliasEmptyTupleUnpackIndex]
from typing import Generic, TypeVarTuple, Unpack

Ts = TypeVarTuple("Ts")
Blah = list[tuple[Unpack[Ts]]]

x: Blah[()]
y: Blah[Unpack[tuple[()]]]

Empty = tuple[()]
z: Blah[Unpack[Empty]]

reveal_type(x) # N: Revealed type is "builtins.list[tuple[()]]"
reveal_type(y) # N: Revealed type is "builtins.list[tuple[()]]"
reveal_type(z) # N: Revealed type is "builtins.list[tuple[()]]"
[builtins fixtures/tuple.pyi]
Loading