Skip to content

[1.16 regression] failure to exhaustively narrow type var bounded by union with value pattern match #19159

Closed

Description

@hauntsaninja

Courtesy of @delfick

So if we have two files

# a.py
from typing import assert_never

import b


def switch[T_Choice: b.One | b.Two](choice: type[T_Choice]) -> None:
    match choice:
        case b.One:
            print(1)
        case b.Two:
            print(2)
        case _:
            assert_never(choice)


switch(b.One)

and

# b.py
class One: ...
class Two: ...

Then I get no errors with mypy 1.15 and this error with 1.16

a.py:13: error: Argument 1 to "assert_never" has incompatible type "type[Two] | Never"; expected "Never"  [arg-type]

Activity

  1. hauntsaninja commented on May 28, 2025

    @hauntsaninja
    CollaboratorAuthor

    Bisects to #18972

  2. delfick commented on May 28, 2025

    @delfick

    I would say though that I think the above example should probably only work if the two classes are decorated with @typing.final and it does seem the same errors happen with that decorator being used (i.e. no error in 1.15, that new error in 1.16)

  3. JukkaL commented on May 28, 2025

    @JukkaL
    Collaborator

    I'm a little surprised that we apparently don't have a test for this. This looks like a significant regression, though it wasn't obvious likely because many projects we test against still support 3.9, which doesn't support the match statement.

    cc @ilevkivskyi as the author of #18972

  4. JukkaL commented on May 28, 2025

    @JukkaL
    Collaborator

    I'm a little surprised that we apparently don't have a test for this.

    I didn't realized that this only happens in a fairly specific scenario. Having everything in a single file doesn't reproduce the issue.

  5. ilevkivskyi commented on May 28, 2025

    @ilevkivskyi
    Member

    I may not have time to properly look into this until weekend, but FWIW this looks really niche to me. I would even say we may go ahead with the release and fix this later, unless this causes big troubles for some repos.

  6. JukkaL commented on May 28, 2025

    @JukkaL
    Collaborator

    Ok, I treat this as a non-blocker for the release.

  7. delfick commented on May 28, 2025

    @delfick

    Ok, that's fine on my end, there's only a few assert_never that I would have to change to an Exception in my repo :)

  8. changed the title [-][1.16 regression] failure to exhaustively narrow type var bounded by union[/-] [+][1.16 regression] failure to exhaustively narrow type var bounded by union (across files)[/+] on Jun 4, 2025
  9. hauntsaninja commented on Jun 29, 2025

    @hauntsaninja
    CollaboratorAuthor

    Btw I improved some behaviour here in #19320 , but we do not still exhaustively narrow so leaving this open

  10. changed the title [-][1.16 regression] failure to exhaustively narrow type var bounded by union (across files)[/-] [+][1.16 regression] failure to exhaustively narrow type var bounded by union with value pattern match[/+] on Jun 29, 2025
  11. randolf-scholz commented on Dec 9, 2025

    @randolf-scholz
    Contributor

    In the original example, I think it is correct for mypy to complain about the assert_never because this case will be selected at runtime if we make a class A(b.One) and call switch(A). Value patterns are evaluated by equality (==).

  12. hauntsaninja commented on Dec 14, 2025

    @hauntsaninja
    CollaboratorAuthor

    Closing this as per above and discussion in #20146

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-match-statementPython 3.10's match statementtopic-type-narrowingConditional type narrowing / binder

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions