Closed
Description
Bug Report
When doing narrowing of a class attribute with a particular type shape A | B | None
, the type of the attribute becomes object
after the narrowing condition chain.
To Reproduce
The following is the most minimal reproduction I was able to create.
class A: pass
class B: pass
class C:
attr: A | B | None
c = C()
if c.attr is None: pass
elif isinstance(c.attr, A): pass
elif isinstance(c.attr, B): pass # Optional line - no difference if removed
reveal_type(c.attr)
Expected Behavior
Revealed type is A | B | None
.
Actual Behavior
Revealed type is object
.
I made some additional tests:
pyright
givesA | B | None
(good).- Doing
x = c.x
and then doing the narrowing andreveal_type
onattr
givesA | B | None
(good). - Replacing the
None
withA | B | D
givesA | B | D
(good). Also if I replaceif isinstance(c.attr, D)
withif type(c.attr) is D
(good). So theNone
seems essential. - With just
attr: A | None
, givesA | None
(good). So more than one type besides theNone
seems essential. - Changing the
elif
->if
givesA | B | None
(good). So theelif
seems essential.
Your Environment
- Mypy version used: master, 0.931, 0.900 (didn't try earlier versions).
- Mypy command-line flags:
--strict
. - Mypy configuration options from
mypy.ini
(and other config files): - Python version used: 3.9, 3.10
- Operating system and version: Arch Linux