mirror of https://github.com/astral-sh/ruff
Fix syntax error false positive on nested alternative patterns (#21104)
## Summary Fixes #21101 by storing the child visitor's names in the parent visitor. This makes sure that `visitor.names` on line 1818 isn't empty after we visit a nested OR pattern. ## Test Plan New inline test cases derived from the issue, [playground](https://play.ruff.rs/7b6439ac-ee8f-4593-9a3e-c2aa34a595d0)
This commit is contained in:
parent
10bda3df00
commit
f0fe6d62fb
|
|
@ -0,0 +1,7 @@
|
||||||
|
match ruff:
|
||||||
|
case {"lint": {"select": x} | {"extend-select": x}} | {"select": x}:
|
||||||
|
...
|
||||||
|
match 42:
|
||||||
|
case [[x] | [x]] | x: ...
|
||||||
|
match 42:
|
||||||
|
case [[x | x] | [x]] | x: ...
|
||||||
|
|
@ -1841,6 +1841,15 @@ impl<'a, Ctx: SemanticSyntaxContext> MatchPatternVisitor<'a, Ctx> {
|
||||||
// case (x, (y | y)): ...
|
// case (x, (y | y)): ...
|
||||||
// case [a, _] | [a, _]: ...
|
// case [a, _] | [a, _]: ...
|
||||||
// case [a] | [C(a)]: ...
|
// case [a] | [C(a)]: ...
|
||||||
|
|
||||||
|
// test_ok nested_alternative_patterns
|
||||||
|
// match ruff:
|
||||||
|
// case {"lint": {"select": x} | {"extend-select": x}} | {"select": x}:
|
||||||
|
// ...
|
||||||
|
// match 42:
|
||||||
|
// case [[x] | [x]] | x: ...
|
||||||
|
// match 42:
|
||||||
|
// case [[x | x] | [x]] | x: ...
|
||||||
SemanticSyntaxChecker::add_error(
|
SemanticSyntaxChecker::add_error(
|
||||||
self.ctx,
|
self.ctx,
|
||||||
SemanticSyntaxErrorKind::DifferentMatchPatternBindings,
|
SemanticSyntaxErrorKind::DifferentMatchPatternBindings,
|
||||||
|
|
@ -1848,6 +1857,7 @@ impl<'a, Ctx: SemanticSyntaxContext> MatchPatternVisitor<'a, Ctx> {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
self.names = visitor.names;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,495 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_parser/resources/inline/ok/nested_alternative_patterns.py
|
||||||
|
---
|
||||||
|
## AST
|
||||||
|
|
||||||
|
```
|
||||||
|
Module(
|
||||||
|
ModModule {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 0..181,
|
||||||
|
body: [
|
||||||
|
Match(
|
||||||
|
StmtMatch {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 0..96,
|
||||||
|
subject: Name(
|
||||||
|
ExprName {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 6..10,
|
||||||
|
id: Name("ruff"),
|
||||||
|
ctx: Load,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
cases: [
|
||||||
|
MatchCase {
|
||||||
|
range: 16..96,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
pattern: MatchOr(
|
||||||
|
PatternMatchOr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 21..83,
|
||||||
|
patterns: [
|
||||||
|
MatchMapping(
|
||||||
|
PatternMatchMapping {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 21..67,
|
||||||
|
keys: [
|
||||||
|
StringLiteral(
|
||||||
|
ExprStringLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 22..28,
|
||||||
|
value: StringLiteralValue {
|
||||||
|
inner: Single(
|
||||||
|
StringLiteral {
|
||||||
|
range: 22..28,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
value: "lint",
|
||||||
|
flags: StringLiteralFlags {
|
||||||
|
quote_style: Double,
|
||||||
|
prefix: Empty,
|
||||||
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
patterns: [
|
||||||
|
MatchOr(
|
||||||
|
PatternMatchOr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 30..66,
|
||||||
|
patterns: [
|
||||||
|
MatchMapping(
|
||||||
|
PatternMatchMapping {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 30..43,
|
||||||
|
keys: [
|
||||||
|
StringLiteral(
|
||||||
|
ExprStringLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 31..39,
|
||||||
|
value: StringLiteralValue {
|
||||||
|
inner: Single(
|
||||||
|
StringLiteral {
|
||||||
|
range: 31..39,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
value: "select",
|
||||||
|
flags: StringLiteralFlags {
|
||||||
|
quote_style: Double,
|
||||||
|
prefix: Empty,
|
||||||
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
patterns: [
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 41..42,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 41..42,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
rest: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MatchMapping(
|
||||||
|
PatternMatchMapping {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 46..66,
|
||||||
|
keys: [
|
||||||
|
StringLiteral(
|
||||||
|
ExprStringLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 47..62,
|
||||||
|
value: StringLiteralValue {
|
||||||
|
inner: Single(
|
||||||
|
StringLiteral {
|
||||||
|
range: 47..62,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
value: "extend-select",
|
||||||
|
flags: StringLiteralFlags {
|
||||||
|
quote_style: Double,
|
||||||
|
prefix: Empty,
|
||||||
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
patterns: [
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 64..65,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 64..65,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
rest: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
rest: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MatchMapping(
|
||||||
|
PatternMatchMapping {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 70..83,
|
||||||
|
keys: [
|
||||||
|
StringLiteral(
|
||||||
|
ExprStringLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 71..79,
|
||||||
|
value: StringLiteralValue {
|
||||||
|
inner: Single(
|
||||||
|
StringLiteral {
|
||||||
|
range: 71..79,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
value: "select",
|
||||||
|
flags: StringLiteralFlags {
|
||||||
|
quote_style: Double,
|
||||||
|
prefix: Empty,
|
||||||
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
patterns: [
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 81..82,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 81..82,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
rest: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
guard: None,
|
||||||
|
body: [
|
||||||
|
Expr(
|
||||||
|
StmtExpr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 93..96,
|
||||||
|
value: EllipsisLiteral(
|
||||||
|
ExprEllipsisLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 93..96,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Match(
|
||||||
|
StmtMatch {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 97..136,
|
||||||
|
subject: NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 103..105,
|
||||||
|
value: Int(
|
||||||
|
42,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
cases: [
|
||||||
|
MatchCase {
|
||||||
|
range: 111..136,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
pattern: MatchOr(
|
||||||
|
PatternMatchOr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 116..131,
|
||||||
|
patterns: [
|
||||||
|
MatchSequence(
|
||||||
|
PatternMatchSequence {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 116..127,
|
||||||
|
patterns: [
|
||||||
|
MatchOr(
|
||||||
|
PatternMatchOr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 117..126,
|
||||||
|
patterns: [
|
||||||
|
MatchSequence(
|
||||||
|
PatternMatchSequence {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 117..120,
|
||||||
|
patterns: [
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 118..119,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 118..119,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MatchSequence(
|
||||||
|
PatternMatchSequence {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 123..126,
|
||||||
|
patterns: [
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 124..125,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 124..125,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 130..131,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 130..131,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
guard: None,
|
||||||
|
body: [
|
||||||
|
Expr(
|
||||||
|
StmtExpr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 133..136,
|
||||||
|
value: EllipsisLiteral(
|
||||||
|
ExprEllipsisLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 133..136,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Match(
|
||||||
|
StmtMatch {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 137..180,
|
||||||
|
subject: NumberLiteral(
|
||||||
|
ExprNumberLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 143..145,
|
||||||
|
value: Int(
|
||||||
|
42,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
cases: [
|
||||||
|
MatchCase {
|
||||||
|
range: 151..180,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
pattern: MatchOr(
|
||||||
|
PatternMatchOr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 156..175,
|
||||||
|
patterns: [
|
||||||
|
MatchSequence(
|
||||||
|
PatternMatchSequence {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 156..171,
|
||||||
|
patterns: [
|
||||||
|
MatchOr(
|
||||||
|
PatternMatchOr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 157..170,
|
||||||
|
patterns: [
|
||||||
|
MatchSequence(
|
||||||
|
PatternMatchSequence {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 157..164,
|
||||||
|
patterns: [
|
||||||
|
MatchOr(
|
||||||
|
PatternMatchOr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 158..163,
|
||||||
|
patterns: [
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 158..159,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 158..159,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 162..163,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 162..163,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MatchSequence(
|
||||||
|
PatternMatchSequence {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 167..170,
|
||||||
|
patterns: [
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 168..169,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 168..169,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MatchAs(
|
||||||
|
PatternMatchAs {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 174..175,
|
||||||
|
pattern: None,
|
||||||
|
name: Some(
|
||||||
|
Identifier {
|
||||||
|
id: Name("x"),
|
||||||
|
range: 174..175,
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
guard: None,
|
||||||
|
body: [
|
||||||
|
Expr(
|
||||||
|
StmtExpr {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 177..180,
|
||||||
|
value: EllipsisLiteral(
|
||||||
|
ExprEllipsisLiteral {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 177..180,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
```
|
||||||
Loading…
Reference in New Issue