diff options
Diffstat (limited to 'compiler/rustc_resolve/src/late/diagnostics.rs')
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 1493d5cc158..42455983575 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -459,7 +459,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { return (err, Vec::new()); } - let (found, mut candidates) = self.try_lookup_name_relaxed( + let (found, suggested_candidates, mut candidates) = self.try_lookup_name_relaxed( &mut err, source, path, @@ -478,7 +478,15 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); - fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error); + fallback |= self.suggest_typo( + &mut err, + source, + path, + following_seg, + span, + &base_error, + suggested_candidates, + ); if fallback { // Fallback label. @@ -589,7 +597,16 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: Span, res: Option<Res>, base_error: &BaseError, - ) -> (bool, Vec<ImportSuggestion>) { + ) -> (bool, FxHashSet<String>, Vec<ImportSuggestion>) { + let span = match following_seg { + Some(_) if path[0].ident.span.eq_ctxt(path[path.len() - 1].ident.span) => { + // The path `span` that comes in includes any following segments, which we don't + // want to replace in the suggestions. + path[0].ident.span.to(path[path.len() - 1].ident.span) + } + _ => span, + }; + let mut suggested_candidates = FxHashSet::default(); // Try to lookup name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; let is_expected = &|res| source.is_expected(res); @@ -646,6 +663,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { }; let msg = format!("{preamble}try using the variant's enum"); + suggested_candidates.extend( + enum_candidates + .iter() + .map(|(_variant_path, enum_ty_path)| enum_ty_path.clone()), + ); err.span_suggestions( span, msg, @@ -658,7 +680,8 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // Try finding a suitable replacement. let typo_sugg = self .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected) - .to_opt_suggestion(); + .to_opt_suggestion() + .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())); if let [segment] = path && !matches!(source, PathSource::Delegation) && self.self_type_is_available() @@ -719,7 +742,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } self.r.add_typo_suggestion(err, typo_sugg, ident_span); - return (true, candidates); + return (true, suggested_candidates, candidates); } // If the first argument in call is `self` suggest calling a method. @@ -737,7 +760,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { format!("self.{path_str}({args_snippet})"), Applicability::MachineApplicable, ); - return (true, candidates); + return (true, suggested_candidates, candidates); } } @@ -754,7 +777,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ) { // We do this to avoid losing a secondary span when we override the main error span. self.r.add_typo_suggestion(err, typo_sugg, ident_span); - return (true, candidates); + return (true, suggested_candidates, candidates); } } @@ -772,7 +795,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ident.span, format!("the binding `{path_str}` is available in a different scope in the same function"), ); - return (true, candidates); + return (true, suggested_candidates, candidates); } } } @@ -781,7 +804,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } - (false, candidates) + (false, suggested_candidates, candidates) } fn suggest_trait_and_bounds( @@ -869,13 +892,16 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { following_seg: Option<&Segment>, span: Span, base_error: &BaseError, + suggested_candidates: FxHashSet<String>, ) -> bool { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); let typo_sugg = self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); let mut fallback = false; - let typo_sugg = typo_sugg.to_opt_suggestion(); + let typo_sugg = typo_sugg + .to_opt_suggestion() + .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())); if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) { fallback = true; match self.diag_metadata.current_let_binding { |
