Skip to content

Narrowing types does not consider the @final decorator #20590

@baluyotraf

Description

@baluyotraf

Bug Report

This is related to #20041. Basically when trying to narrow a type object, using issubclass makes sense instead of is since the narrowing considers that subclasses can be used as replacement. For me however, it makes sense that issubclass be the same as is when the type is marked @final since the subclasses for the type cannot exist.

To Reproduce

https://mypy-play.net/?mypy=latest&python=3.12&gist=38818ca2515ec447077ef432725386d7

from typing import final, assert_never, reveal_type

class Types:

    @final
    class A:
        pass

    @final
    class B:
        pass

def pprint(cls: type[Types.A | Types.B]) -> None:
    match cls:
        case Types.A:
            print("A")
            reveal_type(cls)
        case Types.B:
            print("B")
            reveal_type(cls)
        case _:
            reveal_type(cls)
            assert_never(cls)

Edit: I realized that I used a match statement in this sample. But it also works with if/else:

def pprint(cls: type[Types.A | Types.B]) -> None:
    if cls is Types.A:
        reveal_type(cls)
    elif cls is Types.B:
        reveal_type(cls)
    else:
        reveal_type(cls)
        assert_never(cls)

Expected Behavior

I expect the types to be narrowed down when using is if the type is marked @final.

Actual Behavior

main.py:17: note: Revealed type is "type[__main__.Types.A]"
main.py:20: note: Revealed type is "type[__main__.Types.B]"
main.py:22: note: Revealed type is "type[__main__.Types.A] | type[__main__.Types.B]"
main.py:23: error: Argument 1 to "assert_never" has incompatible type "type[A] | type[B]"; expected "Never"  [arg-type]

The type does not narrow, see main.py:22

Your Environment

  • Mypy version used: mypy 1.19.1 (compiled: yes)
  • Mypy command-line flags:
  • 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 wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions