Skip to content

Commit 46ce325

Browse files
committed
Fix crash when inferring multiple assignment with overloaded function (#10689)
When using lvalue context to re-infer call to an overloaded function, the inferred tuple type can switch to Any. Defensively accept this. It probably means that an Any component in argument types causes ambiguity. Fixes #10653.
1 parent 96366d1 commit 46ce325

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

mypy/checker.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2695,8 +2695,13 @@ def check_multi_assignment_from_tuple(self, lvalues: List[Lvalue], rvalue: Expre
26952695
reinferred_rvalue_type, context,
26962696
infer_lvalue_type)
26972697
return
2698-
if isinstance(reinferred_rvalue_type, AnyType) and self.current_node_deferred:
2699-
# Doing more inference in deferred nodes can be hard, so give up for now.
2698+
if isinstance(reinferred_rvalue_type, AnyType):
2699+
# We can get Any if the current node is
2700+
# deferred. Doing more inference in deferred nodes
2701+
# is hard, so give up for now. We can also get
2702+
# here if reinferring types above changes the
2703+
# inferred return type for an overloaded function
2704+
# to be ambiguous.
27002705
return
27012706
assert isinstance(reinferred_rvalue_type, TupleType)
27022707
rvalue_type = reinferred_rvalue_type

test-data/unit/check-async-await.test

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,3 +758,44 @@ class Foo(Generic[T]):
758758

759759
[builtins fixtures/async_await.pyi]
760760
[typing fixtures/typing-async.pyi]
761+
762+
[case testAwaitOverloadSpecialCase]
763+
from typing import Any, Awaitable, Iterable, overload, Tuple, List, TypeVar, Generic
764+
765+
T = TypeVar("T")
766+
FT = TypeVar("FT", bound='Future[Any]')
767+
768+
class Future(Awaitable[T], Iterable[T]):
769+
pass
770+
771+
class Task(Future[T]):
772+
pass
773+
774+
@overload
775+
def wait(fs: Iterable[FT]) -> Future[Tuple[List[FT], List[FT]]]: ... \
776+
# E: Overloaded function signatures 1 and 2 overlap with incompatible return types
777+
@overload
778+
def wait(fs: Iterable[Awaitable[T]]) -> Future[Tuple[List[Task[T]], List[Task[T]]]]: ...
779+
def wait(fs: Any) -> Any:
780+
pass
781+
782+
async def imprecise1(futures: Iterable[Task[Any]]) -> None:
783+
done: Any
784+
pending: Any
785+
done, pending = await wait(futures)
786+
reveal_type(done) # N: Revealed type is "Any"
787+
788+
async def imprecise2(futures: Iterable[Awaitable[Any]]) -> None:
789+
done, pending = await wait(futures)
790+
reveal_type(done) # N: Revealed type is "builtins.list[__main__.Task[Any]]"
791+
792+
async def precise1(futures: Iterable[Future[int]]) -> None:
793+
done, pending = await wait(futures)
794+
reveal_type(done) # N: Revealed type is "builtins.list[__main__.Future[builtins.int]]"
795+
796+
async def precise2(futures: Iterable[Awaitable[int]]) -> None:
797+
done, pending = await wait(futures)
798+
reveal_type(done) # N: Revealed type is "builtins.list[__main__.Task[builtins.int]]"
799+
800+
[builtins fixtures/async_await.pyi]
801+
[typing fixtures/typing-async.pyi]

0 commit comments

Comments
 (0)