diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 58 |
2 files changed, 64 insertions, 5 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 744dcf0db84..bca95ce54ad 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3503,7 +3503,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let report_errors = |this: &mut Self, res: Option<Res>| { if this.should_report_errs() { let (err, candidates) = - this.smart_resolve_report_errors(path, path_span, source, res); + this.smart_resolve_report_errors(path, path, path_span, source, res); let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); @@ -3560,8 +3560,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { _ => return Some(parent_err), }; - let (mut err, candidates) = - this.smart_resolve_report_errors(prefix_path, path_span, PathSource::Type, None); + let (mut err, candidates) = this.smart_resolve_report_errors( + prefix_path, + path, + path_span, + PathSource::Type, + None, + ); // There are two different error messages user might receive at // this point: diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c62fc031a16..9fec7cc3def 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -4,6 +4,7 @@ use crate::late::{LifetimeBinderKind, LifetimeRes, LifetimeRibKind, LifetimeUseS use crate::{errors, path_names_to_string}; use crate::{Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; +use rustc_hir::def::Namespace::{self, *}; use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt}; use rustc_ast::{ @@ -17,7 +18,6 @@ use rustc_errors::{ MultiSpan, }; use rustc_hir as hir; -use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::PrimTy; @@ -221,10 +221,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let suggestion = if self.current_trait_ref.is_none() && let Some((fn_kind, _)) = self.diagnostic_metadata.current_function && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt() + && let FnKind::Fn(_, _, sig, ..) = fn_kind && let Some(items) = self.diagnostic_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind && i.ident.name == item_str.name + // don't suggest if the item is in Fn signature arguments + // issue #112590 + && !sig.span.contains(item_span) { debug!(?item_str.name); return true @@ -318,11 +322,56 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } + /// Try to suggest for a module path that cannot be resolved. + /// Such as `fmt::Debug` where `fmt` is not resolved without importing, + /// here we search with `lookup_import_candidates` for a module named `fmt` + /// with `TypeNS` as namespace. + /// + /// We need a separate function here because we won't suggest for a path with single segment + /// and we won't change `SourcePath` api `is_expected` to match `Type` with `DefKind::Mod` + pub(crate) fn smart_resolve_partial_mod_path_errors( + &mut self, + prefix_path: &[Segment], + path: &[Segment], + ) -> Vec<ImportSuggestion> { + let next_seg = if path.len() >= prefix_path.len() + 1 && prefix_path.len() == 1 { + path.get(prefix_path.len()) + } else { + None + }; + if let Some(segment) = prefix_path.last() && + let Some(next_seg) = next_seg { + let candidates = self.r.lookup_import_candidates( + segment.ident, + Namespace::TypeNS, + &self.parent_scope, + &|res: Res| matches!(res, Res::Def(DefKind::Mod, _)), + ); + // double check next seg is valid + candidates + .into_iter() + .filter(|candidate| { + if let Some(def_id) = candidate.did && + let Some(module) = self.r.get_module(def_id) { + self.r.resolutions(module).borrow().iter().any(|(key, _r)| { + key.ident.name == next_seg.ident.name + }) + } else { + false + } + }) + .collect::<Vec<_>>() + } else { + Vec::new() + } + } + /// Handles error reporting for `smart_resolve_path_fragment` function. /// Creates base error and amends it with one short label and possibly some longer helps/notes. pub(crate) fn smart_resolve_report_errors( &mut self, path: &[Segment], + full_path: &[Segment], span: Span, source: PathSource<'_>, res: Option<Res>, @@ -364,7 +413,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } let (found, candidates) = - self.try_lookup_name_relaxed(&mut err, source, path, span, res, &base_error); + self.try_lookup_name_relaxed(&mut err, source, path, full_path, span, res, &base_error); if found { return (err, candidates); } @@ -470,6 +519,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], + full_path: &[Segment], span: Span, res: Option<Res>, base_error: &BaseError, @@ -639,6 +689,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } + if candidates.is_empty() { + candidates = self.smart_resolve_partial_mod_path_errors(path, full_path); + } + return (false, candidates); } |
