Skip to content

Incorrect narrowing between two different unions #20820

Open

Description

@A5rocks

Bug Report

Narrowing via isinstance and two unions does not seem to do a full crossproduct of possibilities. Spotted when reviewing #20743.

To Reproduce

from __future__ import annotations

class A: ...

class B: ...

class C: ...

def f1(x: A | C, t: type[A] | type[B]):
    if isinstance(x, t):
        reveal_type(x)  # N: Revealed type is "__main__.A"
    else:
        reveal_type(x)  # Revealed type is "__main__.A | __main__.C"

Expected Behavior

I would expect the revealed types to be a superset of the results if we did a crossproduct. However, note that <subclass of C and B> is missing. (probably the best way to express this would be to have intersections but... yeah...)

Actual Behavior

Positive branch just has A.

Your Environment

Reproduced in mypy-play

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

Activity

  1. added a commit that references this issue on Feb 16, 2026
  2. BHUVANSH855 commented on Apr 12, 2026

    @BHUVANSH855

    Hi @A5rocks I’d like to work on this issue.

    I noticed there was a previous attempt (#20824). I’ll review it and try to address any gaps or concerns from that PR.

    Please let me know if there are any specific expectations before I proceed.

  3. A5rocks commented on Apr 12, 2026

    @A5rocks
    CollaboratorAuthor

    You can work on whatever, no need for permission.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-type-narrowingConditional type narrowing / binder

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions