Skip to content

Commit 344a84a

Browse files
committed
Fix bug in multiassign from union
1 parent 721facc commit 344a84a

File tree

4 files changed

+29
-2
lines changed

4 files changed

+29
-2
lines changed

mypy/checker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4001,7 +4001,7 @@ def check_multi_assignment_from_union(
40014001
for t, lv in zip(transposed, self.flatten_lvalues(lvalues)):
40024002
# We can access _type_maps directly since temporary type maps are
40034003
# only created within expressions.
4004-
t.append(self._type_maps[0].pop(lv, AnyType(TypeOfAny.special_form)))
4004+
t.append(self._type_maps[-1].pop(lv, AnyType(TypeOfAny.special_form)))
40054005
union_types = tuple(make_simplified_union(col) for col in transposed)
40064006
for expr, items in assignments.items():
40074007
# Bind a union of types collected in 'assignments' to every expression.

mypy/checkexpr.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5993,7 +5993,9 @@ def accept(
59935993
# Deeply nested generic calls can deteriorate performance dramatically.
59945994
# Although in most cases caching makes little difference, in worst case
59955995
# it avoids exponential complexity.
5996-
# TODO: figure out why caching within lambdas is fragile.
5996+
# We cannot use cache inside lambdas, because they skip immediate type
5997+
# context, and use enclosing one, see infer_lambda_type_using_context().
5998+
# TODO: consider using cache for more expression kinds.
59975999
elif isinstance(node, (CallExpr, ListExpr, TupleExpr)) and not (
59986000
self.in_lambda_expr or self.chk.current_node_deferred
59996001
):

test-data/unit/check-overloading.test

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6801,3 +6801,26 @@ class D(Generic[T]):
68016801
a: D[str] # E: Type argument "str" of "D" must be a subtype of "C"
68026802
reveal_type(a.f(1)) # N: Revealed type is "builtins.int"
68036803
reveal_type(a.f("x")) # N: Revealed type is "builtins.str"
6804+
6805+
[case testMultiAssignFromUnionInOverloadCached]
6806+
from typing import Iterable, overload, Union, Optional
6807+
6808+
@overload
6809+
def always_bytes(str_or_bytes: None) -> None: ...
6810+
@overload
6811+
def always_bytes(str_or_bytes: Union[str, bytes]) -> bytes: ...
6812+
def always_bytes(str_or_bytes: Union[None, str, bytes]) -> Optional[bytes]:
6813+
pass
6814+
6815+
class Headers:
6816+
def __init__(self, iter: Iterable[tuple[bytes, bytes]]) -> None: ...
6817+
6818+
headers: Union[Headers, dict[Union[str, bytes], Union[str, bytes]], Iterable[tuple[bytes, bytes]]]
6819+
6820+
if isinstance(headers, dict):
6821+
headers = Headers(
6822+
(always_bytes(k), always_bytes(v)) for k, v in headers.items()
6823+
)
6824+
6825+
reveal_type(headers) # N: Revealed type is "Union[__main__.Headers, typing.Iterable[tuple[builtins.bytes, builtins.bytes]]]"
6826+
[builtins fixtures/isinstancelist.pyi]

test-data/unit/fixtures/isinstancelist.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class bool(int): pass
2626
class str:
2727
def __add__(self, x: str) -> str: pass
2828
def __getitem__(self, x: int) -> str: pass
29+
class bytes: pass
2930

3031
T = TypeVar('T')
3132
KT = TypeVar('KT')
@@ -52,6 +53,7 @@ class dict(Mapping[KT, VT]):
5253
def __setitem__(self, k: KT, v: VT) -> None: pass
5354
def __iter__(self) -> Iterator[KT]: pass
5455
def update(self, a: Mapping[KT, VT]) -> None: pass
56+
def items(self) -> Iterable[Tuple[KT, VT]]: pass
5557

5658
class set(Generic[T]):
5759
def __iter__(self) -> Iterator[T]: pass

0 commit comments

Comments
 (0)