Skip to content

[syntax-errors] Fix multiple assignment for class keyword argument #17184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
case {1: x, 2: x}: ... # MatchMapping duplicate pattern
case {1: x, **x}: ... # MatchMapping duplicate in **rest
case Class(x, x): ... # MatchClass positional
case Class(x=1, x=2): ... # MatchClass keyword
case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr
case Class(y=x, z=x): ... # MatchClass keyword
case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr
case x as x: ... # MatchAs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
match 2:
case Class(x=x): ...
9 changes: 6 additions & 3 deletions crates/ruff_python_parser/src/semantic_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,10 @@ struct MultipleCaseAssignmentVisitor<'a, Ctx> {

impl<'a, Ctx: SemanticSyntaxContext> MultipleCaseAssignmentVisitor<'a, Ctx> {
fn visit_pattern(&mut self, pattern: &'a Pattern) {
// test_ok class_keyword_in_case_pattern
// match 2:
// case Class(x=x): ...

// test_err multiple_assignment_in_case_pattern
// match 2:
// case [y, z, y]: ... # MatchSequence
Expand All @@ -802,8 +806,8 @@ impl<'a, Ctx: SemanticSyntaxContext> MultipleCaseAssignmentVisitor<'a, Ctx> {
// case {1: x, 2: x}: ... # MatchMapping duplicate pattern
// case {1: x, **x}: ... # MatchMapping duplicate in **rest
// case Class(x, x): ... # MatchClass positional
// case Class(x=1, x=2): ... # MatchClass keyword
// case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr
// case Class(y=x, z=x): ... # MatchClass keyword
// case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr
// case x as x: ... # MatchAs
match pattern {
Pattern::MatchValue(_) | Pattern::MatchSingleton(_) => {}
Expand All @@ -830,7 +834,6 @@ impl<'a, Ctx: SemanticSyntaxContext> MultipleCaseAssignmentVisitor<'a, Ctx> {
self.visit_pattern(pattern);
}
for keyword in &arguments.keywords {
self.insert(&keyword.attr);
self.visit_pattern(&keyword.pattern);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,18 +391,17 @@ Module(
PatternKeyword {
range: 331..334,
attr: Identifier {
id: Name("x"),
id: Name("y"),
range: 331..332,
},
pattern: MatchValue(
PatternMatchValue {
pattern: MatchAs(
PatternMatchAs {
range: 333..334,
value: NumberLiteral(
ExprNumberLiteral {
pattern: None,
name: Some(
Identifier {
id: Name("x"),
range: 333..334,
value: Int(
1,
),
},
),
},
Expand All @@ -411,18 +410,17 @@ Module(
PatternKeyword {
range: 336..339,
attr: Identifier {
id: Name("x"),
id: Name("z"),
range: 336..337,
},
pattern: MatchValue(
PatternMatchValue {
pattern: MatchAs(
PatternMatchAs {
range: 338..339,
value: NumberLiteral(
ExprNumberLiteral {
pattern: None,
name: Some(
Identifier {
id: Name("x"),
range: 338..339,
value: Int(
2,
),
},
),
},
Expand Down Expand Up @@ -518,18 +516,17 @@ Module(
PatternKeyword {
range: 398..401,
attr: Identifier {
id: Name("x"),
id: Name("y"),
range: 398..399,
},
pattern: MatchValue(
PatternMatchValue {
pattern: MatchAs(
PatternMatchAs {
range: 400..401,
value: NumberLiteral(
ExprNumberLiteral {
pattern: None,
name: Some(
Identifier {
id: Name("x"),
range: 400..401,
value: Int(
1,
),
},
),
},
Expand All @@ -538,18 +535,17 @@ Module(
PatternKeyword {
range: 403..406,
attr: Identifier {
id: Name("x"),
id: Name("z"),
range: 403..404,
},
pattern: MatchValue(
PatternMatchValue {
pattern: MatchAs(
PatternMatchAs {
range: 405..406,
value: NumberLiteral(
ExprNumberLiteral {
pattern: None,
name: Some(
Identifier {
id: Name("x"),
range: 405..406,
value: Int(
2,
),
},
),
},
Expand Down Expand Up @@ -681,7 +677,7 @@ Module(
6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest
| ^ Syntax Error: multiple assignments to name `x` in pattern
7 | case Class(x, x): ... # MatchClass positional
8 | case Class(x=1, x=2): ... # MatchClass keyword
8 | case Class(y=x, z=x): ... # MatchClass keyword
|


Expand All @@ -690,33 +686,33 @@ Module(
6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest
7 | case Class(x, x): ... # MatchClass positional
| ^ Syntax Error: multiple assignments to name `x` in pattern
8 | case Class(x=1, x=2): ... # MatchClass keyword
9 | case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr
8 | case Class(y=x, z=x): ... # MatchClass keyword
9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr
|


|
6 | case {1: x, **x}: ... # MatchMapping duplicate in **rest
7 | case Class(x, x): ... # MatchClass positional
8 | case Class(x=1, x=2): ... # MatchClass keyword
| ^ Syntax Error: multiple assignments to name `x` in pattern
9 | case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr
8 | case Class(y=x, z=x): ... # MatchClass keyword
| ^ Syntax Error: multiple assignments to name `x` in pattern
9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr
10 | case x as x: ... # MatchAs
|


|
7 | case Class(x, x): ... # MatchClass positional
8 | case Class(x=1, x=2): ... # MatchClass keyword
9 | case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr
| ^ Syntax Error: multiple assignments to name `x` in pattern
8 | case Class(y=x, z=x): ... # MatchClass keyword
9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr
| ^ Syntax Error: multiple assignments to name `x` in pattern
10 | case x as x: ... # MatchAs
|


|
8 | case Class(x=1, x=2): ... # MatchClass keyword
9 | case [x] | {1: x} | Class(x=1, x=2): ... # MatchOr
8 | case Class(y=x, z=x): ... # MatchClass keyword
9 | case [x] | {1: x} | Class(y=x, z=x): ... # MatchOr
10 | case x as x: ... # MatchAs
| ^ Syntax Error: multiple assignments to name `x` in pattern
|
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/inline/ok/class_keyword_in_case_pattern.py
---
## AST

```
Module(
ModModule {
range: 0..34,
body: [
Match(
StmtMatch {
range: 0..33,
subject: NumberLiteral(
ExprNumberLiteral {
range: 6..7,
value: Int(
2,
),
},
),
cases: [
MatchCase {
range: 13..33,
pattern: MatchClass(
PatternMatchClass {
range: 18..28,
cls: Name(
ExprName {
range: 18..23,
id: Name("Class"),
ctx: Load,
},
),
arguments: PatternArguments {
range: 23..28,
patterns: [],
keywords: [
PatternKeyword {
range: 24..27,
attr: Identifier {
id: Name("x"),
range: 24..25,
},
pattern: MatchAs(
PatternMatchAs {
range: 26..27,
pattern: None,
name: Some(
Identifier {
id: Name("x"),
range: 26..27,
},
),
},
),
},
],
},
},
),
guard: None,
body: [
Expr(
StmtExpr {
range: 30..33,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 30..33,
},
),
},
),
],
},
],
},
),
],
},
)
```
Loading