@@ -44,9 +44,9 @@ use rustc_index::vec::IndexVec;
4444use rustc_metadata:: creader:: { CStore , CrateLoader } ;
4545use rustc_middle:: hir:: exports:: ExportMap ;
4646use rustc_middle:: middle:: cstore:: { CrateStore , MetadataLoaderDyn } ;
47+ use rustc_middle:: span_bug;
4748use rustc_middle:: ty:: query:: Providers ;
4849use rustc_middle:: ty:: { self , DefIdTree , ResolverOutputs } ;
49- use rustc_middle:: { bug, span_bug} ;
5050use rustc_session:: lint;
5151use rustc_session:: lint:: { BuiltinLintDiagnostics , LintBuffer } ;
5252use rustc_session:: Session ;
@@ -1477,49 +1477,76 @@ impl<'a> Resolver<'a> {
14771477 self . crate_loader . postprocess ( krate) ;
14781478 }
14791479
1480- fn get_traits_in_module_containing_item (
1480+ pub fn traits_in_scope (
1481+ & mut self ,
1482+ current_trait : Option < Module < ' a > > ,
1483+ parent_scope : & ParentScope < ' a > ,
1484+ ctxt : SyntaxContext ,
1485+ assoc_item : Option < ( Symbol , Namespace ) > ,
1486+ ) -> Vec < TraitCandidate > {
1487+ let mut found_traits = Vec :: new ( ) ;
1488+
1489+ if let Some ( module) = current_trait {
1490+ if self . trait_may_have_item ( Some ( module) , assoc_item) {
1491+ let def_id = module. def_id ( ) . unwrap ( ) ;
1492+ found_traits. push ( TraitCandidate { def_id, import_ids : smallvec ! [ ] } ) ;
1493+ }
1494+ }
1495+
1496+ self . visit_scopes ( ScopeSet :: All ( TypeNS , false ) , parent_scope, ctxt, |this, scope, _, _| {
1497+ match scope {
1498+ Scope :: Module ( module) => {
1499+ this. traits_in_module ( module, assoc_item, & mut found_traits) ;
1500+ }
1501+ Scope :: StdLibPrelude => {
1502+ if let Some ( module) = this. prelude {
1503+ this. traits_in_module ( module, assoc_item, & mut found_traits) ;
1504+ }
1505+ }
1506+ Scope :: ExternPrelude | Scope :: ToolPrelude | Scope :: BuiltinTypes => { }
1507+ _ => unreachable ! ( ) ,
1508+ }
1509+ None :: < ( ) >
1510+ } ) ;
1511+
1512+ found_traits
1513+ }
1514+
1515+ fn traits_in_module (
14811516 & mut self ,
1482- ident : Ident ,
1483- ns : Namespace ,
14841517 module : Module < ' a > ,
1518+ assoc_item : Option < ( Symbol , Namespace ) > ,
14851519 found_traits : & mut Vec < TraitCandidate > ,
1486- parent_scope : & ParentScope < ' a > ,
14871520 ) {
1488- assert ! ( ns == TypeNS || ns == ValueNS ) ;
14891521 module. ensure_traits ( self ) ;
14901522 let traits = module. traits . borrow ( ) ;
1523+ for ( trait_name, trait_binding) in traits. as_ref ( ) . unwrap ( ) . iter ( ) {
1524+ if self . trait_may_have_item ( trait_binding. module ( ) , assoc_item) {
1525+ let def_id = trait_binding. res ( ) . def_id ( ) ;
1526+ let import_ids = self . find_transitive_imports ( & trait_binding. kind , * trait_name) ;
1527+ found_traits. push ( TraitCandidate { def_id, import_ids } ) ;
1528+ }
1529+ }
1530+ }
14911531
1492- for & ( trait_name, binding) in traits. as_ref ( ) . unwrap ( ) . iter ( ) {
1493- // Traits have pseudo-modules that can be used to search for the given ident.
1494- if let Some ( module) = binding. module ( ) {
1495- let mut ident = ident;
1496- if ident. span . glob_adjust ( module. expansion , binding. span ) . is_none ( ) {
1497- continue ;
1498- }
1499- if self
1500- . resolve_ident_in_module_unadjusted (
1501- ModuleOrUniformRoot :: Module ( module) ,
1502- ident,
1503- ns,
1504- parent_scope,
1505- false ,
1506- module. span ,
1507- )
1508- . is_ok ( )
1509- {
1510- let import_ids = self . find_transitive_imports ( & binding. kind , trait_name) ;
1511- let trait_def_id = module. def_id ( ) . unwrap ( ) ;
1512- found_traits. push ( TraitCandidate { def_id : trait_def_id, import_ids } ) ;
1513- }
1514- } else if let Res :: Def ( DefKind :: TraitAlias , _) = binding. res ( ) {
1515- // For now, just treat all trait aliases as possible candidates, since we don't
1516- // know if the ident is somewhere in the transitive bounds.
1517- let import_ids = self . find_transitive_imports ( & binding. kind , trait_name) ;
1518- let trait_def_id = binding. res ( ) . def_id ( ) ;
1519- found_traits. push ( TraitCandidate { def_id : trait_def_id, import_ids } ) ;
1520- } else {
1521- bug ! ( "candidate is not trait or trait alias?" )
1532+ // List of traits in scope is pruned on best effort basis. We reject traits not having an
1533+ // associated item with the given name and namespace (if specified). This is a conservative
1534+ // optimization, proper hygienic type-based resolution of associated items is done in typeck.
1535+ // We don't reject trait aliases (`trait_module == None`) because we don't have access to their
1536+ // associated items.
1537+ fn trait_may_have_item (
1538+ & mut self ,
1539+ trait_module : Option < Module < ' a > > ,
1540+ assoc_item : Option < ( Symbol , Namespace ) > ,
1541+ ) -> bool {
1542+ match ( trait_module, assoc_item) {
1543+ ( Some ( trait_module) , Some ( ( name, ns) ) ) => {
1544+ self . resolutions ( trait_module) . borrow ( ) . iter ( ) . any ( |resolution| {
1545+ let ( & BindingKey { ident : assoc_ident, ns : assoc_ns, .. } , _) = resolution;
1546+ assoc_ns == ns && assoc_ident. name == name
1547+ } )
15221548 }
1549+ _ => true ,
15231550 }
15241551 }
15251552
@@ -3227,34 +3254,6 @@ impl<'a> Resolver<'a> {
32273254 } )
32283255 }
32293256
3230- /// This is equivalent to `get_traits_in_module_containing_item`, but without filtering by the associated item.
3231- ///
3232- /// This is used by rustdoc for intra-doc links.
3233- pub fn traits_in_scope ( & mut self , module_id : DefId ) -> Vec < TraitCandidate > {
3234- let module = self . get_module ( module_id) ;
3235- module. ensure_traits ( self ) ;
3236- let traits = module. traits . borrow ( ) ;
3237- let to_candidate =
3238- |this : & mut Self , & ( trait_name, binding) : & ( Ident , & NameBinding < ' _ > ) | TraitCandidate {
3239- def_id : binding. res ( ) . def_id ( ) ,
3240- import_ids : this. find_transitive_imports ( & binding. kind , trait_name) ,
3241- } ;
3242-
3243- let mut candidates: Vec < _ > =
3244- traits. as_ref ( ) . unwrap ( ) . iter ( ) . map ( |x| to_candidate ( self , x) ) . collect ( ) ;
3245-
3246- if let Some ( prelude) = self . prelude {
3247- if !module. no_implicit_prelude {
3248- prelude. ensure_traits ( self ) ;
3249- candidates. extend (
3250- prelude. traits . borrow ( ) . as_ref ( ) . unwrap ( ) . iter ( ) . map ( |x| to_candidate ( self , x) ) ,
3251- ) ;
3252- }
3253- }
3254-
3255- candidates
3256- }
3257-
32583257 /// Rustdoc uses this to resolve things in a recoverable way. `ResolutionError<'a>`
32593258 /// isn't something that can be returned because it can't be made to live that long,
32603259 /// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
0 commit comments