diff options
Diffstat (limited to 'src/librustc_resolve/lib.rs')
| -rw-r--r-- | src/librustc_resolve/lib.rs | 89 | 
1 files changed, 67 insertions, 22 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 264f5c01135..78c518aea96 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -14,6 +14,7 @@ #![feature(crate_visibility_modifier)] #![cfg_attr(not(stage0), feature(nll))] +#![cfg_attr(not(stage0), feature(infer_outlives_requirements))] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] @@ -1951,9 +1952,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { "access to extern crates through prelude is experimental").emit(); } - let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); - let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(crate_root); + let crate_root = self.load_extern_prelude_crate_if_needed(ident); let binding = (crate_root, ty::Visibility::Public, ident.span, Mark::root()).to_name_binding(self.arenas); @@ -1981,6 +1980,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { None } + fn load_extern_prelude_crate_if_needed(&mut self, ident: Ident) -> Module<'a> { + let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); + let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + self.populate_module_if_necessary(&crate_root); + crate_root + } + fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span) -> Option<Module<'a>> { if !module.expansion.is_descendant_of(span.ctxt().outer()) { @@ -4227,16 +4233,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } } - /// When name resolution fails, this method can be used to look up candidate - /// entities with the expected name. It allows filtering them using the - /// supplied predicate (which should be used to only accept the types of - /// definitions expected e.g. traits). The lookup spans across all crates. - /// - /// NOTE: The method does not look into imports, but this is not a problem, - /// since we report the definitions (thus, the de-aliased imports). - fn lookup_import_candidates<FilterFn>(&mut self, + fn lookup_import_candidates_from_module<FilterFn>(&mut self, lookup_name: Name, namespace: Namespace, + start_module: &'a ModuleData<'a>, + crate_name: Ident, filter_fn: FilterFn) -> Vec<ImportSuggestion> where FilterFn: Fn(Def) -> bool @@ -4244,7 +4245,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut candidates = Vec::new(); let mut worklist = Vec::new(); let mut seen_modules = FxHashSet(); - worklist.push((self.graph_root, Vec::new(), false)); + let not_local_module = crate_name != keywords::Crate.ident(); + worklist.push((start_module, Vec::<ast::PathSegment>::new(), not_local_module)); while let Some((in_module, path_segments, @@ -4263,17 +4265,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { if ident.name == lookup_name && ns == namespace { if filter_fn(name_binding.def()) { // create the path - let mut segms = if self.session.rust_2018() && !in_module_is_extern { + let mut segms = path_segments.clone(); + if self.session.rust_2018() { // crate-local absolute paths start with `crate::` in edition 2018 // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660) - let mut full_segms = vec![ - ast::PathSegment::from_ident(keywords::Crate.ident()) - ]; - full_segms.extend(path_segments.clone()); - full_segms - } else { - path_segments.clone() - }; + segms.insert( + 0, ast::PathSegment::from_ident(crate_name) + ); + } segms.push(ast::PathSegment::from_ident(ident)); let path = Path { @@ -4299,7 +4298,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut path_segments = path_segments.clone(); path_segments.push(ast::PathSegment::from_ident(ident)); - if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { + let is_extern_crate_that_also_appears_in_prelude = + name_binding.is_extern_crate() && + self.session.rust_2018(); + + let is_visible_to_user = + !in_module_is_extern || name_binding.vis == ty::Visibility::Public; + + if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user { // add the module to the lookup let is_extern = in_module_is_extern || name_binding.is_extern_crate(); if seen_modules.insert(module.def_id().unwrap()) { @@ -4313,6 +4319,45 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { candidates } + /// When name resolution fails, this method can be used to look up candidate + /// entities with the expected name. It allows filtering them using the + /// supplied predicate (which should be used to only accept the types of + /// definitions expected e.g. traits). The lookup spans across all crates. + /// + /// NOTE: The method does not look into imports, but this is not a problem, + /// since we report the definitions (thus, the de-aliased imports). + fn lookup_import_candidates<FilterFn>(&mut self, + lookup_name: Name, + namespace: Namespace, + filter_fn: FilterFn) + -> Vec<ImportSuggestion> + where FilterFn: Fn(Def) -> bool + { + let mut suggestions = vec![]; + + suggestions.extend( + self.lookup_import_candidates_from_module( + lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn + ) + ); + + if self.session.features_untracked().extern_prelude { + let extern_prelude_names = self.extern_prelude.clone(); + for &krate_name in extern_prelude_names.iter() { + let krate_ident = Ident::with_empty_ctxt(krate_name); + let external_prelude_module = self.load_extern_prelude_crate_if_needed(krate_ident); + + suggestions.extend( + self.lookup_import_candidates_from_module( + lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn + ) + ); + } + } + + suggestions + } + fn find_module(&mut self, module_def: Def) -> Option<(Module<'a>, ImportSuggestion)>  | 
