Skip to content

Union interacts poorly with isinstance-based unreachability #20057

@A5rocks

Description

@A5rocks

Bug Report

This is probably already a bug report but the only place I know where this was mentioned was #13607 (comment).

Including | None in a type makes isinstance type narrowing incorrectly report unreachability. This isn't only a problem with | None.

To Reproduce

class SymbolTableNode: pass
class FuncBase: pass

def bad(node: SymbolTableNode | None) -> None:
    assert isinstance(node, FuncBase)
    reveal_type(node)  # unreachable

def good(node: SymbolTableNode) -> None:
    assert isinstance(node, FuncBase)
    reveal_type(node)  # <subclass of SymbolTableNode and FuncBase>

Expected Behavior

No unreachable statements.

Actual Behavior

Unreachable reveal_type(node).

Your Environment

Reproduced in mypy-play.

  • Mypy version used: 1.18.2
  • Mypy command-line flags: --warn-unreachable
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.12

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-reachabilityDetecting unreachable code

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions