@@ -44,9 +44,9 @@ use rustc_index::vec::IndexVec;
44
44
use rustc_metadata:: creader:: { CStore , CrateLoader } ;
45
45
use rustc_middle:: hir:: exports:: ExportMap ;
46
46
use rustc_middle:: middle:: cstore:: { CrateStore , MetadataLoaderDyn } ;
47
+ use rustc_middle:: span_bug;
47
48
use rustc_middle:: ty:: query:: Providers ;
48
49
use rustc_middle:: ty:: { self , DefIdTree , ResolverOutputs } ;
49
- use rustc_middle:: { bug, span_bug} ;
50
50
use rustc_session:: lint;
51
51
use rustc_session:: lint:: { BuiltinLintDiagnostics , LintBuffer } ;
52
52
use rustc_session:: Session ;
@@ -1477,49 +1477,76 @@ impl<'a> Resolver<'a> {
1477
1477
self . crate_loader . postprocess ( krate) ;
1478
1478
}
1479
1479
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 (
1481
1516
& mut self ,
1482
- ident : Ident ,
1483
- ns : Namespace ,
1484
1517
module : Module < ' a > ,
1518
+ assoc_item : Option < ( Symbol , Namespace ) > ,
1485
1519
found_traits : & mut Vec < TraitCandidate > ,
1486
- parent_scope : & ParentScope < ' a > ,
1487
1520
) {
1488
- assert ! ( ns == TypeNS || ns == ValueNS ) ;
1489
1521
module. ensure_traits ( self ) ;
1490
1522
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
+ }
1491
1531
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
+ } )
1522
1548
}
1549
+ _ => true ,
1523
1550
}
1524
1551
}
1525
1552
@@ -3227,34 +3254,6 @@ impl<'a> Resolver<'a> {
3227
3254
} )
3228
3255
}
3229
3256
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
-
3258
3257
/// Rustdoc uses this to resolve things in a recoverable way. `ResolutionError<'a>`
3259
3258
/// isn't something that can be returned because it can't be made to live that long,
3260
3259
/// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
0 commit comments