Skip to content

Commit c724a6a

Browse files
authored
Do not narrow types to Never with binder (#18972)
Fixes #18967 Fixes #16494 Fixes #15793 Fixes #12949 As you can see from updated test cases, it is kind of gray area, so whether we go this way will depend on the `mypy_primer` results (and also potentially on Dropbox internal code bases, where the above issue may cause problems).
1 parent 70ee798 commit c724a6a

File tree

4 files changed

+22
-5
lines changed

4 files changed

+22
-5
lines changed

mypy/checkexpr.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6297,7 +6297,13 @@ def narrow_type_from_binder(
62976297
known_type, restriction, prohibit_none_typevar_overlap=True
62986298
):
62996299
return None
6300-
return narrow_declared_type(known_type, restriction)
6300+
narrowed = narrow_declared_type(known_type, restriction)
6301+
if isinstance(get_proper_type(narrowed), UninhabitedType):
6302+
# If we hit this case, it means that we can't reliably mark the code as
6303+
# unreachable, but the resulting type can't be expressed in type system.
6304+
# Falling back to restriction is more intuitive in most cases.
6305+
return restriction
6306+
return narrowed
63016307
return known_type
63026308

63036309
def has_abstract_type_part(self, caller_type: ProperType, callee_type: ProperType) -> bool:

test-data/unit/check-isinstance.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,9 +1812,9 @@ reveal_type(fm) # N: Revealed type is "__main__.FooMetaclass"
18121812
if issubclass(fm, Foo):
18131813
reveal_type(fm) # N: Revealed type is "Type[__main__.Foo]"
18141814
if issubclass(fm, Bar):
1815-
reveal_type(fm) # N: Revealed type is "Never"
1815+
reveal_type(fm) # N: Revealed type is "Type[__main__.Bar]"
18161816
if issubclass(fm, Baz):
1817-
reveal_type(fm) # N: Revealed type is "Never"
1817+
reveal_type(fm) # N: Revealed type is "Type[__main__.Baz]"
18181818
[builtins fixtures/isinstance.pyi]
18191819

18201820
[case testIsinstanceAndNarrowTypeVariable]

test-data/unit/check-narrowing.test

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,7 @@ def f(t: Type[T], a: A, b: B) -> None:
12841284
reveal_type(a) # N: Revealed type is "__main__.A"
12851285

12861286
if type(b) is t:
1287-
reveal_type(b) # N: Revealed type is "Never"
1287+
reveal_type(b) # N: Revealed type is "T`-1"
12881288
else:
12891289
reveal_type(b) # N: Revealed type is "__main__.B"
12901290

@@ -2413,3 +2413,14 @@ def foo(x: T) -> T:
24132413
reveal_type(x) # N: Revealed type is "T`-1"
24142414
return x
24152415
[builtins fixtures/isinstance.pyi]
2416+
2417+
[case testDoNotNarrowToNever]
2418+
def any():
2419+
return 1
2420+
2421+
def f() -> None:
2422+
x = "a"
2423+
x = any()
2424+
assert isinstance(x, int)
2425+
reveal_type(x) # N: Revealed type is "builtins.int"
2426+
[builtins fixtures/isinstance.pyi]

test-data/unit/check-python310.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1347,7 +1347,7 @@ m: str
13471347

13481348
match m:
13491349
case a if a := 1: # E: Incompatible types in assignment (expression has type "int", variable has type "str")
1350-
reveal_type(a) # N: Revealed type is "Never"
1350+
reveal_type(a) # N: Revealed type is "Literal[1]?"
13511351

13521352
[case testMatchAssigningPatternGuard]
13531353
m: str

0 commit comments

Comments
 (0)