Skip to content

Commit df070ec

Browse files
committed
Improve the support for promotions inside unions.
1 parent 55c4067 commit df070ec

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

mypy/meet.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from itertools import product
34
from typing import Callable
45

56
from mypy import join
@@ -130,16 +131,23 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type:
130131
if isinstance(declared, UnionType):
131132
return make_simplified_union(
132133
[
133-
narrow_declared_type(x, narrowed)
134-
for x in declared.relevant_items()
134+
narrow_declared_type(d, n)
135+
for d, n in product(
136+
declared.relevant_items(),
137+
narrowed.relevant_items() if isinstance(narrowed, UnionType) else (narrowed,),
138+
)
135139
# This (ugly) special-casing is needed to support checking
136140
# branches like this:
137141
# x: Union[float, complex]
138142
# if isinstance(x, int):
139143
# ...
144+
# And assignments like this:
145+
# x: float | None
146+
# y: int | None
147+
# x = y
140148
if (
141-
is_overlapping_types(x, narrowed, ignore_promotions=True)
142-
or is_subtype(narrowed, x, ignore_promotions=False)
149+
is_overlapping_types(d, n, ignore_promotions=True)
150+
or is_subtype(n, d, ignore_promotions=False)
143151
)
144152
]
145153
)

test-data/unit/check-narrowing.test

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,6 +2453,39 @@ while x is not None and b():
24532453

24542454
[builtins fixtures/primitives.pyi]
24552455

2456+
[case testNarrowPromotionsInsideUnions1]
2457+
2458+
from typing import Union
2459+
2460+
x: Union[str, float, None]
2461+
y: Union[int, str]
2462+
x = y
2463+
reveal_type(x) # N: Revealed type is "Union[builtins.str, builtins.int]"
2464+
z: Union[complex, str]
2465+
z = x
2466+
reveal_type(z) # N: Revealed type is "Union[builtins.int, builtins.str]"
2467+
2468+
[builtins fixtures/primitives.pyi]
2469+
2470+
[case testNarrowPromotionsInsideUnions2]
2471+
# flags: --warn-unreachable
2472+
2473+
from typing import Optional
2474+
2475+
def b() -> bool: ...
2476+
def i() -> int: ...
2477+
x: Optional[float]
2478+
2479+
while b():
2480+
x = None
2481+
while b():
2482+
reveal_type(x) # N: Revealed type is "Union[builtins.int, None]"
2483+
if x is None or b():
2484+
x = i()
2485+
reveal_type(x) # N: Revealed type is "builtins.int"
2486+
2487+
[builtins fixtures/bool.pyi]
2488+
24562489
[case testNarrowingTypeVarMultiple]
24572490
from typing import TypeVar
24582491

0 commit comments

Comments
 (0)