Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 32 additions & 2 deletions test-data/unit/check-narrowing.test
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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]
Expand Down