Skip to content

Commit 8467b32

Browse files
author
Gilad Chase
committed
fix(semantic): add diagnostic for duplicate var names in pattern
1 parent 73f5bd7 commit 8467b32

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

crates/cairo-lang-semantic/src/diagnostic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,9 @@ impl<'db> DiagnosticEntry<'db> for SemanticDiagnostic<'db> {
404404
SemanticDiagnosticKind::MissingVariableInPattern => {
405405
"Missing variable in pattern.".into()
406406
}
407+
SemanticDiagnosticKind::VariableDefinedMultipleTimesInPattern(name) => {
408+
format!(r#"Redefinition of variable name "{}" in pattern."#, name.long(db))
409+
}
407410
SemanticDiagnosticKind::StructMemberRedefinition { struct_id, member_name } => {
408411
format!(
409412
r#"Redefinition of member "{}" on struct "{}"."#,
@@ -1293,6 +1296,7 @@ pub enum SemanticDiagnosticKind<'db> {
12931296
},
12941297
VariableNotFound(SmolStrId<'db>),
12951298
MissingVariableInPattern,
1299+
VariableDefinedMultipleTimesInPattern(SmolStrId<'db>),
12961300
StructMemberRedefinition {
12971301
struct_id: StructId<'db>,
12981302
member_name: SmolStrId<'db>,

crates/cairo-lang-semantic/src/expr/compute.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,17 +1770,21 @@ fn compute_pattern_list_or_semantic<'db>(
17701770
for (pattern_syntax, pattern) in patterns_syntax.elements(db).zip(patterns.iter()) {
17711771
let variables = pattern.variables(&ctx.arenas.patterns);
17721772

1773-
if variables.len() != arm_patterns_variables.len() {
1774-
ctx.diagnostics.report(pattern_syntax.stable_ptr(db), MissingVariableInPattern);
1775-
}
1776-
1773+
let mut variable_names_in_pattern = UnorderedHashSet::<_>::default();
17771774
for v in variables {
1775+
if !variable_names_in_pattern.insert(v.name) {
1776+
ctx.diagnostics.report(v.stable_ptr, VariableDefinedMultipleTimesInPattern(v.name));
1777+
}
17781778
let var_def = Binding::LocalVar(v.var.clone());
17791779
// TODO(spapini): Wrap this in a function to couple with semantic_defs
17801780
// insertion.
17811781
ctx.environment.variables.insert(v.name, var_def.clone());
17821782
ctx.semantic_defs.insert(var_def.id(), var_def);
17831783
}
1784+
1785+
if variable_names_in_pattern.len() != arm_patterns_variables.len() {
1786+
ctx.diagnostics.report(pattern_syntax.stable_ptr(db), MissingVariableInPattern);
1787+
}
17841788
}
17851789

17861790
patterns
@@ -2112,7 +2116,13 @@ fn compute_expr_for_semantic<'db>(
21122116
&UnorderedHashMap::default(),
21132117
);
21142118
let variables = inner_pattern.variables(&new_ctx.arenas.patterns);
2119+
let mut variable_names_in_pattern = UnorderedHashSet::<_>::default();
21152120
for v in variables {
2121+
if !variable_names_in_pattern.insert(v.name) {
2122+
new_ctx
2123+
.diagnostics
2124+
.report(v.stable_ptr, VariableDefinedMultipleTimesInPattern(v.name));
2125+
}
21162126
let var_def = Binding::LocalVar(v.var.clone());
21172127
new_ctx.environment.variables.insert(v.name, var_def.clone());
21182128
new_ctx.semantic_defs.insert(var_def.id(), var_def);
@@ -4227,7 +4237,12 @@ pub fn compute_and_append_statement_semantic<'db>(
42274237
&UnorderedHashMap::default(),
42284238
);
42294239
let variables = pattern.variables(&ctx.arenas.patterns);
4240+
let mut variable_names_in_pattern = UnorderedHashSet::<_>::default();
42304241
for v in variables {
4242+
if !variable_names_in_pattern.insert(v.name) {
4243+
ctx.diagnostics
4244+
.report(v.stable_ptr, VariableDefinedMultipleTimesInPattern(v.name));
4245+
}
42314246
let var_def = Binding::LocalVar(v.var.clone());
42324247
if let Some(old_var) = ctx.environment.variables.insert(v.name, var_def.clone()) {
42334248
if matches!(old_var, Binding::LocalItem(_)) {

crates/cairo-lang-semantic/src/expr/test_data/for

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ error[E0006]: Identifier not found.
6363
//! > Test for loop with duplicate variables in pattern.
6464

6565
//! > test_runner_name
66-
test_function_diagnostics(expect_diagnostics: false)
66+
test_function_diagnostics(expect_diagnostics: true)
6767

6868
//! > function
6969
fn foo() {
@@ -76,3 +76,7 @@ foo
7676
//! > module_code
7777

7878
//! > expected_diagnostics
79+
error: Redefinition of variable name "_a" in pattern.
80+
--> lib.cairo:2:14
81+
for (_a, _a) in array![(1, 2)] {}
82+
^^

crates/cairo-lang-semantic/src/expr/test_data/pattern

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ error: Wrong number of tuple elements in pattern. Expected: 0. Got: 1.
276276
//! > Test duplicate variables in tuple pattern let.
277277

278278
//! > test_runner_name
279-
test_function_diagnostics(expect_diagnostics: false)
279+
test_function_diagnostics(expect_diagnostics: true)
280280

281281
//! > function
282282
fn foo() {
@@ -289,6 +289,10 @@ foo
289289
//! > module_code
290290

291291
//! > expected_diagnostics
292+
error: Redefinition of variable name "_a" in pattern.
293+
--> lib.cairo:2:14
294+
let (_a, _a) = (1, 2);
295+
^^
292296

293297
//! > ==========================================================================
294298

@@ -314,12 +318,12 @@ foo
314318
//! > module_code
315319

316320
//! > expected_diagnostics
317-
error: Missing variable in pattern.
318-
--> lib.cairo:3:9
321+
error: Redefinition of variable name "a" in pattern.
322+
--> lib.cairo:3:13
319323
(a, a) => a,
320-
^^^^^^
324+
^
321325

322-
error: Missing variable in pattern.
323-
--> lib.cairo:7:9
326+
error: Redefinition of variable name "b" in pattern.
327+
--> lib.cairo:7:19
324328
((b, _c), b) => b,
325-
^^^^^^^^^^^^
329+
^

0 commit comments

Comments
 (0)