diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c21d3653a13be..0fe0aad06e6cc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -286,7 +286,8 @@ impl RibKind<'_> { #[derive(Debug)] pub(crate) struct Rib<'ra, R = Res> { pub bindings: FxIndexMap, - pub patterns_with_skipped_bindings: UnordMap)>>, + pub patterns_with_skipped_bindings: + UnordMap, Result<(), ErrorGuaranteed>)>>, pub kind: RibKind<'ra>, } @@ -4309,6 +4310,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .or_default() .push(( pat.span, + match rest { + ast::PatFieldsRest::Rest(span) => Some(*span), + _ => None, + }, match rest { ast::PatFieldsRest::Recovered(guar) => Err(*guar), _ => Ok(()), diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b126272583692..3ec755f7ea4f3 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1602,11 +1602,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { { for field in fields { if field.name == segment.ident.name { - if spans.iter().all(|(_, had_error)| had_error.is_err()) { + if spans.iter().all(|(_, _, had_error)| had_error.is_err()) { // This resolution error will likely be fixed by fixing a // syntax error in a pattern, so it is irrelevant to the user. let multispan: MultiSpan = - spans.iter().map(|(s, _)| *s).collect::>().into(); + spans.iter().map(|(s, _, _)| *s).collect::>().into(); err.span_note( multispan, "this pattern had a recovered parse error which likely lost \ @@ -1615,7 +1615,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.downgrade_to_delayed_bug(); } let ty = self.r.tcx.item_name(*def_id); - for (span, _) in spans { + for (span, dotdot_span, _) in spans { err.span_label( *span, format!( @@ -1623,6 +1623,14 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { available in `{ty}`", ), ); + if let Some(dotdot_span) = dotdot_span { + err.span_suggestion_hidden( + *dotdot_span, + format!("include `{field}` in the pattern"), + format!("{field}, .."), + Applicability::MaybeIncorrect, + ); + } } } } diff --git a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr index b8c6f1d867a19..ef0c2b84ff1b4 100644 --- a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr +++ b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr @@ -13,6 +13,8 @@ LL | if let Website { url, .. } = website { | ------------------- this pattern doesn't include `title`, which is available in `Website` LL | println!("[{}]({})", title, url); | ^^^^^ not found in this scope + | + = help: include `title` in the pattern error[E0425]: cannot find value `a` in this scope --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:28:20 @@ -22,6 +24,7 @@ LL | if let Foo::Bar { .. } = x { LL | println!("{a}"); | ^ | + = help: include `a` in the pattern help: a local variable with a similar name exists | LL - println!("{a}");