Unexhaustive pattern match on dataclass field union #9429
-
Hello ! Here is a minimal case of pattern matching on a dataclass field that is the union of two types: from dataclasses import dataclass
@dataclass
class Classic:
pass
@dataclass
class Admin:
pass
@dataclass
class User:
name: str
role: Classic | Admin
some_user = User("pluto", role=Admin())
match some_user:
case User(_, role=Classic()):
pass
case User(_, role=Admin()):
pass I would expect that the pattern match is exhaustive here but pyright (1.1.386) disagree:
Pyright only considers that the pattern match is exhaustive when I add the following branch: match some_user:
case User(_, role=Classic()):
pass
case User(_, role=Admin()):
pass
case User():
pass Do you have any idea why this 3rd branch is required ? Thanks in advance, and have a nice day 🌴 EDIT: Here is a link to the same code on pyright's playground |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Exhaustion detection uses type narrowing to determine whether you have handled all possible types. In this case, the subject type starts as If you want static analysis exhaustion to work, you'll need to change your code somewhat. Code sample in pyright playground # pyright: strict
from dataclasses import dataclass
@dataclass
class Classic:
pass
@dataclass
class Admin:
pass
@dataclass
class User[T: Classic | Admin]:
name: str
role: T
def func(some_user: User[Classic] | User[Admin]):
match some_user:
case User(_, role=Classic()):
pass
case User(_, role=Admin()):
pass |
Beta Was this translation helpful? Give feedback.
Exhaustion detection uses type narrowing to determine whether you have handled all possible types. In this case, the subject type starts as
User
. The subsequent case statements do not narrow the type further. The type of the subject remainsUser
after the first and the second. There is no notion in the Python type system of the typeUser where the "role" attribute refers to a "Classic" object
.If you want static analysis exhaustion to work, you'll need to change your code somewhat.
Code sample in pyright playground