@@ -1952,9 +1952,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
1952
1952
"access to extern crates through prelude is experimental" ) . emit ( ) ;
1953
1953
}
1954
1954
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) ;
1958
1956
1959
1957
let binding = ( crate_root, ty:: Visibility :: Public ,
1960
1958
ident. span , Mark :: root ( ) ) . to_name_binding ( self . arenas ) ;
@@ -1982,6 +1980,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
1982
1980
None
1983
1981
}
1984
1982
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
+
1985
1990
fn hygienic_lexical_parent ( & mut self , module : Module < ' a > , span : & mut Span )
1986
1991
-> Option < Module < ' a > > {
1987
1992
if !module. expansion . is_descendant_of ( span. ctxt ( ) . outer ( ) ) {
@@ -4228,24 +4233,20 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4228
4233
}
4229
4234
}
4230
4235
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 ,
4239
4237
lookup_name : Name ,
4240
4238
namespace : Namespace ,
4239
+ start_module : & ' a ModuleData < ' a > ,
4240
+ crate_name : Ident ,
4241
4241
filter_fn : FilterFn )
4242
4242
-> Vec < ImportSuggestion >
4243
4243
where FilterFn : Fn ( Def ) -> bool
4244
4244
{
4245
4245
let mut candidates = Vec :: new ( ) ;
4246
4246
let mut worklist = Vec :: new ( ) ;
4247
4247
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) ) ;
4249
4250
4250
4251
while let Some ( ( in_module,
4251
4252
path_segments,
@@ -4264,17 +4265,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4264
4265
if ident. name == lookup_name && ns == namespace {
4265
4266
if filter_fn ( name_binding. def ( ) ) {
4266
4267
// 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 ( ) {
4268
4270
// crate-local absolute paths start with `crate::` in edition 2018
4269
4271
// 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
+ }
4278
4276
4279
4277
segms. push ( ast:: PathSegment :: from_ident ( ident) ) ;
4280
4278
let path = Path {
@@ -4300,7 +4298,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4300
4298
let mut path_segments = path_segments. clone ( ) ;
4301
4299
path_segments. push ( ast:: PathSegment :: from_ident ( ident) ) ;
4302
4300
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 {
4304
4309
// add the module to the lookup
4305
4310
let is_extern = in_module_is_extern || name_binding. is_extern_crate ( ) ;
4306
4311
if seen_modules. insert ( module. def_id ( ) . unwrap ( ) ) {
@@ -4314,6 +4319,45 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
4314
4319
candidates
4315
4320
}
4316
4321
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
+
4317
4361
fn find_module ( & mut self ,
4318
4362
module_def : Def )
4319
4363
-> Option < ( Module < ' a > , ImportSuggestion ) >
0 commit comments