Describe the Bug
Hi folks,
Thanks for the package!! I really like non-exhaustive-match and have been using it. One issue I have run into recently is that pyrefly reports an exhaustive match as non-exhaustive when separate class-pattern arms jointly cover a field union.
Here is an example:
from dataclasses import dataclass
from typing import final
@final
@dataclass
class A:
pass
@final
@dataclass
class B:
pass
@final
@dataclass
class Box:
value: A | B
def f(box: Box) -> int:
match box:
case Box(A()):
return 1
case Box(B()):
return 2
Actual:
Function declared to return `int`, but one or more paths are missing an explicit `return`
Match on `Box` is not exhaustive
Missing cases: Box
Expected: no errors. The two arms jointly cover Box.value.
Related: #3731 handles coverage within one arm, but not across arms.
Reproduces on current main. Enable non-exhaustive-match to see the second diagnostic (See sandbox link please)
I'm not familiar with the pyrefly codebase, so I asked a clanker to take a look. I reviewed the result, but it's easy for the clanker to convince me it's doing the right thing.
The patch does this:
before: check each arm on its own
after: keep that check, then look across unguarded arms when needed
The extra check keeps field combinations together and only removes the class when every combination is covered. If it cannot prove that, it leaves the type alone.
Draft patch: https://github.com/JafarAbdi/pyrefly/tree/fix/class-pattern-coverage-across-arms
Happy to open a PR if this patch looks reasonable.
Sandbox Link
https://pyrefly.org/sandbox/?project=v2.q8ZXZOLL9tCSAbVUBYcSKIpi8hygbMxM64gS_vjVOpGiNr8CtSxwVKhRcILoAucrjaT8CiuQMnCyzMwrgaeskuQMhSS4dhBITixOBSnVcNTQRM4USBnDEItqJ5yqjcBxhpZiEMkiLz9PN7UiI7G0GBRRuhAngSIcrAIc4_iiEQA
(Only applicable for extension issues) IDE Information
No response
Describe the Bug
Hi folks,
Thanks for the package!! I really like
non-exhaustive-matchand have been using it. One issue I have run into recently is that pyrefly reports an exhaustive match as non-exhaustive when separate class-pattern arms jointly cover a field union.Here is an example:
Actual:
Expected: no errors. The two arms jointly cover
Box.value.Related: #3731 handles coverage within one arm, but not across arms.
Reproduces on current
main. Enablenon-exhaustive-matchto see the second diagnostic (See sandbox link please)I'm not familiar with the pyrefly codebase, so I asked a clanker to take a look. I reviewed the result, but it's easy for the clanker to convince me it's doing the right thing.
The patch does this:
The extra check keeps field combinations together and only removes the class when every combination is covered. If it cannot prove that, it leaves the type alone.
Draft patch: https://github.com/JafarAbdi/pyrefly/tree/fix/class-pattern-coverage-across-arms
Happy to open a PR if this patch looks reasonable.
Sandbox Link
https://pyrefly.org/sandbox/?project=v2.q8ZXZOLL9tCSAbVUBYcSKIpi8hygbMxM64gS_vjVOpGiNr8CtSxwVKhRcILoAucrjaT8CiuQMnCyzMwrgaeskuQMhSS4dhBITixOBSnVcNTQRM4USBnDEItqJ5yqjcBxhpZiEMkiLz9PN7UiI7G0GBRRuhAngSIcrAIc4_iiEQA
(Only applicable for extension issues) IDE Information
No response