Skip to content
Open
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
2 changes: 2 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -6734,6 +6734,8 @@ def narrow_type_by_identity_equality(
and len(type_expr.args) == 1
):
expr_in_type_expr = type_expr.args[0]
elif isinstance(type_expr, MemberExpr) and type_expr.name == "__class__":
expr_in_type_expr = type_expr.expr
else:
continue
for j in expr_indices:
Expand Down
28 changes: 28 additions & 0 deletions test-data/unit/check-narrowing.test
Original file line number Diff line number Diff line change
Expand Up @@ -3076,3 +3076,31 @@ if type(x) is not C:
reveal_type(x) # N: Revealed type is "__main__.D"
else:
reveal_type(x) # N: Revealed type is "__main__.C"

[case testDunderClassNarrowing]
# flags: --warn-unreachable
from typing import Any

def foo(y: object):
if y.__class__ == int:
reveal_type(y) # N: Revealed type is "builtins.int"
else:
reveal_type(y) # N: Revealed type is "builtins.object"

if y.__class__ is int:
reveal_type(y) # N: Revealed type is "builtins.int"
else:
reveal_type(y) # N: Revealed type is "builtins.object"


def bar(y: Any):
if y.__class__ == int:
reveal_type(y) # N: Revealed type is "Any"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this Any will actually get fixed by #20643

else:
reveal_type(y) # N: Revealed type is "Any"

if y.__class__ is int:
reveal_type(y) # N: Revealed type is "builtins.int"
else:
reveal_type(y) # N: Revealed type is "Any"
[builtins fixtures/dict-full.pyi]
4 changes: 2 additions & 2 deletions test-data/unit/fixtures/dict-full.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ KT = TypeVar('KT')
VT = TypeVar('VT')

class object:
__class__: object
def __init__(self) -> None: pass
def __init_subclass__(cls) -> None: pass
def __eq__(self, other: object) -> bool: pass
Expand Down Expand Up @@ -75,8 +76,7 @@ class float: pass
class complex: pass
class bool(int): pass

class ellipsis:
__class__: object
class ellipsis: pass
def isinstance(x: object, t: Union[type, Tuple[type, ...]]) -> bool: pass
class BaseException: pass

Expand Down