File tree Expand file tree Collapse file tree 2 files changed +47
-4
lines changed Expand file tree Collapse file tree 2 files changed +47
-4
lines changed Original file line number Diff line number Diff line change @@ -128,18 +128,28 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type:
128128 if declared == narrowed :
129129 return original_declared
130130 if isinstance (declared , UnionType ):
131+ declared_items = declared .relevant_items ()
132+ if isinstance (narrowed , UnionType ):
133+ narrowed_items = narrowed .relevant_items ()
134+ else :
135+ narrowed_items = [narrowed ]
131136 return make_simplified_union (
132137 [
133- narrow_declared_type (x , narrowed )
134- for x in declared .relevant_items ()
138+ narrow_declared_type (d , n )
139+ for d in declared_items
140+ for n in narrowed_items
135141 # This (ugly) special-casing is needed to support checking
136142 # branches like this:
137143 # x: Union[float, complex]
138144 # if isinstance(x, int):
139145 # ...
146+ # And assignments like this:
147+ # x: float | None
148+ # y: int | None
149+ # x = y
140150 if (
141- is_overlapping_types (x , narrowed , ignore_promotions = True )
142- or is_subtype (narrowed , x , ignore_promotions = False )
151+ is_overlapping_types (d , n , ignore_promotions = True )
152+ or is_subtype (n , d , ignore_promotions = False )
143153 )
144154 ]
145155 )
Original file line number Diff line number Diff line change @@ -2446,6 +2446,39 @@ while x is not None and b():
24462446 x = f()
24472447[builtins fixtures/primitives.pyi]
24482448
2449+ [case testNarrowPromotionsInsideUnions1]
2450+
2451+ from typing import Union
2452+
2453+ x: Union[str, float, None]
2454+ y: Union[int, str]
2455+ x = y
2456+ reveal_type(x) # N: Revealed type is "Union[builtins.str, builtins.int]"
2457+ z: Union[complex, str]
2458+ z = x
2459+ reveal_type(z) # N: Revealed type is "Union[builtins.int, builtins.str]"
2460+
2461+ [builtins fixtures/primitives.pyi]
2462+
2463+ [case testNarrowPromotionsInsideUnions2]
2464+ # flags: --warn-unreachable
2465+
2466+ from typing import Optional
2467+
2468+ def b() -> bool: ...
2469+ def i() -> int: ...
2470+ x: Optional[float]
2471+
2472+ while b():
2473+ x = None
2474+ while b():
2475+ reveal_type(x) # N: Revealed type is "Union[None, builtins.int]"
2476+ if x is None or b():
2477+ x = i()
2478+ reveal_type(x) # N: Revealed type is "builtins.int"
2479+
2480+ [builtins fixtures/bool.pyi]
2481+
24492482[case testAvoidFalseUnreachableInFinally]
24502483# flags: --allow-redefinition-new --local-partial-types --warn-unreachable
24512484def f() -> None:
You can’t perform that action at this time.
0 commit comments