Skip to content

Commit

Permalink
Fix crash with type alias to `Callable[[Unpack[Tuple[Any, ...]]], Any…
Browse files Browse the repository at this point in the history
…]` (#16541)

Fixes #16533
  • Loading branch information
AlexWaygood authored Dec 12, 2023
1 parent 0567da9 commit 5fa9569
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 11 deletions.
28 changes: 17 additions & 11 deletions mypy/expandtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,18 +307,24 @@ def interpolate_args_for_unpack(self, t: CallableType, var_arg: UnpackType) -> l
suffix = self.expand_types(t.arg_types[star_index + 1 :])

var_arg_type = get_proper_type(var_arg.type)
# We have something like Unpack[Tuple[Unpack[Ts], X1, X2]]
if isinstance(var_arg_type, TupleType):
expanded_tuple = var_arg_type.accept(self)
assert isinstance(expanded_tuple, ProperType) and isinstance(expanded_tuple, TupleType)
expanded_items = expanded_tuple.items
fallback = var_arg_type.partial_fallback
if isinstance(var_arg_type, Instance):
# we have something like Unpack[Tuple[Any, ...]]
new_unpack = var_arg
else:
# We have plain Unpack[Ts]
assert isinstance(var_arg_type, TypeVarTupleType)
fallback = var_arg_type.tuple_fallback
expanded_items = self.expand_unpack(var_arg)
new_unpack = UnpackType(TupleType(expanded_items, fallback))
if isinstance(var_arg_type, TupleType):
# We have something like Unpack[Tuple[Unpack[Ts], X1, X2]]
expanded_tuple = var_arg_type.accept(self)
assert isinstance(expanded_tuple, ProperType) and isinstance(
expanded_tuple, TupleType
)
expanded_items = expanded_tuple.items
fallback = var_arg_type.partial_fallback
else:
# We have plain Unpack[Ts]
assert isinstance(var_arg_type, TypeVarTupleType), type(var_arg_type)
fallback = var_arg_type.tuple_fallback
expanded_items = self.expand_unpack(var_arg)
new_unpack = UnpackType(TupleType(expanded_items, fallback))
return prefix + [new_unpack] + suffix

def visit_callable_type(self, t: CallableType) -> CallableType:
Expand Down
42 changes: 42 additions & 0 deletions test-data/unit/check-typevar-tuple.test
Original file line number Diff line number Diff line change
Expand Up @@ -2235,3 +2235,45 @@ z: Tuple[int, Unpack[Tuple[int, ...]]] = (1,)
w: Tuple[int, Unpack[Tuple[int, ...]]] = (1, *[2, 3, 4])
t: Tuple[int, Unpack[Tuple[int, ...]]] = (1, *(2, 3, 4))
[builtins fixtures/tuple.pyi]

[case testAliasToCallableWithUnpack]
from typing import Any, Callable, Tuple, Unpack

_CallableValue = Callable[[Unpack[Tuple[Any, ...]]], Any]
def higher_order(f: _CallableValue) -> None: ...

def good1(*args: int) -> None: ...
def good2(*args: str) -> int: ...

def bad1(a: str, b: int, /) -> None: ...
def bad2(c: bytes, *args: int) -> str: ...
def bad3(*, d: str) -> int: ...
def bad4(**kwargs: None) -> None: ...

higher_order(good1)
higher_order(good2)

higher_order(bad1) # E: Argument 1 to "higher_order" has incompatible type "Callable[[str, int], None]"; expected "Callable[[VarArg(Any)], Any]"
higher_order(bad2) # E: Argument 1 to "higher_order" has incompatible type "Callable[[bytes, VarArg(int)], str]"; expected "Callable[[VarArg(Any)], Any]"
higher_order(bad3) # E: Argument 1 to "higher_order" has incompatible type "Callable[[NamedArg(str, 'd')], int]"; expected "Callable[[VarArg(Any)], Any]"
higher_order(bad4) # E: Argument 1 to "higher_order" has incompatible type "Callable[[KwArg(None)], None]"; expected "Callable[[VarArg(Any)], Any]"
[builtins fixtures/tuple.pyi]

[case testAliasToCallableWithUnpack2]
from typing import Any, Callable, Tuple, Unpack

_CallableValue = Callable[[int, str, Unpack[Tuple[Any, ...]], int], Any]
def higher_order(f: _CallableValue) -> None: ...

def good(a: int, b: str, *args: Unpack[Tuple[Unpack[Tuple[Any, ...]], int]]) -> int: ...
def bad1(a: str, b: int, /) -> None: ...
def bad2(c: bytes, *args: int) -> str: ...
def bad3(*, d: str) -> int: ...
def bad4(**kwargs: None) -> None: ...

higher_order(good)
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]"
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]"
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]"
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]"
[builtins fixtures/tuple.pyi]

0 comments on commit 5fa9569

Please sign in to comment.