From 0b7966351ae2c06701daa6ea9640a87d93bb57b6 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Sun, 9 Aug 2026 23:30:15 -0700 Subject: [PATCH] Fix crash when unpacking return value from overload Fixes #21824 Fixes #19920 Closes #19921 Note that ilevkivskyi has a suggestion to change overload inference here: https://github.com/python/mypy/issues/19920#issuecomment-3341557826 While that is right, it is a little separate, and I think it is okay to remove the crash given that it now affects numpy and has been reported in other contexts too --- mypy/checker.py | 6 ++++-- test-data/unit/check-tuples.test | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 813939ca49646..7d356d30bb123 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4409,8 +4409,10 @@ def check_multi_assignment_from_tuple( # inferred return type for an overloaded function # to be ambiguous. return - assert isinstance(reinferred_rvalue_type, TupleType) - rvalue_type = reinferred_rvalue_type + if isinstance(reinferred_rvalue_type, TupleType): + # This branch will usually be taken, but in some cases context can + # e.g. select a different overload + rvalue_type = reinferred_rvalue_type left_rv_types, star_rv_types, right_rv_types = self.split_around_star( rvalue_type.items, star_index, len(lvalues) diff --git a/test-data/unit/check-tuples.test b/test-data/unit/check-tuples.test index bfbd2e631f5d8..79c6f630f4d98 100644 --- a/test-data/unit/check-tuples.test +++ b/test-data/unit/check-tuples.test @@ -426,6 +426,42 @@ class A: pass class B: pass [builtins fixtures/tuple.pyi] +[case testMultipleAssignmentWithOverloadReinferredAsHomogeneousTuple] +from typing import Any, TypeVar, overload + +T = TypeVar("T") + +@overload +def f(value: T) -> tuple[T, int]: ... +@overload +def f(*values: object) -> tuple[Any, ...]: ... +def f(*values: object, **kwargs: object) -> object: ... + +def g() -> None: + first: str + first, second = f(1) # E: Incompatible types in assignment (expression has type "int", variable has type "str") + reveal_type(second) # N: Revealed type is "builtins.int" + + last: str + _, last = f(1) # E: Incompatible types in assignment (expression has type "int", variable has type "str") +[builtins fixtures/tuple.pyi] + +[case testMultipleAssignmentWithOverloadReinferredAsNonTuple] +from typing import TypeVar, overload + +T = TypeVar("T") + +@overload +def f(value: T) -> tuple[T]: ... +@overload +def f(*values: object) -> int: ... +def f(*values: object, **kwargs: object) -> object: ... + +def g() -> None: + value: str + (value,) = f(1) # E: Incompatible types in assignment (expression has type "int", variable has type "str") +[builtins fixtures/tuple.pyi] + [case testMultipleAssignmentWithSquareBracketTuples] # flags: --no-strict-optional from typing import Tuple