Skip to content

Incorrect type narrowing for select class hierarchies  #16379

Description

@Redoubts

Bug Report

I've found that in an exhaustive isinstance if block, mypy still leaves a more general type resolution than it should. In the snippet of code, mypy should be able to understand that there is no attr-defined error.

To Reproduce

from __future__ importannotationsclassA:
passclassB(A):
defget_x(self):
passclassC(A):
defget_x(self):
passclassD(C):
passclassE(C):
passclassF(C):
passdefx(obj: A):
value=""ifisinstance(obj, B):
value=obj.__class__.__name__elifisinstance(obj, D):
value=obj.__class__.__name__elifisinstance(obj, E):
value=obj.__class__.__name__elifisinstance(obj, F):
value=obj.__class__.__name__else:
raiseRuntimeError("unhandled type")
reveal_type(obj)
obj.get_x()

Expected Behavior

x.py:43: note: Revealed type is "B | D | E | F"

Actual Behavior

x.py:43: note: Revealed type is "x.A"
x.py:44: error: "A" has no attribute "get_x" [attr-defined]

Your Environment

  • Mypy version used: mypy 1.6.1 (compiled: yes)
  • Mypy command-line flags: default
  • Mypy configuration options from mypy.ini (and other config files): default
  • Python version used: 3.10.13

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions