diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 0dbb6269d2e..d113eb22aba 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -8,7 +8,7 @@ use RibKind::*; use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; -use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult}; +use crate::{Module, ModuleOrUniformRoot, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; @@ -24,7 +24,6 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::TraitCandidate; use rustc_middle::{bug, span_bug}; use rustc_session::lint; -use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -2342,95 +2341,31 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident.span = ident.span.normalize_to_macros_2_0(); let mut search_module = self.parent_scope.module; loop { - self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits); + self.r.get_traits_in_module_containing_item( + ident, + ns, + search_module, + &mut found_traits, + &self.parent_scope, + ); search_module = unwrap_or!(self.r.hygienic_lexical_parent(search_module, &mut ident.span), break); } if let Some(prelude) = self.r.prelude { if !search_module.no_implicit_prelude { - self.get_traits_in_module_containing_item(ident, ns, prelude, &mut found_traits); + self.r.get_traits_in_module_containing_item( + ident, + ns, + prelude, + &mut found_traits, + &self.parent_scope, + ); } } found_traits } - - fn get_traits_in_module_containing_item( - &mut self, - ident: Ident, - ns: Namespace, - module: Module<'a>, - found_traits: &mut Vec, - ) { - assert!(ns == TypeNS || ns == ValueNS); - let mut traits = module.traits.borrow_mut(); - if traits.is_none() { - let mut collected_traits = Vec::new(); - module.for_each_child(self.r, |_, name, ns, binding| { - if ns != TypeNS { - return; - } - match binding.res() { - Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => { - collected_traits.push((name, binding)) - } - _ => (), - } - }); - *traits = Some(collected_traits.into_boxed_slice()); - } - - for &(trait_name, binding) in traits.as_ref().unwrap().iter() { - // Traits have pseudo-modules that can be used to search for the given ident. - if let Some(module) = binding.module() { - let mut ident = ident; - if ident.span.glob_adjust(module.expansion, binding.span).is_none() { - continue; - } - if self - .r - .resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(module), - ident, - ns, - &self.parent_scope, - false, - module.span, - ) - .is_ok() - { - let import_ids = self.find_transitive_imports(&binding.kind, trait_name); - let trait_def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); - } - } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() { - // For now, just treat all trait aliases as possible candidates, since we don't - // know if the ident is somewhere in the transitive bounds. - let import_ids = self.find_transitive_imports(&binding.kind, trait_name); - let trait_def_id = binding.res().def_id(); - found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); - } else { - bug!("candidate is not trait or trait alias?") - } - } - } - - fn find_transitive_imports( - &mut self, - mut kind: &NameBindingKind<'_>, - trait_name: Ident, - ) -> SmallVec<[LocalDefId; 1]> { - let mut import_ids = smallvec![]; - while let NameBindingKind::Import { import, binding, .. } = kind { - let id = self.r.local_def_id(import.id); - self.r.maybe_unused_trait_imports.insert(id); - self.r.add_to_glob_map(&import, trait_name); - import_ids.push(id); - kind = &binding.kind; - } - import_ids - } } impl<'a> Resolver<'a> { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 36b7a430f78..c24a38bcadf 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -43,9 +43,9 @@ use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::hir::exports::ExportMap; use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn}; -use rustc_middle::span_bug; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, ResolverOutputs}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; @@ -54,6 +54,7 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; use std::{cmp, fmt, iter, ptr}; @@ -1430,6 +1431,82 @@ impl<'a> Resolver<'a> { self.crate_loader.postprocess(krate); } + fn get_traits_in_module_containing_item( + &mut self, + ident: Ident, + ns: Namespace, + module: Module<'a>, + found_traits: &mut Vec, + parent_scope: &ParentScope<'a>, + ) { + assert!(ns == TypeNS || ns == ValueNS); + let mut traits = module.traits.borrow_mut(); + if traits.is_none() { + let mut collected_traits = Vec::new(); + module.for_each_child(self, |_, name, ns, binding| { + if ns != TypeNS { + return; + } + match binding.res() { + Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => { + collected_traits.push((name, binding)) + } + _ => (), + } + }); + *traits = Some(collected_traits.into_boxed_slice()); + } + + for &(trait_name, binding) in traits.as_ref().unwrap().iter() { + // Traits have pseudo-modules that can be used to search for the given ident. + if let Some(module) = binding.module() { + let mut ident = ident; + if ident.span.glob_adjust(module.expansion, binding.span).is_none() { + continue; + } + if self + .resolve_ident_in_module_unadjusted( + ModuleOrUniformRoot::Module(module), + ident, + ns, + parent_scope, + false, + module.span, + ) + .is_ok() + { + let import_ids = self.find_transitive_imports(&binding.kind, trait_name); + let trait_def_id = module.def_id().unwrap(); + found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); + } + } else if let Res::Def(DefKind::TraitAlias, _) = binding.res() { + // For now, just treat all trait aliases as possible candidates, since we don't + // know if the ident is somewhere in the transitive bounds. + let import_ids = self.find_transitive_imports(&binding.kind, trait_name); + let trait_def_id = binding.res().def_id(); + found_traits.push(TraitCandidate { def_id: trait_def_id, import_ids }); + } else { + bug!("candidate is not trait or trait alias?") + } + } + } + + fn find_transitive_imports( + &mut self, + mut kind: &NameBindingKind<'_>, + trait_name: Ident, + ) -> SmallVec<[LocalDefId; 1]> { + let mut import_ids = smallvec![]; + while let NameBindingKind::Import { import, binding, .. } = kind { + let id = self.local_def_id(import.id); + self.maybe_unused_trait_imports.insert(id); + self.add_to_glob_map(&import, trait_name); + import_ids.push(id); + kind = &binding.kind; + } + import_ids + } + fn new_module( &self, parent: Module<'a>,