mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-10 02:12:09 +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
|
@ -35,8 +35,8 @@ use crate::semantic_index::place::{
|
|||
PlaceExprWithFlags, PlaceTableBuilder, Scope, ScopeId, ScopeKind, ScopedPlaceId,
|
||||
};
|
||||
use crate::semantic_index::predicate::{
|
||||
CallableAndCallExpr, PatternPredicate, PatternPredicateKind, Predicate, PredicateNode,
|
||||
PredicateOrLiteral, ScopedPredicateId, StarImportPlaceholderPredicate,
|
||||
CallableAndCallExpr, ClassPatternKind, PatternPredicate, PatternPredicateKind, Predicate,
|
||||
PredicateNode, PredicateOrLiteral, ScopedPredicateId, StarImportPlaceholderPredicate,
|
||||
};
|
||||
use crate::semantic_index::re_exports::exported_names;
|
||||
use crate::semantic_index::reachability_constraints::{
|
||||
|
@ -697,7 +697,25 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> {
|
|||
}
|
||||
ast::Pattern::MatchClass(pattern) => {
|
||||
let cls = self.add_standalone_expression(&pattern.cls);
|
||||
PatternPredicateKind::Class(cls)
|
||||
|
||||
PatternPredicateKind::Class(
|
||||
cls,
|
||||
if pattern
|
||||
.arguments
|
||||
.patterns
|
||||
.iter()
|
||||
.all(ast::Pattern::is_irrefutable)
|
||||
&& pattern
|
||||
.arguments
|
||||
.keywords
|
||||
.iter()
|
||||
.all(|kw| kw.pattern.is_irrefutable())
|
||||
{
|
||||
ClassPatternKind::Irrefutable
|
||||
} else {
|
||||
ClassPatternKind::Refutable
|
||||
},
|
||||
)
|
||||
}
|
||||
ast::Pattern::MatchOr(pattern) => {
|
||||
let predicates = pattern
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue