[ty] Make class-pattern fallthrough member-aware#26283
Conversation
Typing conformance resultsNo changes detected ✅Current numbersThe percentage of diagnostics emitted that were expected errors held steady at 94.47%. The percentage of expected errors that received a diagnostic held steady at 89.19%. The number of fully passing files held steady at 95/134. |
Memory usage reportMemory usage unchanged ✅ |
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
type-assertion-failure |
0 | 0 | 2 |
invalid-return-type |
0 | 1 | 0 |
| Total | 0 | 1 | 2 |
Large timing changes:
| Project | Old Time | New Time | Change |
|---|---|---|---|
egglog-python |
0.31s | 0.50s | +61% |
Raw diff:
Expression (https://github.com/cognitedata/Expression)
- expression/extra/parser.py:128:34 error[invalid-return-type] Function can implicitly return `None`, which is not assignable to return type `Result[tuple[tuple[_A@and_then, _B@and_then], tuple[str, int]], str]`
egglog-python (https://github.com/egraphs-good/egglog-python)
- python/egglog/egraph_state.py:623:25 error[type-assertion-failure] Type `Unknown & ~None & ~int & ~float & ~str` is not equivalent to `Never`
+ python/egglog/egraph_state.py:623:25 error[type-assertion-failure] Type `Unknown & ~None` is not equivalent to `Never`
- python/egglog/pretty.py:309:17 error[type-assertion-failure] Type `Unknown & ~None & ~int & ~float & ~str` is not equivalent to `Never`
+ python/egglog/pretty.py:309:17 error[type-assertion-failure] Type `Unknown & ~None` is not equivalent to `Never`bf68588 to
6cf2b7c
Compare
|
Should this raise an error? At runtime, this prints This also means that the first pattern is refutable which is why it falls through to the second case. from dataclasses import dataclass
class Point:
__match_args__ = ("x",)
def f(value: Point) -> None:
match value:
case Point(_):
print("first")
case x:
reveal_type(x)
print("second")
f(Point())Both pyrefly and mypy raises a diagnostic stating that I think not raising a diagnostic is fine but it might still be useful to make the pattern refutable in this case. |
| } | ||
|
|
||
| impl ClassPatternPredicateKind<'_> { | ||
| pub fn is_argumentless(&self) -> bool { |
Maybe this is something that needs to be done in #26284 ? |
6cf2b7c to
afd19f8
Compare
|
Yeah, this is handled by #26284! The missing |
## Summary This is the second of three stacked PRs split from #26010. It is based on #26283. The first PR makes keyword class-pattern exhaustiveness subject-aware, but positional patterns still use a syntax-only approximation: any positional capture is treated as irrefutable without determining which value Python passes to it. That can classify a pattern as exhaustive when `__match_args__` is missing, uncertain, widened, or names an absent attribute. This resolves each positional source from the class named in the pattern. For ordinary classes, we require a definitely bound fixed tuple of literal names from `__match_args__` and check each selected member recursively. For Python's match-self builtins, including their subclasses, the first positional pattern receives the complete subject. Generated `NamedTuple.__match_args__` values follow the same path.
Summary
This is the first of three stacked PRs split from #26010.
On
main, we consider a class pattern exhaustive whenever its subpatterns are irrefutable. We do not check whether the attributes requested by the pattern are actually present:mainaccepts both functions. This is wrong formissing_attribute: aBaseinstance may not havex, so the pattern can fail and the function can returnNone. However,subject_attributeis exhaustive because its static subject type isChild, which guarantees thatxis present.(This isn't exactly right -- Pyright requires that
Childis@final, but I think this is more consistent with our semantics elsewhere.)This PR retains the attributes requested by a class pattern and checks them against the static subject type. With this change,
missing_attributereportsinvalid-return-type, whilesubject_attributeremains accepted. Nested attribute patterns use the same check recursively, including inside sequence,or, andaspatterns.