@@ -1952,9 +1952,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
19521952 "access to extern crates through prelude is experimental" ) . emit ( ) ;
19531953 }
19541954
1955- let crate_id = self . crate_loader . process_path_extern ( ident. name , ident. span ) ;
1956- let crate_root = self . get_module ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } ) ;
1957- self . populate_module_if_necessary ( crate_root) ;
1955+ let crate_root = self . load_extern_prelude_crate_if_needed ( ident) ;
19581956
19591957 let binding = ( crate_root, ty:: Visibility :: Public ,
19601958 ident. span , Mark :: root ( ) ) . to_name_binding ( self . arenas ) ;
@@ -1982,6 +1980,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
19821980 None
19831981 }
19841982
1983+ fn load_extern_prelude_crate_if_needed ( & mut self , ident : Ident ) -> Module < ' a > {
1984+ let crate_id = self . crate_loader . process_path_extern ( ident. name , ident. span ) ;
1985+ let crate_root = self . get_module ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } ) ;
1986+ self . populate_module_if_necessary ( & crate_root) ;
1987+ crate_root
1988+ }
1989+
19851990 fn hygienic_lexical_parent ( & mut self , module : Module < ' a > , span : & mut Span )
19861991 -> Option < Module < ' a > > {
19871992 if !module. expansion . is_descendant_of ( span. ctxt ( ) . outer ( ) ) {
@@ -4228,24 +4233,20 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
42284233 }
42294234 }
42304235
4231- /// When name resolution fails, this method can be used to look up candidate
4232- /// entities with the expected name. It allows filtering them using the
4233- /// supplied predicate (which should be used to only accept the types of
4234- /// definitions expected e.g. traits). The lookup spans across all crates.
4235- ///
4236- /// NOTE: The method does not look into imports, but this is not a problem,
4237- /// since we report the definitions (thus, the de-aliased imports).
4238- fn lookup_import_candidates < FilterFn > ( & mut self ,
4236+ fn lookup_import_candidates_from_module < FilterFn > ( & mut self ,
42394237 lookup_name : Name ,
42404238 namespace : Namespace ,
4239+ start_module : & ' a ModuleData < ' a > ,
4240+ crate_name : Ident ,
42414241 filter_fn : FilterFn )
42424242 -> Vec < ImportSuggestion >
42434243 where FilterFn : Fn ( Def ) -> bool
42444244 {
42454245 let mut candidates = Vec :: new ( ) ;
42464246 let mut worklist = Vec :: new ( ) ;
42474247 let mut seen_modules = FxHashSet ( ) ;
4248- worklist. push ( ( self . graph_root , Vec :: new ( ) , false ) ) ;
4248+ let not_local_module = crate_name != keywords:: Crate . ident ( ) ;
4249+ worklist. push ( ( start_module, Vec :: < ast:: PathSegment > :: new ( ) , not_local_module) ) ;
42494250
42504251 while let Some ( ( in_module,
42514252 path_segments,
@@ -4264,17 +4265,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
42644265 if ident. name == lookup_name && ns == namespace {
42654266 if filter_fn ( name_binding. def ( ) ) {
42664267 // create the path
4267- let mut segms = if self . session . rust_2018 ( ) && !in_module_is_extern {
4268+ let mut segms = path_segments. clone ( ) ;
4269+ if self . session . rust_2018 ( ) {
42684270 // crate-local absolute paths start with `crate::` in edition 2018
42694271 // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
4270- let mut full_segms = vec ! [
4271- ast:: PathSegment :: from_ident( keywords:: Crate . ident( ) )
4272- ] ;
4273- full_segms. extend ( path_segments. clone ( ) ) ;
4274- full_segms
4275- } else {
4276- path_segments. clone ( )
4277- } ;
4272+ segms. insert (
4273+ 0 , ast:: PathSegment :: from_ident ( crate_name)
4274+ ) ;
4275+ }
42784276
42794277 segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
42804278 let path = Path {
@@ -4300,7 +4298,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
43004298 let mut path_segments = path_segments. clone ( ) ;
43014299 path_segments. push ( ast:: PathSegment :: from_ident ( ident) ) ;
43024300
4303- if !in_module_is_extern || name_binding. vis == ty:: Visibility :: Public {
4301+ let is_extern_crate_that_also_appears_in_prelude =
4302+ name_binding. is_extern_crate ( ) &&
4303+ self . session . rust_2018 ( ) ;
4304+
4305+ let is_visible_to_user =
4306+ !in_module_is_extern || name_binding. vis == ty:: Visibility :: Public ;
4307+
4308+ if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user {
43044309 // add the module to the lookup
43054310 let is_extern = in_module_is_extern || name_binding. is_extern_crate ( ) ;
43064311 if seen_modules. insert ( module. def_id ( ) . unwrap ( ) ) {
@@ -4314,6 +4319,45 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
43144319 candidates
43154320 }
43164321
4322+ /// When name resolution fails, this method can be used to look up candidate
4323+ /// entities with the expected name. It allows filtering them using the
4324+ /// supplied predicate (which should be used to only accept the types of
4325+ /// definitions expected e.g. traits). The lookup spans across all crates.
4326+ ///
4327+ /// NOTE: The method does not look into imports, but this is not a problem,
4328+ /// since we report the definitions (thus, the de-aliased imports).
4329+ fn lookup_import_candidates < FilterFn > ( & mut self ,
4330+ lookup_name : Name ,
4331+ namespace : Namespace ,
4332+ filter_fn : FilterFn )
4333+ -> Vec < ImportSuggestion >
4334+ where FilterFn : Fn ( Def ) -> bool
4335+ {
4336+ let mut suggestions = vec ! [ ] ;
4337+
4338+ suggestions. extend (
4339+ self . lookup_import_candidates_from_module (
4340+ lookup_name, namespace, self . graph_root , keywords:: Crate . ident ( ) , & filter_fn
4341+ )
4342+ ) ;
4343+
4344+ if self . session . features_untracked ( ) . extern_prelude {
4345+ let extern_prelude_names = self . extern_prelude . clone ( ) ;
4346+ for & krate_name in extern_prelude_names. iter ( ) {
4347+ let krate_ident = Ident :: with_empty_ctxt ( krate_name) ;
4348+ let external_prelude_module = self . load_extern_prelude_crate_if_needed ( krate_ident) ;
4349+
4350+ suggestions. extend (
4351+ self . lookup_import_candidates_from_module (
4352+ lookup_name, namespace, external_prelude_module, krate_ident, & filter_fn
4353+ )
4354+ ) ;
4355+ }
4356+ }
4357+
4358+ suggestions
4359+ }
4360+
43174361 fn find_module ( & mut self ,
43184362 module_def : Def )
43194363 -> Option < ( Module < ' a > , ImportSuggestion ) >
0 commit comments