diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index e7c2cba3fc55..d59c20c4605a 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -6297,7 +6297,13 @@ def narrow_type_from_binder( known_type, restriction, prohibit_none_typevar_overlap=True ): return None - return narrow_declared_type(known_type, restriction) + narrowed = narrow_declared_type(known_type, restriction) + if isinstance(get_proper_type(narrowed), UninhabitedType): + # If we hit this case, it means that we can't reliably mark the code as + # unreachable, but the resulting type can't be expressed in type system. + # Falling back to restriction is more intuitive in most cases. + return restriction + return narrowed return known_type def has_abstract_type_part(self, caller_type: ProperType, callee_type: ProperType) -> bool: diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index 49140bf52b8d..058db1ea8197 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -1812,9 +1812,9 @@ reveal_type(fm) # N: Revealed type is "__main__.FooMetaclass" if issubclass(fm, Foo): reveal_type(fm) # N: Revealed type is "Type[__main__.Foo]" if issubclass(fm, Bar): - reveal_type(fm) # N: Revealed type is "Never" + reveal_type(fm) # N: Revealed type is "Type[__main__.Bar]" if issubclass(fm, Baz): - reveal_type(fm) # N: Revealed type is "Never" + reveal_type(fm) # N: Revealed type is "Type[__main__.Baz]" [builtins fixtures/isinstance.pyi] [case testIsinstanceAndNarrowTypeVariable] diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test index 1856ca26f736..dc2cfd46d9ad 100644 --- a/test-data/unit/check-narrowing.test +++ b/test-data/unit/check-narrowing.test @@ -1284,7 +1284,7 @@ def f(t: Type[T], a: A, b: B) -> None: reveal_type(a) # N: Revealed type is "__main__.A" if type(b) is t: - reveal_type(b) # N: Revealed type is "Never" + reveal_type(b) # N: Revealed type is "T`-1" else: reveal_type(b) # N: Revealed type is "__main__.B" @@ -2413,3 +2413,14 @@ def foo(x: T) -> T: reveal_type(x) # N: Revealed type is "T`-1" return x [builtins fixtures/isinstance.pyi] + +[case testDoNotNarrowToNever] +def any(): + return 1 + +def f() -> None: + x = "a" + x = any() + assert isinstance(x, int) + reveal_type(x) # N: Revealed type is "builtins.int" +[builtins fixtures/isinstance.pyi] diff --git a/test-data/unit/check-python310.test b/test-data/unit/check-python310.test index 3774abfc548b..c2e2e5bddb34 100644 --- a/test-data/unit/check-python310.test +++ b/test-data/unit/check-python310.test @@ -1347,7 +1347,7 @@ m: str match m: case a if a := 1: # E: Incompatible types in assignment (expression has type "int", variable has type "str") - reveal_type(a) # N: Revealed type is "Never" + reveal_type(a) # N: Revealed type is "Literal[1]?" [case testMatchAssigningPatternGuard] m: str