microsoft / microsoft/pyright

Match-case on type() is not well interpreted

Open
#11,576 5 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.