From c8e1e3479fd0a98b6f417bd41231af8de9d90456 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Mon, 31 Mar 2025 00:22:06 +0100 Subject: [PATCH] Fix crash on type inference against non-normal callables --- mypy/constraints.py | 4 ++-- mypy/types.py | 2 +- test-data/unit/check-typevar-tuple.test | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/mypy/constraints.py b/mypy/constraints.py index e76f6cd639ad..079f6536ee20 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -1063,11 +1063,11 @@ def visit_callable_type(self, template: CallableType) -> list[Constraint]: # using e.g. callback protocols. # TODO: check that callables match? Ideally we should not infer constraints # callables that can never be subtypes of one another in given direction. - template = template.with_unpacked_kwargs() + template = template.with_unpacked_kwargs().with_normalized_var_args() extra_tvars = False if isinstance(self.actual, CallableType): res: list[Constraint] = [] - cactual = self.actual.with_unpacked_kwargs() + cactual = self.actual.with_unpacked_kwargs().with_normalized_var_args() param_spec = template.param_spec() template_ret_type, cactual_ret_type = template.ret_type, cactual.ret_type diff --git a/mypy/types.py b/mypy/types.py index 9dd0ef8552b9..41a958ae93cc 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -2210,7 +2210,7 @@ def with_normalized_var_args(self) -> Self: new_unpack = nested_unpacked.args[0] else: if not isinstance(nested_unpacked, TypeVarTupleType): - # We found a non-nomralized tuple type, this means this method + # We found a non-normalized tuple type, this means this method # is called during semantic analysis (e.g. from get_proper_type()) # there is no point in normalizing callables at this stage. return self diff --git a/test-data/unit/check-typevar-tuple.test b/test-data/unit/check-typevar-tuple.test index 57a96291b04a..d364439f22e9 100644 --- a/test-data/unit/check-typevar-tuple.test +++ b/test-data/unit/check-typevar-tuple.test @@ -2618,3 +2618,13 @@ 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] + +[case testNoCrashOnNonNormalUnpackInCallable] +from typing import Callable, Unpack, TypeVar + +T = TypeVar("T") +def fn(f: Callable[[*tuple[T]], int]) -> Callable[[*tuple[T]], int]: ... + +def test(*args: Unpack[tuple[T]]) -> int: ... +reveal_type(fn(test)) # N: Revealed type is "def [T] (T`1) -> builtins.int" +[builtins fixtures/tuple.pyi]