Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
5 changes: 4 additions & 1 deletion mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@
UnboundType,
UnionType,
UnpackType,
flatten_nested_tuples,
get_proper_type,
get_proper_types,
has_type_vars,
Expand Down Expand Up @@ -6093,7 +6094,9 @@ def analyze_type_application_args(self, expr: IndexExpr) -> list[Type] | None:
types.append(analyzed)

if allow_unpack:
types = self.type_analyzer().check_unpacks_in_list(types)
# need to flatten away harmless unpacks like Unpack[tuple[int]]
flattened_items = flatten_nested_tuples(types)
types = self.type_analyzer().check_unpacks_in_list(flattened_items)
if has_param_spec and num_args == 1 and types:
first_arg = get_proper_type(types[0])
single_any = len(types) == 1 and isinstance(first_arg, AnyType)
Expand Down
2 changes: 1 addition & 1 deletion mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1978,7 +1978,7 @@ def check_unpacks_in_list(self, items: list[Type]) -> list[Type]:

if num_unpacks > 1:
assert final_unpack is not None
self.fail("More than one Unpack in a type is not allowed", final_unpack.type)
self.fail("More than one variable Unpack in a type is not allowed", final_unpack.type)
return new_items

def tuple_type(self, items: list[Type], line: int, column: int) -> TupleType:
Expand Down
11 changes: 6 additions & 5 deletions test-data/unit/check-python312.test
Original file line number Diff line number Diff line change
Expand Up @@ -2038,12 +2038,13 @@ class Z: ... # E: Name "Z" already defined on line 2
# https://github.com/python/mypy/issues/18856
class A[*Ts]: ...

A[*tuple[int, ...], *tuple[int, ...]] # E: More than one Unpack in a type is not allowed
a: A[*tuple[int, ...], *tuple[int, ...]] # E: More than one Unpack in a type is not allowed
def foo(a: A[*tuple[int, ...], *tuple[int, ...]]): ... # E: More than one Unpack in a type is not allowed
A[*tuple[int, ...], *tuple[int, ...]] # E: More than one variable Unpack in a type is not allowed
A[*tuple[*tuple[int, ...]], *tuple[*tuple[int, ...]]] # E: More than one variable Unpack in a type is not allowed
a: A[*tuple[int, ...], *tuple[int, ...]] # E: More than one variable Unpack in a type is not allowed
def foo(a: A[*tuple[int, ...], *tuple[int, ...]]): ... # E: More than one variable Unpack in a type is not allowed

tuple[*tuple[int, ...], *tuple[int, ...]] # E: More than one Unpack in a type is not allowed
b: tuple[*tuple[int, ...], *tuple[int, ...]] # E: More than one Unpack in a type is not allowed
tuple[*tuple[int, ...], *tuple[int, ...]] # E: More than one variable Unpack in a type is not allowed
b: tuple[*tuple[int, ...], *tuple[int, ...]] # E: More than one variable Unpack in a type is not allowed
[builtins fixtures/tuple.pyi]
[typing fixtures/typing-full.pyi]

Expand Down
18 changes: 9 additions & 9 deletions test-data/unit/check-typevar-tuple.test
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ reveal_type(empty) # N: Revealed type is "__main__.Variadic[()]"
omitted: Variadic
reveal_type(omitted) # N: Revealed type is "__main__.Variadic[Unpack[builtins.tuple[Any, ...]]]"

bad: Variadic[Unpack[Tuple[int, ...]], str, Unpack[Tuple[bool, ...]]] # E: More than one Unpack in a type is not allowed
bad: Variadic[Unpack[Tuple[int, ...]], str, Unpack[Tuple[bool, ...]]] # E: More than one variable Unpack in a type is not allowed
reveal_type(bad) # N: Revealed type is "__main__.Variadic[Unpack[builtins.tuple[builtins.int, ...]], builtins.str]"

bad2: Unpack[Tuple[int, ...]] # E: Unpack is only valid in a variadic position
Expand Down Expand Up @@ -353,12 +353,12 @@ expect_variadic_array_2(u)
Ts = TypeVarTuple("Ts")
Ts2 = TypeVarTuple("Ts2")

def bad(x: Tuple[int, Unpack[Ts], str, Unpack[Ts2]]) -> None: # E: More than one Unpack in a type is not allowed
def bad(x: Tuple[int, Unpack[Ts], str, Unpack[Ts2]]) -> None: # E: More than one variable Unpack in a type is not allowed

...
reveal_type(bad) # N: Revealed type is "def [Ts, Ts2] (x: tuple[builtins.int, Unpack[Ts`-1], builtins.str])"

def bad2(x: Tuple[int, Unpack[Tuple[int, ...]], str, Unpack[Tuple[str, ...]]]) -> None: # E: More than one Unpack in a type is not allowed
def bad2(x: Tuple[int, Unpack[Tuple[int, ...]], str, Unpack[Tuple[str, ...]]]) -> None: # E: More than one variable Unpack in a type is not allowed
...
reveal_type(bad2) # N: Revealed type is "def (x: tuple[builtins.int, Unpack[builtins.tuple[builtins.int, ...]], builtins.str])"
[builtins fixtures/tuple.pyi]
Expand Down Expand Up @@ -571,7 +571,7 @@ from typing_extensions import Unpack, TypeVarTuple

Ts = TypeVarTuple("Ts")
Us = TypeVarTuple("Us")
a: Callable[[Unpack[Ts], Unpack[Us]], int] # E: More than one Unpack in a type is not allowed
a: Callable[[Unpack[Ts], Unpack[Us]], int] # E: More than one variable Unpack in a type is not allowed
reveal_type(a) # N: Revealed type is "def [Ts, Us] (*Unpack[Ts`-1]) -> builtins.int"
b: Callable[[Unpack], int] # E: Unpack[...] requires exactly one type argument
reveal_type(b) # N: Revealed type is "def (*Any) -> builtins.int"
Expand Down Expand Up @@ -725,15 +725,15 @@ Ts = TypeVarTuple("Ts")
Us = TypeVarTuple("Us")
class G(Generic[Unpack[Ts]]): ...

A = Tuple[Unpack[Ts], Unpack[Us]] # E: More than one Unpack in a type is not allowed
A = Tuple[Unpack[Ts], Unpack[Us]] # E: More than one variable Unpack in a type is not allowed
x: A[int, str]
reveal_type(x) # N: Revealed type is "tuple[builtins.int, builtins.str]"

B = Callable[[Unpack[Ts], Unpack[Us]], int] # E: More than one Unpack in a type is not allowed
B = Callable[[Unpack[Ts], Unpack[Us]], int] # E: More than one variable Unpack in a type is not allowed
y: B[int, str]
reveal_type(y) # N: Revealed type is "def (builtins.int, builtins.str) -> builtins.int"

C = G[Unpack[Ts], Unpack[Us]] # E: More than one Unpack in a type is not allowed
C = G[Unpack[Ts], Unpack[Us]] # E: More than one variable Unpack in a type is not allowed
z: C[int, str]
reveal_type(z) # N: Revealed type is "__main__.G[builtins.int, builtins.str]"
[builtins fixtures/tuple.pyi]
Expand Down Expand Up @@ -2223,12 +2223,12 @@ cb2(1, 2, 3, a="a", b="b")
cb2(1, a="a", b="b") # E: Too few arguments
cb2(1, 2, 3, a="a") # E: Missing named argument "b"

bad1: Callable[[Unpack[Ints], Unpack[Ints]], None] # E: More than one Unpack in a type is not allowed
bad1: Callable[[Unpack[Ints], Unpack[Ints]], None] # E: More than one variable Unpack in a type is not allowed
reveal_type(bad1) # N: Revealed type is "def (*builtins.int)"
bad2: Callable[[Unpack[Keywords], Unpack[Keywords]], None] # E: "Keywords" cannot be unpacked (must be tuple or TypeVarTuple)
reveal_type(bad2) # N: Revealed type is "def (*Any, **Unpack[TypedDict('__main__.Keywords', {'a': builtins.str, 'b': builtins.str})])"
bad3: Callable[[Unpack[Keywords], Unpack[Ints]], None] # E: "Keywords" cannot be unpacked (must be tuple or TypeVarTuple) \
# E: More than one Unpack in a type is not allowed
# E: More than one variable Unpack in a type is not allowed
reveal_type(bad3) # N: Revealed type is "def (*Any)"
[builtins fixtures/dict.pyi]
[typing fixtures/typing-typeddict.pyi]
Expand Down
Loading