Skip to content

Commit 1c65fb6

Browse files
author
sanyam-brudite
committed
Fix type narrowing with not isinstance(x, cls) in classmethods
Adjust get_type_range_of_type to set is_upper_bound=False for Self types, allowing precise narrowing in negative checks. Fixes #21271.
1 parent fd11e89 commit 1c65fb6

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

mypy/checker.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8173,10 +8173,13 @@ def get_type_range_of_type(self, typ: Type) -> TypeRange | None:
81738173
# Type[A] means "any type that is a subtype of A" rather than "precisely type A"
81748174
# we indicate this by setting is_upper_bound flag
81758175
is_upper_bound = True
8176-
if isinstance(typ.item, NoneType):
8176+
item = get_proper_type(typ.item)
8177+
if isinstance(item, TypeVarType) and item.id.is_self():
8178+
is_upper_bound = False
8179+
elif isinstance(item, NoneType):
81778180
# except for Type[None], because "'NoneType' is not an acceptable base type"
81788181
is_upper_bound = False
8179-
if isinstance(typ.item, Instance) and typ.item.type.is_final:
8182+
elif isinstance(item, Instance) and item.type.is_final:
81808183
is_upper_bound = False
81818184
return TypeRange(typ.item, is_upper_bound=is_upper_bound)
81828185
if isinstance(typ, AnyType):

test-data/unit/check-isinstance.test

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3322,3 +3322,16 @@ def f2(x: A | None, t: type[A]):
33223322
else:
33233323
reveal_type(x) # N: Revealed type is "None"
33243324
[builtins fixtures/isinstancelist.pyi]
3325+
3326+
[case testNarrowingSelfInClassMethod]
3327+
# flags: --warn-unreachable
3328+
from typing import Self, Union
3329+
3330+
class Foo:
3331+
@classmethod
3332+
def foo(cls, x: Union[Self, float]) -> None:
3333+
if isinstance(x, cls):
3334+
reveal_type(x) # N: Revealed type is "Self`0"
3335+
else:
3336+
reveal_type(x) # N: Revealed type is "builtins.float"
3337+
[builtins fixtures/isinstancelist.pyi]

0 commit comments

Comments
 (0)