diff --git a/mypy/checker.py b/mypy/checker.py index 396aee8d2503..fcdd56c57bce 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -8321,6 +8321,18 @@ def conditional_types( proposed_type = make_simplified_union(proposed_items) if isinstance(proper_type, AnyType): + # When current type is Any, we need to be careful about narrowing. + # For isinstance checks, proposed_type is typically an Instance, and we should narrow. + # For identity checks (is/is not), proposed_type is typically a FunctionLike (type object), + # and we should NOT narrow because Any could be anything. + proposed_proper = proposed_type + if ( + isinstance(proposed_proper, (FunctionLike, Overloaded)) + and proposed_proper.is_type_obj() + ): + # Identity check against a type object - don't narrow Any + return current_type, current_type + # isinstance check or other cases - narrow as before return proposed_type, current_type if isinstance(proposed_type, AnyType): # We don't really know much about the proposed type, so we shouldn't diff --git a/test-data/unit/check-narrowing.test b/test-data/unit/check-narrowing.test index 117d0e72ed79..c4eef23bf059 100644 --- a/test-data/unit/check-narrowing.test +++ b/test-data/unit/check-narrowing.test @@ -3439,12 +3439,12 @@ else: from typing import Any def foo(y: object): - if y.__class__ == int: + if y.__class__ == int: # E: "object" has no attribute "__class__" reveal_type(y) # N: Revealed type is "builtins.int" else: reveal_type(y) # N: Revealed type is "builtins.object" - if y.__class__ is int: + if y.__class__ is int: # E: "object" has no attribute "__class__" reveal_type(y) # N: Revealed type is "builtins.int" else: reveal_type(y) # N: Revealed type is "builtins.object" @@ -3460,6 +3460,36 @@ def bar(y: Any): reveal_type(y) # N: Revealed type is "builtins.int" else: reveal_type(y) # N: Revealed type is "Any" + + +[case testAnyIdentityTypeObjectNoNarrowing] +# flags: --strict-equality +from typing import Any + +class A: + foo: Any + +def f(x: Any, a: A) -> None: + if x is list: + reveal_type(x) # N: Revealed type is "Any" + else: + reveal_type(x) # N: Revealed type is "Any" + + if x is not list: + reveal_type(x) # N: Revealed type is "Any" + else: + reveal_type(x) # N: Revealed type is "Any" + + if a.foo is list: + reveal_type(a.foo) # N: Revealed type is "Any" + else: + reveal_type(a.foo) # N: Revealed type is "Any" + + if a.foo is not list: + a.foo = [] + + reveal_type(a.foo) # N: Revealed type is "Any" + a.foo.append(1) [builtins fixtures/dict-full.pyi] [case testNarrowTypeVarType]