Unnamed repository; edit this file 'description' to name the repository.
ide-diagnostics: emit error for duplicate field in record pattern
Resolves a FIXME at hir-ty/src/infer/pat.rs that allowed record patterns like `let S { foo, foo } = ...;` to type-check with no error. Pushes the InferenceDiagnostic::DuplicateField variant (added in rust-lang/rust-analyzer#22235) at the pattern site; the cooked diagnostic already supports ExprOrPatId, so no plumbing changes are needed. Tests: struct pattern positive, enum variant pattern positive. Part of rust-lang/rust-analyzer#22140. Signed-off-by: Onyeka Obi <[email protected]>
Onyeka Obi 6 days ago
parent 73ca1d4 · commit af15884
-rw-r--r--crates/hir-ty/src/infer/pat.rs5
-rw-r--r--crates/ide-diagnostics/src/handlers/duplicate_field.rs39
2 files changed, 43 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 5d8b1196c0..ca2a0d87f7 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -1185,7 +1185,10 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
for (field_idx, field) in fields.iter().enumerate() {
match used_fields.entry(field.name.clone()) {
Occupied(_occupied) => {
- // FIXME: Emit an error, field specified twice.
+ self.push_diagnostic(InferenceDiagnostic::DuplicateField {
+ field: field.pat.into(),
+ variant,
+ });
}
Vacant(vacant) => {
vacant.insert(field_idx);
diff --git a/crates/ide-diagnostics/src/handlers/duplicate_field.rs b/crates/ide-diagnostics/src/handlers/duplicate_field.rs
index 13d594066d..08748bf8af 100644
--- a/crates/ide-diagnostics/src/handlers/duplicate_field.rs
+++ b/crates/ide-diagnostics/src/handlers/duplicate_field.rs
@@ -81,4 +81,43 @@ fn main() {
"#,
);
}
+
+ #[test]
+ fn duplicate_field_in_struct_pattern() {
+ check_diagnostics(
+ r#"
+struct S { foo: i32, bar: i32 }
+fn f(s: S) {
+ let S {
+ foo,
+ bar,
+ foo,
+ //^^^ error: field specified more than once
+ ..
+ } = s;
+ let _ = (foo, bar);
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn duplicate_field_in_enum_variant_pattern() {
+ check_diagnostics(
+ r#"
+enum E { V { foo: i32, bar: i32 } }
+fn f(e: E) {
+ match e {
+ E::V {
+ foo,
+ bar,
+ foo,
+ //^^^ error: field specified more than once
+ ..
+ } => { let _ = (foo, bar); }
+ }
+}
+"#,
+ );
+ }
}