mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-29 03:02:27 +00:00
[ty] Fix narrowing and reachability of class patterns with arguments (#19512)
## Summary
I noticed that our type narrowing and reachability analysis was
incorrect for class patterns that are not irrefutable. The test cases
below compare the old and the new behavior:
```py
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
class Other: ...
def _(target: Point):
y = 1
match target:
case Point(0, 0):
y = 2
case Point(x=0, y=1):
y = 3
case Point(x=1, y=0):
y = 4
reveal_type(y) # revealed: Literal[1, 2, 3, 4] (previously: Literal[2])
def _(target: Point | Other):
match target:
case Point(0, 0):
reveal_type(target) # revealed: Point
case Point(x=0, y=1):
reveal_type(target) # revealed: Point (previously: Never)
case Point(x=1, y=0):
reveal_type(target) # revealed: Point (previously: Never)
case Other():
reveal_type(target) # revealed: Other (previously: Other & ~Point)
```
## Test Plan
New Markdown test
This commit is contained in:
parent
fa1df4cedc
commit
3d17897c02
5 changed files with 111 additions and 11 deletions
|
|
@ -689,13 +689,20 @@ impl ReachabilityConstraints {
|
|||
});
|
||||
truthiness
|
||||
}
|
||||
PatternPredicateKind::Class(class_expr) => {
|
||||
PatternPredicateKind::Class(class_expr, kind) => {
|
||||
let subject_ty = infer_expression_type(db, subject);
|
||||
let class_ty = infer_expression_type(db, *class_expr).to_instance(db);
|
||||
|
||||
class_ty.map_or(Truthiness::Ambiguous, |class_ty| {
|
||||
if subject_ty.is_subtype_of(db, class_ty) {
|
||||
Truthiness::AlwaysTrue
|
||||
if kind.is_irrefutable() {
|
||||
Truthiness::AlwaysTrue
|
||||
} else {
|
||||
// A class pattern like `case Point(x=0, y=0)` is not irrefutable,
|
||||
// i.e. it does not match all instances of `Point`. This means that
|
||||
// we can't tell for sure if this pattern will match or not.
|
||||
Truthiness::Ambiguous
|
||||
}
|
||||
} else if subject_ty.is_disjoint_from(db, class_ty) {
|
||||
Truthiness::AlwaysFalse
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue