Skip to content

Commit

Permalink
Fix crash for callable with *args and suffix against Any (#18781)
Browse files Browse the repository at this point in the history
Fixes #18780

Fix is trivial: handle a missing case. Note I re-use
`flatten_nested_tuples()` out of laziness. In theory, there should be at
most one level of nesting at this point, after which we should put an
assert (and IIRC we do something like this in other places). But I think
it is not worth the effort here, as this is a quite niche edge case
anyway.
  • Loading branch information
ilevkivskyi authored Mar 11, 2025
1 parent a4313e4 commit 662bbeb
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 2 deletions.
5 changes: 4 additions & 1 deletion mypy/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
UnionType,
UnpackType,
find_unpack_in_list,
flatten_nested_tuples,
get_proper_type,
has_recursive_types,
has_type_vars,
Expand Down Expand Up @@ -1347,7 +1348,9 @@ def visit_type_alias_type(self, template: TypeAliasType) -> list[Constraint]:

def infer_against_any(self, types: Iterable[Type], any_type: AnyType) -> list[Constraint]:
res: list[Constraint] = []
for t in types:
# Some items may be things like `*Tuple[*Ts, T]` for example from callable types with
# suffix after *arg, so flatten them.
for t in flatten_nested_tuples(types):
if isinstance(t, UnpackType):
if isinstance(t.type, TypeVarTupleType):
res.append(Constraint(t.type, self.direction, any_type))
Expand Down
2 changes: 1 addition & 1 deletion mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3726,7 +3726,7 @@ def find_unpack_in_list(items: Sequence[Type]) -> int | None:
return unpack_index


def flatten_nested_tuples(types: Sequence[Type]) -> list[Type]:
def flatten_nested_tuples(types: Iterable[Type]) -> list[Type]:
"""Recursively flatten TupleTypes nested with Unpack.
For example this will transform
Expand Down
12 changes: 12 additions & 0 deletions test-data/unit/check-typevar-tuple.test
Original file line number Diff line number Diff line change
Expand Up @@ -2606,3 +2606,15 @@ def test(xs: tuple[Unpack[Ts]], xsi: tuple[int, Unpack[Ts]]) -> None:
reveal_type(join(xsi, ai)) # N: Revealed type is "Tuple[builtins.int, Unpack[builtins.tuple[Any, ...]]]"
reveal_type(join(ai, xsi)) # N: Revealed type is "Tuple[builtins.int, Unpack[builtins.tuple[Any, ...]]]"
[builtins fixtures/tuple.pyi]

[case testTypeVarTupleInferAgainstAnyCallableSuffix]
from typing import Any, Callable, TypeVar, TypeVarTuple

Ts = TypeVarTuple("Ts")
R = TypeVar("R")
def deco(func: Callable[[*Ts, int], R]) -> Callable[[*Ts], R]:
...

untyped: Any
reveal_type(deco(untyped)) # N: Revealed type is "def (*Any) -> Any"
[builtins fixtures/tuple.pyi]

0 comments on commit 662bbeb

Please sign in to comment.