diff options
Diffstat (limited to 'compiler/rustc_resolve/src/late/diagnostics.rs')
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 09f3e848766..660ac2d37cc 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -430,6 +430,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut err = self.r.dcx().struct_span_err(base_error.span, base_error.msg.clone()); err.code(code); + self.detect_missing_binding_available_from_pattern(&mut err, path, following_seg); self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); @@ -1120,6 +1121,65 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { true } + fn detect_missing_binding_available_from_pattern( + &mut self, + err: &mut Diag<'_>, + path: &[Segment], + following_seg: Option<&Segment>, + ) { + let [segment] = path else { return }; + let None = following_seg else { return }; + 'outer: for rib in self.ribs[ValueNS].iter().rev() { + for (def_id, spans) in &rib.patterns_with_skipped_bindings { + if let Some(fields) = self.r.field_idents(*def_id) { + for field in fields { + if field.name == segment.ident.name { + if spans.iter().all(|(_, was_recovered)| *was_recovered) { + // 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::<Vec<_>>().into(); + err.span_note( + multispan, + "this pattern had a recovered parse error which likely \ + lost the expected fields", + ); + err.downgrade_to_delayed_bug(); + } + let mut multispan: MultiSpan = spans + .iter() + .filter(|(_, was_recovered)| !was_recovered) + .map(|(sp, _)| *sp) + .collect::<Vec<_>>() + .into(); + let def_span = self.r.def_span(*def_id); + let ty = self.r.tcx.item_name(*def_id); + multispan.push_span_label(def_span, String::new()); + multispan.push_span_label(field.span, "defined here".to_string()); + for (span, _) in spans.iter().filter(|(_, r)| !r) { + multispan.push_span_label( + *span, + format!( + "this pattern doesn't include `{field}`, which is \ + available in `{ty}`", + ), + ); + } + err.span_note( + multispan, + format!( + "`{ty}` has a field `{field}` which could have been included \ + in this pattern, but it wasn't", + ), + ); + break 'outer; + } + } + } + } + } + } + fn suggest_at_operator_in_slice_pat_with_range( &mut self, err: &mut Diag<'_>, |
