Skip to content

Commit a6dbbbb

Browse files
authored
Fix descriptor/Union interactions (#5039)
Fixes #4943
1 parent 88ebe48 commit a6dbbbb

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

mypy/checkexpr.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,13 @@ def analyze_descriptor_access(self, instance_type: Type, descriptor_type: Type,
12781278
Return:
12791279
The return type of the appropriate ``__get__`` overload for the descriptor.
12801280
"""
1281-
if not isinstance(descriptor_type, Instance):
1281+
if isinstance(descriptor_type, UnionType):
1282+
# Map the access over union types
1283+
return UnionType.make_simplified_union([
1284+
self.analyze_descriptor_access(instance_type, typ, context)
1285+
for typ in descriptor_type.items
1286+
])
1287+
elif not isinstance(descriptor_type, Instance):
12821288
return descriptor_type
12831289

12841290
if not descriptor_type.type.has_readable_member('__get__'):

test-data/unit/check-classes.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,20 @@ a = A()
14951495
a.f = 1
14961496
reveal_type(a.f) # E: Revealed type is 'builtins.str'
14971497

1498+
[case testDescriptorGetUnion]
1499+
from typing import Any, Union
1500+
class String:
1501+
def __get__(self, inst: Any, owner: Any) -> str:
1502+
return ''
1503+
1504+
class A:
1505+
attr: str
1506+
1507+
class B:
1508+
attr = String()
1509+
1510+
def foo(x: Union[A, B]) -> None:
1511+
reveal_type(x.attr) # E: Revealed type is 'builtins.str'
14981512

14991513
-- _promote decorators
15001514
-- -------------------

0 commit comments

Comments
 (0)