Skip to content

Commit ca11151

Browse files
committed
Implement or-ing typemaps for Never-based unreachability
1 parent 72349c0 commit ca11151

File tree

3 files changed

+9
-8
lines changed

3 files changed

+9
-8
lines changed

mypy/checker.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8136,6 +8136,7 @@ def and_conditional_maps(m1: TypeMap, m2: TypeMap, use_meet: bool = False) -> Ty
81368136
result = m2.copy()
81378137
m2_keys = {literal_hash(n2) for n2 in m2}
81388138
for n1 in m1:
8139+
# TODO: should this check for UninhabitedType as well as AnyType?
81398140
if literal_hash(n1) not in m2_keys or isinstance(get_proper_type(m1[n1]), AnyType):
81408141
result[n1] = m1[n1]
81418142
if use_meet:
@@ -8156,9 +8157,9 @@ def or_conditional_maps(m1: TypeMap, m2: TypeMap, coalesce_any: bool = False) ->
81568157
joining restrictions.
81578158
"""
81588159

8159-
if m1 is None:
8160+
if m1 is None or any(isinstance(get_proper_type(t1), UninhabitedType) for t1 in m1.values()):
81608161
return m2
8161-
if m2 is None:
8162+
if m2 is None or any(isinstance(get_proper_type(t2), UninhabitedType) for t2 in m2.values()):
81628163
return m1
81638164
# Both conditions can be true. Combine information about
81648165
# expressions whose type is refined by both conditions. (We do not

test-data/unit/check-narrowing.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -741,8 +741,6 @@ def test3(switch: FlipFlopEnum) -> None:
741741
assert switch.state is State.B # E: Non-overlapping identity check (left operand type: "Literal[State.A]", right operand type: "Literal[State.B]")
742742
reveal_type(switch.state) # E: Statement is unreachable \
743743
# N: Revealed type is "Never"
744-
745-
746744
[builtins fixtures/primitives.pyi]
747745

748746
[case testNarrowingEqualityRequiresExplicitStrLiteral]
@@ -939,7 +937,7 @@ if a == a == b:
939937
reveal_type(b) # N: Revealed type is "Literal[1]"
940938
else:
941939
reveal_type(a) # N: Revealed type is "Literal[1]"
942-
reveal_type(b) # N: Revealed type is "Union[Literal[1], Literal[2]]"
940+
reveal_type(b) # N: Revealed type is "Literal[2]"
943941

944942
# In this case, it's ok for 'b' to narrow down to Literal[1] in the else case
945943
# since that's the only way 'b == 2' can be false
@@ -1336,6 +1334,7 @@ else:
13361334
[typing fixtures/typing-typeddict.pyi]
13371335

13381336
[case testNarrowingRuntimeCover]
1337+
# flags: --warn-unreachable
13391338
from typing import Dict, List, Union
13401339

13411340
def unreachable(x: Union[str, List[str]]) -> None:
@@ -1344,7 +1343,8 @@ def unreachable(x: Union[str, List[str]]) -> None:
13441343
elif isinstance(x, list):
13451344
reveal_type(x) # N: Revealed type is "builtins.list[builtins.str]"
13461345
else:
1347-
reveal_type(x) # No output: this branch is unreachable # N: Revealed type is "Never"
1346+
reveal_type(x) # E: Statement is unreachable \
1347+
# N: Revealed type is "Never"
13481348

13491349
def all_parts_covered(x: Union[str, List[str], List[int], int]) -> None:
13501350
if isinstance(x, str):

test-data/unit/check-python310.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2319,7 +2319,7 @@ def f3(e: int | str | bytes) -> int:
23192319
return 0 # E: Statement is unreachable
23202320
case str(x):
23212321
return 0
2322-
reveal_type(e) # N: Revealed type is "Union[builtins.int, builtins.bytes]"
2322+
reveal_type(e) # N: Revealed type is "builtins.bytes"
23232323
return 0
23242324

23252325
def f4(e: int | str | bytes) -> int:
@@ -2330,7 +2330,7 @@ def f4(e: int | str | bytes) -> int:
23302330
return 0 # E: Statement is unreachable
23312331
case x if isinstance(x, str):
23322332
return 0
2333-
reveal_type(e) # N: Revealed type is "Union[builtins.int, builtins.str, builtins.bytes]"
2333+
reveal_type(e) # N: Revealed type is "Union[builtins.int, builtins.bytes]"
23342334
return 0
23352335

23362336
[builtins fixtures/primitives.pyi]

0 commit comments

Comments
 (0)