Skip to content

Commit 60d30e3

Browse files
AlexWaygoodwesleywright
authored andcommitted
Fix crash with type alias to Callable[[Unpack[Tuple[Any, ...]]], Any] (#16541)
Fixes #16533
1 parent f53f422 commit 60d30e3

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

mypy/expandtype.py

+17-11
Original file line numberDiff line numberDiff line change
@@ -307,18 +307,24 @@ def interpolate_args_for_unpack(self, t: CallableType, var_arg: UnpackType) -> l
307307
suffix = self.expand_types(t.arg_types[star_index + 1 :])
308308

309309
var_arg_type = get_proper_type(var_arg.type)
310-
# We have something like Unpack[Tuple[Unpack[Ts], X1, X2]]
311-
if isinstance(var_arg_type, TupleType):
312-
expanded_tuple = var_arg_type.accept(self)
313-
assert isinstance(expanded_tuple, ProperType) and isinstance(expanded_tuple, TupleType)
314-
expanded_items = expanded_tuple.items
315-
fallback = var_arg_type.partial_fallback
310+
if isinstance(var_arg_type, Instance):
311+
# we have something like Unpack[Tuple[Any, ...]]
312+
new_unpack = var_arg
316313
else:
317-
# We have plain Unpack[Ts]
318-
assert isinstance(var_arg_type, TypeVarTupleType)
319-
fallback = var_arg_type.tuple_fallback
320-
expanded_items = self.expand_unpack(var_arg)
321-
new_unpack = UnpackType(TupleType(expanded_items, fallback))
314+
if isinstance(var_arg_type, TupleType):
315+
# We have something like Unpack[Tuple[Unpack[Ts], X1, X2]]
316+
expanded_tuple = var_arg_type.accept(self)
317+
assert isinstance(expanded_tuple, ProperType) and isinstance(
318+
expanded_tuple, TupleType
319+
)
320+
expanded_items = expanded_tuple.items
321+
fallback = var_arg_type.partial_fallback
322+
else:
323+
# We have plain Unpack[Ts]
324+
assert isinstance(var_arg_type, TypeVarTupleType), type(var_arg_type)
325+
fallback = var_arg_type.tuple_fallback
326+
expanded_items = self.expand_unpack(var_arg)
327+
new_unpack = UnpackType(TupleType(expanded_items, fallback))
322328
return prefix + [new_unpack] + suffix
323329

324330
def visit_callable_type(self, t: CallableType) -> CallableType:

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

+42
Original file line numberDiff line numberDiff line change
@@ -2235,3 +2235,45 @@ z: Tuple[int, Unpack[Tuple[int, ...]]] = (1,)
22352235
w: Tuple[int, Unpack[Tuple[int, ...]]] = (1, *[2, 3, 4])
22362236
t: Tuple[int, Unpack[Tuple[int, ...]]] = (1, *(2, 3, 4))
22372237
[builtins fixtures/tuple.pyi]
2238+
2239+
[case testAliasToCallableWithUnpack]
2240+
from typing import Any, Callable, Tuple, Unpack
2241+
2242+
_CallableValue = Callable[[Unpack[Tuple[Any, ...]]], Any]
2243+
def higher_order(f: _CallableValue) -> None: ...
2244+
2245+
def good1(*args: int) -> None: ...
2246+
def good2(*args: str) -> int: ...
2247+
2248+
def bad1(a: str, b: int, /) -> None: ...
2249+
def bad2(c: bytes, *args: int) -> str: ...
2250+
def bad3(*, d: str) -> int: ...
2251+
def bad4(**kwargs: None) -> None: ...
2252+
2253+
higher_order(good1)
2254+
higher_order(good2)
2255+
2256+
higher_order(bad1) # E: Argument 1 to "higher_order" has incompatible type "Callable[[str, int], None]"; expected "Callable[[VarArg(Any)], Any]"
2257+
higher_order(bad2) # E: Argument 1 to "higher_order" has incompatible type "Callable[[bytes, VarArg(int)], str]"; expected "Callable[[VarArg(Any)], Any]"
2258+
higher_order(bad3) # E: Argument 1 to "higher_order" has incompatible type "Callable[[NamedArg(str, 'd')], int]"; expected "Callable[[VarArg(Any)], Any]"
2259+
higher_order(bad4) # E: Argument 1 to "higher_order" has incompatible type "Callable[[KwArg(None)], None]"; expected "Callable[[VarArg(Any)], Any]"
2260+
[builtins fixtures/tuple.pyi]
2261+
2262+
[case testAliasToCallableWithUnpack2]
2263+
from typing import Any, Callable, Tuple, Unpack
2264+
2265+
_CallableValue = Callable[[int, str, Unpack[Tuple[Any, ...]], int], Any]
2266+
def higher_order(f: _CallableValue) -> None: ...
2267+
2268+
def good(a: int, b: str, *args: Unpack[Tuple[Unpack[Tuple[Any, ...]], int]]) -> int: ...
2269+
def bad1(a: str, b: int, /) -> None: ...
2270+
def bad2(c: bytes, *args: int) -> str: ...
2271+
def bad3(*, d: str) -> int: ...
2272+
def bad4(**kwargs: None) -> None: ...
2273+
2274+
higher_order(good)
2275+
higher_order(bad1) # E: Argument 1 to "higher_order" has incompatible type "Callable[[str, int], None]"; expected "Callable[[int, str, VarArg(Unpack[Tuple[Unpack[Tuple[Any, ...]], int]])], Any]"
2276+
higher_order(bad2) # E: Argument 1 to "higher_order" has incompatible type "Callable[[bytes, VarArg(int)], str]"; expected "Callable[[int, str, VarArg(Unpack[Tuple[Unpack[Tuple[Any, ...]], int]])], Any]"
2277+
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]"
2278+
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]"
2279+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)