Match-case on type() is not well interpreted
- Dominant language
- Python
- Stars
- 15.6k
- Forks
- 1.8k
- Avg merge
- 12h 13m
- Merged PRs (30d)
- 52
Description
**Environment**
* Python version: 3.12.3
* PyRight version: 1.1.411
* PyRight configuration: [pyrightconfig.json](https://github.com/user-attachments/files/30548992/pyrightconfig.json)
**Describe the bug**
Discriminating based on the type of an object, using a match-case statement, seems erroneously interpreted by PyRight. It complains about lack of cases coverage, erroneously, and additionally suggest terms to add case statements which are syntactically invalid for Python.
PyRight is very clean and useful, but I feel disappointed with this issue, because case coverage checking is as much important as type checking (like in SML). Can still type-check adding an `assert isintance(...)` at the start of each case branch, but ensuring coverage is sadly missing and it's really important.
**Code or Screenshots**
There are explanations in the comments.
Note to other people: the example below only matches exact classes (the real case is with some `NamedTuple` classes). If `inst` was an instance of a derived class of `B`, it would not work (would print nothing). I don’t know if there exist a way to express the same with the idea of matching derived class and with the benefit of cases coverage check. There is `isinstance` but it cannot be used in this `match` expression.
```python
import builtins
class Base:
pass
class A(Base):
pass
class B(Base):
pass
class C(Base):
pass
# Add classes in a kind of name-space, so that the cases in the match, are not
# taken to be variable names. Without this, the case statements don’t mean what
# is intended. The bug is not here, this to explain to people who try to
# discover and learn things.
class NS:
A = A
B = B
C = C
inst: Base = B()
match type(inst):
case NS.A:
print("A")
case NS.B:
print("B")
case NS.C:
print("C")
# It prints "B", as expected, so it works, but PyRight complains about this:
# > error: Cases within match statement do not exhaustively handle all values
# > Unhandled type: "type[B]"
# Additionally, the suggestion is misleading, because using `type[...]` yields
# a syntax error. Please, un-comment the below if you want to test it.
#
# match type(inst):
# case builtins.type[NS.A]:
# print("A")
# case builtins.type[NS.B]:
# print("B")
# case builtins.type[NS.C]:
# print("C")
```
Contributor guide
Research direction
Start with the provided Python 3.12.3 reproduction and inspect Pyright's exhaustive match-case analysis for match type(inst) with qualified class patterns. Verify the reported unhandled type and the suggested type[...] cases, then confirm that the diagnostic and suggestions correctly reflect valid Python syntax and intended coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100