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
| -rw-r--r-- | crates/hir-ty/src/diagnostics/expr.rs | 12 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 8 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/pat.rs | 10 | ||||
| -rw-r--r-- | crates/hir/src/diagnostics.rs | 46 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/missing_fields.rs | 4 |
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 } |