mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
resolve: Move get_traits_in_module_containing_item
to Resolver
This commit is contained in:
parent
e674422f86
commit
344a42e66e
@ -8,7 +8,7 @@
|
|||||||
use RibKind::*;
|
use RibKind::*;
|
||||||
|
|
||||||
use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
|
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 crate::{ResolutionError, Resolver, Segment, UseError};
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
@ -24,7 +24,6 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
|||||||
use rustc_hir::TraitCandidate;
|
use rustc_hir::TraitCandidate;
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_span::def_id::LocalDefId;
|
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use smallvec::{smallvec, SmallVec};
|
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();
|
ident.span = ident.span.normalize_to_macros_2_0();
|
||||||
let mut search_module = self.parent_scope.module;
|
let mut search_module = self.parent_scope.module;
|
||||||
loop {
|
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 =
|
search_module =
|
||||||
unwrap_or!(self.r.hygienic_lexical_parent(search_module, &mut ident.span), break);
|
unwrap_or!(self.r.hygienic_lexical_parent(search_module, &mut ident.span), break);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prelude) = self.r.prelude {
|
if let Some(prelude) = self.r.prelude {
|
||||||
if !search_module.no_implicit_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
|
found_traits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_traits_in_module_containing_item(
|
|
||||||
&mut self,
|
|
||||||
ident: Ident,
|
|
||||||
ns: Namespace,
|
|
||||||
module: Module<'a>,
|
|
||||||
found_traits: &mut Vec<TraitCandidate>,
|
|
||||||
) {
|
|
||||||
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> {
|
impl<'a> Resolver<'a> {
|
||||||
|
@ -43,9 +43,9 @@ use rustc_index::vec::IndexVec;
|
|||||||
use rustc_metadata::creader::{CStore, CrateLoader};
|
use rustc_metadata::creader::{CStore, CrateLoader};
|
||||||
use rustc_middle::hir::exports::ExportMap;
|
use rustc_middle::hir::exports::ExportMap;
|
||||||
use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn};
|
use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn};
|
||||||
use rustc_middle::span_bug;
|
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::{self, DefIdTree, ResolverOutputs};
|
use rustc_middle::ty::{self, DefIdTree, ResolverOutputs};
|
||||||
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||||
use rustc_session::Session;
|
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::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::{cmp, fmt, iter, ptr};
|
use std::{cmp, fmt, iter, ptr};
|
||||||
@ -1430,6 +1431,82 @@ impl<'a> Resolver<'a> {
|
|||||||
self.crate_loader.postprocess(krate);
|
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<TraitCandidate>,
|
||||||
|
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(
|
fn new_module(
|
||||||
&self,
|
&self,
|
||||||
parent: Module<'a>,
|
parent: Module<'a>,
|
||||||
|
Loading…
Reference in New Issue
Block a user