Unnamed repository; edit this file 'description' to name the repository.
feat(ide-diagnostics): add diagnostics for invalid union patterns
AI-assisted: I used an LLM to guide me through the debugging process. all code was reviewed and tested.
dotacow 7 weeks ago
parent 71b0fd2 · commit 63fa044
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs11
-rw-r--r--crates/hir-ty/src/infer.rs8
-rw-r--r--crates/hir-ty/src/infer/pat.rs8
-rw-r--r--crates/hir/src/diagnostics.rs16
-rw-r--r--crates/ide-diagnostics/src/handlers/record_pat_missing_fields.rs43
-rw-r--r--crates/ide-diagnostics/src/handlers/union_pat_has_rest.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/union_pat_must_have_exactly_one_field.rs4
-rw-r--r--crates/ide-diagnostics/src/lib.rs4
8 files changed, 15 insertions, 81 deletions
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index e512915ccc..760ebd27e0 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -158,6 +158,17 @@ impl<'db> ExprValidator<'db> {
}
}
+ for (id, pat) in body.pats() {
+ if let Some((variant, missed_fields)) =
+ record_pattern_missing_fields(db, self.infer, id, pat)
+ {
+ self.diagnostics.push(BodyValidationDiagnostic::RecordMissingFields {
+ record: Either::Right(id),
+ variant,
+ missed_fields,
+ });
+ }
+ }
}
fn validate_call(
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index fc1e77efce..d9486fb0eb 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -383,14 +383,6 @@ pub enum InferenceDiagnostic {
#[type_visitable(ignore)]
pat: PatId,
},
- RecordPatMissingFields {
- #[type_visitable(ignore)]
- pat: PatId,
- #[type_visitable(ignore)]
- variant: VariantId,
- #[type_visitable(ignore)]
- missing_fields: Vec<LocalFieldId>,
- },
FunctionalRecordUpdateOnNonStruct {
#[type_visitable(ignore)]
base_expr: ExprId,
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index e876375cbc..2583054fcd 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -1247,13 +1247,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
self.push_diagnostic(InferenceDiagnostic::UnionPatHasRest { pat });
}
} else if !unmentioned_fields.is_empty() && !has_rest_pat {
- let missing_fields =
- unmentioned_fields.iter().map(|(field_id, _)| *field_id).collect();
- self.push_diagnostic(InferenceDiagnostic::RecordPatMissingFields {
- pat,
- variant,
- missing_fields,
- });
+ // FIXME: Emit an error.
}
}
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 77f227b841..f21f906772 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -176,7 +176,6 @@ diagnostics![AnyDiagnostic<'db> ->
UnionExprMustHaveExactlyOneField,
UnionPatMustHaveExactlyOneField,
UnionPatHasRest,
- RecordPatMissingFields,
UnimplementedTrait<'db>,
];
@@ -639,12 +638,6 @@ pub struct UnionPatHasRest {
}
#[derive(Debug)]
-pub struct RecordPatMissingFields {
- pub pat: InFile<ExprOrPatPtr>,
- pub missed_fields: Vec<Name>,
-}
-
-#[derive(Debug)]
pub struct InvalidLhsOfAssignment {
pub lhs: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
}
@@ -969,15 +962,6 @@ impl<'db> AnyDiagnostic<'db> {
let pat = pat_syntax(pat)?.map(Into::into);
UnionPatHasRest { pat }.into()
}
- InferenceDiagnostic::RecordPatMissingFields { pat, variant, missing_fields } => {
- let pat = pat_syntax(*pat)?.map(Into::into);
- let variant_data = variant.fields(db);
- let missed_fields = missing_fields
- .iter()
- .map(|field_id| variant_data.fields()[*field_id].name.clone())
- .collect();
- RecordPatMissingFields { pat, missed_fields }.into()
- }
&InferenceDiagnostic::FunctionalRecordUpdateOnNonStruct { base_expr } => {
FunctionalRecordUpdateOnNonStruct { base_expr: expr_syntax(base_expr)? }.into()
}
diff --git a/crates/ide-diagnostics/src/handlers/record_pat_missing_fields.rs b/crates/ide-diagnostics/src/handlers/record_pat_missing_fields.rs
deleted file mode 100644
index 5ef4b1b045..0000000000
--- a/crates/ide-diagnostics/src/handlers/record_pat_missing_fields.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use stdx::format_to;
-
-use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
-
-// Diagnostic: record-pat-missing-fields
-//
-// This diagnostic is triggered if a record pattern omits fields without `..`.
-pub(crate) fn record_pat_missing_fields(
- ctx: &DiagnosticsContext<'_, '_>,
- d: &hir::RecordPatMissingFields,
-) -> Diagnostic {
- let mut message = String::from("missing structure fields:\n");
- for field in &d.missed_fields {
- format_to!(message, "- {}\n", field.display(ctx.sema.db, ctx.edition));
- }
-
- Diagnostic::new_with_syntax_node_ptr(
- ctx,
- DiagnosticCode::RustcHardError("E0063"),
- message,
- d.pat.map(Into::into),
- )
- .stable()
-}
-
-#[cfg(test)]
-mod tests {
- use crate::tests::check_diagnostics;
-
- #[test]
- fn record_pat_missing_fields() {
- check_diagnostics(
- r#"
-struct S { foo: i32, bar: () }
-fn baz(s: S) {
- let S { foo: _ } = s;
- //^ error: missing structure fields:
- //| - bar
-}
-"#,
- );
- }
-}
diff --git a/crates/ide-diagnostics/src/handlers/union_pat_has_rest.rs b/crates/ide-diagnostics/src/handlers/union_pat_has_rest.rs
index 03694f621c..9333118719 100644
--- a/crates/ide-diagnostics/src/handlers/union_pat_has_rest.rs
+++ b/crates/ide-diagnostics/src/handlers/union_pat_has_rest.rs
@@ -32,7 +32,7 @@ union Bird {
fn main(bird: Bird) {
unsafe {
let Bird { pigeon: 0, .. } = bird;
- // ^^^^^^^^^^^^^^^^^^^^^ error: union patterns cannot use `..`
+ //^^^^^^^^^^^^^^^^^^^^^^ error: union patterns cannot use `..`
}
}
"#,
diff --git a/crates/ide-diagnostics/src/handlers/union_pat_must_have_exactly_one_field.rs b/crates/ide-diagnostics/src/handlers/union_pat_must_have_exactly_one_field.rs
index f78514cd3c..5c229211e1 100644
--- a/crates/ide-diagnostics/src/handlers/union_pat_must_have_exactly_one_field.rs
+++ b/crates/ide-diagnostics/src/handlers/union_pat_must_have_exactly_one_field.rs
@@ -32,9 +32,9 @@ union Bird {
fn main(bird: Bird) {
unsafe {
let Bird {} = bird;
- // ^^^^^^^ error: union patterns should have exactly one field
+ //^^^^^^^ error: union patterns should have exactly one field
let Bird { pigeon: 0, turtledove: 1 } = bird;
- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: union patterns should have exactly one field
+ //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: union patterns should have exactly one field
}
}
"#,
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index d99f71db76..62b5106ada 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -59,7 +59,6 @@ mod handlers {
pub(crate) mod mismatched_arg_count;
pub(crate) mod mismatched_array_pat_len;
pub(crate) mod missing_fields;
- pub(crate) mod record_pat_missing_fields;
pub(crate) mod missing_lifetime;
pub(crate) mod missing_match_arms;
pub(crate) mod missing_unsafe;
@@ -475,9 +474,6 @@ pub fn semantic_diagnostics(
AnyDiagnostic::MismatchedArgCount(d) => handlers::mismatched_arg_count::mismatched_arg_count(&ctx, &d),
AnyDiagnostic::MismatchedArrayPatLen(d) => handlers::mismatched_array_pat_len::mismatched_array_pat_len(&ctx, &d),
AnyDiagnostic::MissingFields(d) => handlers::missing_fields::missing_fields(&ctx, &d),
- AnyDiagnostic::RecordPatMissingFields(d) => {
- handlers::record_pat_missing_fields::record_pat_missing_fields(&ctx, &d)
- }
AnyDiagnostic::MissingMatchArms(d) => handlers::missing_match_arms::missing_match_arms(&ctx, &d),
AnyDiagnostic::MissingUnsafe(d) => handlers::missing_unsafe::missing_unsafe(&ctx, &d),
AnyDiagnostic::MovedOutOfRef(d) => handlers::moved_out_of_ref::moved_out_of_ref(&ctx, &d),