Skip to content

Commit c5ddc36

Browse files
authored
Fix narrowing union types that include Self with isinstance (#14923)
Fix narrowing union types that include Self with isinstance (Fixes #14912). The special case of bound type variables was not handled in function `covers_at_runtime` of module `subtypes`. So I added it and defined the test case `testNarrowSelfType`.
1 parent 46ab0f8 commit c5ddc36

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

mypy/subtypes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,9 @@ def covers_at_runtime(item: Type, supertype: Type) -> bool:
18021802
# Special case useful for selecting TypedDicts from unions using isinstance(x, dict).
18031803
if supertype.type.fullname == "builtins.dict":
18041804
return True
1805+
elif isinstance(item, TypeVarType):
1806+
if is_proper_subtype(item.upper_bound, supertype, ignore_promotions=True):
1807+
return True
18051808
elif isinstance(item, Instance) and supertype.type.fullname == "builtins.int":
18061809
# "int" covers all native int types
18071810
if item.type.fullname in MYPYC_NATIVE_INT_NAMES:

test-data/unit/check-selftype.test

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,3 +1829,21 @@ class C(Generic[T]):
18291829
reveal_type(self.val) # N: Revealed type is "__main__.A" \
18301830
# N: Revealed type is "__main__.B"
18311831
self.val = x
1832+
1833+
[case testNarrowSelfType]
1834+
from typing import Self, Union
1835+
1836+
class A: ...
1837+
class B:
1838+
def f1(self, v: Union[Self, A]) -> A:
1839+
if isinstance(v, B):
1840+
return A()
1841+
else:
1842+
return v
1843+
def f2(self, v: Union[Self, A]) -> A:
1844+
if isinstance(v, B):
1845+
return A()
1846+
else:
1847+
return B() # E: Incompatible return value type (got "B", expected "A")
1848+
1849+
[builtins fixtures/isinstancelist.pyi]

0 commit comments

Comments
 (0)