Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22851 from TheDoctor314/fixme-error-incomplete-struct-pat
fix: add diagnostic for struct patterns which don't specify sub-patterns for its fields
Chayim Refael Friedman 2 weeks ago
parent a121446 · parent bca0658 · commit efc96ed
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs12
-rw-r--r--crates/hir-ty/src/infer.rs8
-rw-r--r--crates/hir-ty/src/infer/pat.rs10
-rw-r--r--crates/hir/src/diagnostics.rs46
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs4
5 files changed, 63 insertions, 17 deletions
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index fd8d7e02a5..0947f456ad 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -157,18 +157,6 @@ 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 5db5be0fd1..2cb6666672 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -538,6 +538,14 @@ pub enum InferenceDiagnostic {
#[type_visitable(ignore)]
kind: ReturnKind,
},
+ RecordMissingFields {
+ #[type_visitable(ignore)]
+ record: ExprOrPatId,
+ #[type_visitable(ignore)]
+ variant: VariantId,
+ #[type_visitable(ignore)]
+ missed_fields: Vec<LocalFieldId>,
+ },
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 91e0619fd3..f464de06cd 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -10,8 +10,8 @@ use hir_def::{
AdtId, LocalFieldId, VariantId,
expr_store::path::Path,
hir::{
- BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatIdPacked, Literal, Pat, PatId,
- RecordFieldPat,
+ BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, ExprOrPatIdPacked, Literal, Pat,
+ PatId, RecordFieldPat,
},
resolver::ValueNs,
signatures::VariantFields,
@@ -1248,7 +1248,11 @@ impl<'db> InferenceContext<'db> {
self.push_diagnostic(InferenceDiagnostic::UnionPatHasRest { pat });
}
} else if !unmentioned_fields.is_empty() && !has_rest_pat {
- // FIXME: Emit an error.
+ self.push_diagnostic(InferenceDiagnostic::RecordMissingFields {
+ record: ExprOrPatId::PatId(pat),
+ variant,
+ missed_fields: unmentioned_fields.into_iter().map(|f| f.0).collect(),
+ })
}
}
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 2edcc63c44..91bb7b481f 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -1141,6 +1141,52 @@ impl<'db> AnyDiagnostic<'db> {
&InferenceDiagnostic::ReturnOutsideFunction { expr, kind } => {
ReturnOutsideFunction { expr: expr_syntax(expr)?, kind }.into()
}
+ &InferenceDiagnostic::RecordMissingFields { record, variant, ref missed_fields } => {
+ let record = expr_or_pat_syntax(record)?;
+ let file = record.file_id;
+ let root = record.file_syntax(db);
+ let variant_data = variant.fields(db);
+ let missed_fields = missed_fields
+ .iter()
+ .map(|&idx| {
+ (
+ variant_data.fields()[idx].name.clone(),
+ Field { parent: variant.into(), id: idx },
+ )
+ })
+ .collect();
+ match record.value.to_node(&root) {
+ Either::Left(ast::Expr::RecordExpr(record_expr))
+ if record_expr.record_expr_field_list().is_some() =>
+ {
+ let field_list_parent_path =
+ record_expr.path().map(|path| AstPtr::new(&path));
+ return Some(
+ MissingFields {
+ file,
+ field_list_parent: AstPtr::new(&Either::Left(record_expr)),
+ field_list_parent_path,
+ missed_fields,
+ }
+ .into(),
+ );
+ }
+ Either::Right(ast::Pat::RecordPat(record_pat))
+ if record_pat.record_pat_field_list().is_some() =>
+ {
+ let field_list_parent_path =
+ record_pat.path().map(|path| AstPtr::new(&path));
+ MissingFields {
+ file,
+ field_list_parent: AstPtr::new(&Either::Right(record_pat)),
+ field_list_parent_path,
+ missed_fields,
+ }
+ .into()
+ }
+ _ => return None,
+ }
+ }
})
}
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index 2030be4368..639be5e85a 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -274,7 +274,7 @@ fn get_default_constructor(
#[cfg(test)]
mod tests {
- use crate::tests::{check_diagnostics, check_fix, check_no_fix};
+ use crate::tests::{check_diagnostics, check_fix, check_has_fix, check_no_fix};
#[test]
fn missing_record_pat_field_diagnostic() {
@@ -829,7 +829,7 @@ fn f() {
#[test]
fn test_fill_struct_pat_fields_partial() {
- check_fix(
+ check_has_fix(
r#"
struct S { a: &'static str, b: i32 }