From 1ee37cd87245bb9e21a500bc1dc4185f3afea8a1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 9 Aug 2019 19:25:34 -0400 Subject: [PATCH 01/13] Cleanup historical stability comments These weren't removed by ccbcc720a679ae76155a8 most likely by accident, let's clean them up now. --- src/librustc_driver/lib.rs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 77b7ef96d3f6c..e9d85a53d1e42 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -957,14 +957,11 @@ fn print_flag_list(cmdline_opt: &str, /// otherwise returns `None`. /// /// The compiler's handling of options is a little complicated as it ties into -/// our stability story, and it's even *more* complicated by historical -/// accidents. The current intention of each compiler option is to have one of -/// three modes: +/// our stability story. The current intention of each compiler option is to +/// have one of two modes: /// /// 1. An option is stable and can be used everywhere. -/// 2. An option is unstable, but was historically allowed on the stable -/// channel. -/// 3. An option is unstable, and can only be used on nightly. +/// 2. An option is unstable, and can only be used on nightly. /// /// Like unstable library and language features, however, unstable options have /// always required a form of "opt in" to indicate that you're using them. This @@ -1007,19 +1004,13 @@ pub fn handle_options(args: &[String]) -> Option { // this option that was passed. // * If we're a nightly compiler, then unstable options are now unlocked, so // we're good to go. - // * Otherwise, if we're a truly unstable option then we generate an error + // * Otherwise, if we're an unstable option then we generate an error // (unstable option being used on stable) - // * If we're a historically stable-but-should-be-unstable option then we - // emit a warning that we're going to turn this into an error soon. nightly_options::check_nightly_options(&matches, &config::rustc_optgroups()); if matches.opt_present("h") || matches.opt_present("help") { - // Only show unstable options in --help if we *really* accept unstable - // options, which catches the case where we got `-Z unstable-options` on - // the stable channel of Rust which was accidentally allowed - // historically. - usage(matches.opt_present("verbose"), - nightly_options::is_unstable_enabled(&matches)); + // Only show unstable options in --help if we accept unstable options. + usage(matches.opt_present("verbose"), nightly_options::is_unstable_enabled(&matches)); return None; } From 352c6d036f874728511a9e761cd745559999a967 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 10 Aug 2019 08:47:22 +0200 Subject: [PATCH 02/13] .gitignore: Readd `/tmp/` It is produced during `./x.py test` --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a0b491f42789a..3b7c613e65ef9 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ __pycache__/ /src/libcore/unicode/UnicodeData.txt /src/libcore/unicode/downloaded /target/ +/tmp/ tags tags.* TAGS From 87a8c5706deae871def85a044156362f2dafef10 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 10 Aug 2019 10:01:03 +0200 Subject: [PATCH 03/13] Explain why `/tmp/` is ignored --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3b7c613e65ef9..a7dd5a13b6f48 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ __pycache__/ /src/libcore/unicode/UnicodeData.txt /src/libcore/unicode/downloaded /target/ +# Generated by compiletest for incremental: /tmp/ tags tags.* From 83b837a7f911ea56ca3c466a43a7c3958eb24b13 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 10 Aug 2019 10:39:40 +0200 Subject: [PATCH 04/13] .gitignore: Explain why `/obj/` is ignored --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a7dd5a13b6f48..81a472451d777 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ __pycache__/ /inst/ /llvm/ /mingw-build/ +# Created by default with `src/ci/docker/run.sh`: /obj/ /rustllvm/ /src/libcore/unicode/DerivedCoreProperties.txt From e2e8746acc1d4fd236552a59f54b732680b4524e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 5 Aug 2019 21:18:50 +0300 Subject: [PATCH 05/13] resolve: Move late resolution into a separate visitor Move `Resolver` fields specific to late resolution to the new visitor. The `current_module` field from `Resolver` is replaced with two `current_module`s in `LateResolutionVisitor` and `BuildReducedGraphVisitor`. Outside of those visitors `current_module` is replaced by passing `parent_scope` to more functions and using the parent module from it. Visibility resolution no longer have access to later resolution methods and has to use early resolution, so its diagnostics in case of errors regress slightly. --- src/librustc_resolve/build_reduced_graph.rs | 111 +++-- src/librustc_resolve/check_unused.rs | 4 - src/librustc_resolve/diagnostics.rs | 30 +- src/librustc_resolve/lib.rs | 417 +++++++++++------- src/librustc_resolve/macros.rs | 61 ++- src/librustc_resolve/resolve_imports.rs | 53 +-- src/test/ui/hygiene/privacy-early.rs | 17 + src/test/ui/hygiene/privacy-early.stderr | 21 + src/test/ui/resolve/resolve-bad-visibility.rs | 4 +- .../ui/resolve/resolve-bad-visibility.stderr | 21 +- .../ui/resolve/visibility-indeterminate.rs | 5 + .../resolve/visibility-indeterminate.stderr | 19 + src/test/ui/span/visibility-ty-params.stderr | 14 +- 13 files changed, 477 insertions(+), 300 deletions(-) create mode 100644 src/test/ui/hygiene/privacy-early.rs create mode 100644 src/test/ui/hygiene/privacy-early.stderr create mode 100644 src/test/ui/resolve/visibility-indeterminate.rs create mode 100644 src/test/ui/resolve/visibility-indeterminate.stderr diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9d01f33002940..668daaba643a8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -19,6 +19,7 @@ use rustc::middle::cstore::CrateStore; use rustc_metadata::cstore::LoadedMacro; use std::cell::Cell; +use std::ops::{Deref, DerefMut}; use std::ptr; use rustc_data_structures::sync::Lrc; @@ -115,7 +116,7 @@ impl<'a> Resolver<'a> { parent_prefix: &[Segment], nested: bool, // The whole `use` item - parent_scope: ParentScope<'a>, + parent_scope: &ParentScope<'a>, item: &Item, vis: ty::Visibility, root_span: Span, @@ -249,7 +250,7 @@ impl<'a> Resolver<'a> { root_span, item.id, vis, - parent_scope, + parent_scope.clone(), ); } ast::UseTreeKind::Glob => { @@ -266,7 +267,7 @@ impl<'a> Resolver<'a> { root_span, item.id, vis, - parent_scope, + parent_scope.clone(), ); } ast::UseTreeKind::Nested(ref items) => { @@ -297,7 +298,7 @@ impl<'a> Resolver<'a> { // This particular use tree tree, id, &prefix, true, // The whole `use` item - parent_scope.clone(), item, vis, root_span, + parent_scope, item, vis, root_span, ); } @@ -327,14 +328,16 @@ impl<'a> Resolver<'a> { } } } +} +impl<'a> BuildReducedGraphVisitor<'_, 'a> { /// Constructs the reduced graph for one item. - fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScope<'a>) { + fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: &ParentScope<'a>) { let parent = parent_scope.module; let expansion = parent_scope.expansion; let ident = item.ident.gensym_if_underscore(); let sp = item.span; - let vis = self.resolve_visibility(&item.vis); + let vis = self.resolve_visibility(&item.vis, parent_scope); match item.node { ItemKind::Use(ref use_tree) => { @@ -361,7 +364,9 @@ impl<'a> Resolver<'a> { } else if orig_name == Some(kw::SelfLower) { self.graph_root } else { - let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions); + let crate_id = self.resolver.crate_loader.process_extern_crate( + item, &self.resolver.definitions + ); self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; @@ -372,13 +377,13 @@ impl<'a> Resolver<'a> { } } - let used = self.process_legacy_macro_imports(item, module, &parent_scope); + let used = self.process_legacy_macro_imports(item, module, parent_scope); let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas); let directive = self.arenas.alloc_import_directive(ImportDirective { root_id: item.id, id: item.id, - parent_scope, + parent_scope: parent_scope.clone(), imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), subclass: ImportDirectiveSubclass::ExternCrate { source: orig_name, @@ -395,7 +400,7 @@ impl<'a> Resolver<'a> { }); self.potentially_unused_imports.push(directive); let imported_binding = self.import(binding, directive); - if ptr::eq(self.current_module, self.graph_root) { + if ptr::eq(parent, self.graph_root) { if let Some(entry) = self.extern_prelude.get(&ident.modern()) { if expansion != ExpnId::root() && orig_name.is_some() && entry.extern_crate_item.is_none() { @@ -455,7 +460,7 @@ impl<'a> Resolver<'a> { // Functions introducing procedural macros reserve a slot // in the macro namespace as well (see #52225). - self.define_macro(item, expansion, &mut LegacyScope::Empty); + self.define_macro(item, parent_scope); } // These items live in the type namespace. @@ -511,8 +516,8 @@ impl<'a> Resolver<'a> { // Record field names for error reporting. let field_names = struct_def.fields().iter().filter_map(|field| { - let field_vis = self.resolve_visibility(&field.vis); - if ctor_vis.is_at_least(field_vis, &*self) { + let field_vis = self.resolve_visibility(&field.vis, parent_scope); + if ctor_vis.is_at_least(field_vis, &*self.resolver) { ctor_vis = field_vis; } field.ident.map(|ident| ident.name) @@ -538,7 +543,7 @@ impl<'a> Resolver<'a> { // Record field names for error reporting. let field_names = vdata.fields().iter().filter_map(|field| { - self.resolve_visibility(&field.vis); + self.resolve_visibility(&field.vis, parent_scope); field.ident.map(|ident| ident.name) }).collect(); let item_def_id = self.definitions.local_def_id(item.id); @@ -614,7 +619,13 @@ impl<'a> Resolver<'a> { ForeignItemKind::Macro(_) => unreachable!(), }; let parent = self.current_module; - let vis = self.resolve_visibility(&item.vis); + let parent_scope = &ParentScope { + module: self.current_module, + expansion: self.expansion, + legacy: self.current_legacy_scope, + derives: Vec::new(), + }; + let vis = self.resolver.resolve_visibility(&item.vis, parent_scope); self.define(parent, item.ident, ns, (res, vis, item.span, expn_id)); } @@ -630,7 +641,9 @@ impl<'a> Resolver<'a> { self.current_module = module; // Descend into the block. } } +} +impl<'a> Resolver<'a> { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_res( &mut self, @@ -804,7 +817,9 @@ impl<'a> Resolver<'a> { self.session.struct_span_err(span, &msg).note(note).emit(); } } +} +impl<'a> BuildReducedGraphVisitor<'_, 'a> { /// Returns `true` if we should consider the underlying `extern crate` to be used. fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, parent_scope: &ParentScope<'a>) -> bool { @@ -873,7 +888,7 @@ impl<'a> Resolver<'a> { ModuleOrUniformRoot::Module(module), ident, MacroNS, - None, + parent_scope, false, ident.span, ); @@ -918,22 +933,36 @@ impl<'a> Resolver<'a> { pub struct BuildReducedGraphVisitor<'a, 'b> { pub resolver: &'a mut Resolver<'b>, + pub current_module: Module<'b>, pub current_legacy_scope: LegacyScope<'b>, pub expansion: ExpnId, } +impl<'b> Deref for BuildReducedGraphVisitor<'_, 'b> { + type Target = Resolver<'b>; + fn deref(&self) -> &Self::Target { + self.resolver + } +} + +impl<'b> DerefMut for BuildReducedGraphVisitor<'_, 'b> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.resolver + } +} + impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { let invoc_id = id.placeholder_to_expn_id(); - self.resolver.current_module.unresolved_invocations.borrow_mut().insert(invoc_id); + self.current_module.unresolved_invocations.borrow_mut().insert(invoc_id); - let invocation_data = self.resolver.arenas.alloc_invocation_data(InvocationData { - module: self.resolver.current_module, + let invocation_data = self.arenas.alloc_invocation_data(InvocationData { + module: self.current_module, parent_legacy_scope: self.current_legacy_scope, output_legacy_scope: Cell::new(None), }); - let old_invocation_data = self.resolver.invocations.insert(invoc_id, invocation_data); + let old_invocation_data = self.invocations.insert(invoc_id, invocation_data); assert!(old_invocation_data.is_none(), "invocation data is reset for an invocation"); invocation_data @@ -959,30 +988,30 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty); fn visit_item(&mut self, item: &'a Item) { + let parent_scope = &ParentScope { + module: self.current_module, + expansion: self.expansion, + legacy: self.current_legacy_scope, + derives: Vec::new(), + }; let macro_use = match item.node { ItemKind::MacroDef(..) => { - self.resolver.define_macro(item, self.expansion, &mut self.current_legacy_scope); + self.current_legacy_scope = self.resolver.define_macro(item, parent_scope); return } ItemKind::Mac(..) => { self.current_legacy_scope = LegacyScope::Invocation(self.visit_invoc(item.id)); return } - ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs), + ItemKind::Mod(..) => self.contains_macro_use(&item.attrs), _ => false, }; - let orig_current_module = self.resolver.current_module; + let orig_current_module = self.current_module; let orig_current_legacy_scope = self.current_legacy_scope; - let parent_scope = ParentScope { - module: self.resolver.current_module, - expansion: self.expansion, - legacy: self.current_legacy_scope, - derives: Vec::new(), - }; - self.resolver.build_reduced_graph_for_item(item, parent_scope); + self.build_reduced_graph_for_item(item, parent_scope); visit::walk_item(self, item); - self.resolver.current_module = orig_current_module; + self.current_module = orig_current_module; if !macro_use { self.current_legacy_scope = orig_current_legacy_scope; } @@ -1002,21 +1031,21 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { return; } - self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion); + self.build_reduced_graph_for_foreign_item(foreign_item, self.expansion); visit::walk_foreign_item(self, foreign_item); } fn visit_block(&mut self, block: &'a Block) { - let orig_current_module = self.resolver.current_module; + let orig_current_module = self.current_module; let orig_current_legacy_scope = self.current_legacy_scope; - self.resolver.build_reduced_graph_for_block(block, self.expansion); + self.build_reduced_graph_for_block(block, self.expansion); visit::walk_block(self, block); - self.resolver.current_module = orig_current_module; + self.current_module = orig_current_module; self.current_legacy_scope = orig_current_legacy_scope; } fn visit_trait_item(&mut self, item: &'a TraitItem) { - let parent = self.resolver.current_module; + let parent = self.current_module; if let TraitItemKind::Macro(_) = item.node { self.visit_invoc(item.id); @@ -1024,12 +1053,12 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { } // Add the item to the trait info. - let item_def_id = self.resolver.definitions.local_def_id(item.id); + let item_def_id = self.definitions.local_def_id(item.id); let (res, ns) = match item.node { TraitItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), TraitItemKind::Method(ref sig, _) => { if sig.decl.has_self() { - self.resolver.has_self.insert(item_def_id); + self.has_self.insert(item_def_id); } (Res::Def(DefKind::Method, item_def_id), ValueNS) } @@ -1040,9 +1069,9 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { let vis = ty::Visibility::Public; self.resolver.define(parent, item.ident, ns, (res, vis, item.span, self.expansion)); - self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor + self.current_module = parent.parent.unwrap(); // nearest normal ancestor visit::walk_trait_item(self, item); - self.resolver.current_module = parent; + self.current_module = parent; } fn visit_token(&mut self, t: Token) { @@ -1058,7 +1087,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { fn visit_attribute(&mut self, attr: &'a ast::Attribute) { if !attr.is_sugared_doc && is_builtin_attr(attr) { let parent_scope = ParentScope { - module: self.resolver.current_module.nearest_item_scope(), + module: self.current_module.nearest_item_scope(), expansion: self.expansion, legacy: self.current_legacy_scope, // Let's hope discerning built-in attributes from derive helpers is not necessary diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 4fee15c59b33d..d733a32c9c38e 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -270,10 +270,6 @@ pub fn check_crate(resolver: &mut Resolver<'_>, krate: &ast::Crate) { } } - for (id, span) in resolver.unused_labels.iter() { - resolver.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); - } - let mut visitor = UnusedImportCheckVisitor { resolver, unused_imports: Default::default(), diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index aeb6f23da5aa6..c1fe7188f6dda 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -18,7 +18,7 @@ use syntax_pos::{BytePos, Span}; use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; use crate::{is_self_type, is_self_value, path_names_to_string, KNOWN_TOOLS}; -use crate::{CrateLint, LegacyScope, Module, ModuleKind, ModuleOrUniformRoot}; +use crate::{CrateLint, LateResolutionVisitor, LegacyScope, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, ParentScope, Resolver, RibKind, Scope, ScopeSet, Segment}; type Res = def::Res; @@ -78,7 +78,7 @@ fn add_module_candidates( } } -impl<'a> Resolver<'a> { +impl<'a> LateResolutionVisitor<'a, '_> { /// Handles error reporting for `smart_resolve_path_fragment` function. /// Creates base error and amends it with one short label and possibly some longer helps/notes. pub(crate) fn smart_resolve_report_errors( @@ -112,7 +112,7 @@ impl<'a> Resolver<'a> { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; - let mod_prefix = match self.resolve_path_without_parent_scope( + let mod_prefix = match self.resolve_path( mod_path, Some(TypeNS), false, span, CrateLint::No ) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => @@ -288,7 +288,9 @@ impl<'a> Resolver<'a> { } (err, candidates) } +} +impl<'a> Resolver<'a> { fn followed_by_brace(&self, span: Span) -> (bool, Option<(Span, String)>) { // HACK(estebank): find a better way to figure out that this was a // parser issue where a struct literal is being used on an expression @@ -338,7 +340,9 @@ impl<'a> Resolver<'a> { } return (followed_by_brace, closing_brace) } +} +impl<'a> LateResolutionVisitor<'a, '_> { /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment` /// function. /// Returns `true` if able to provide context-dependent help. @@ -457,7 +461,7 @@ impl<'a> Resolver<'a> { (Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => { if let Some((ctor_def, ctor_vis)) = self.struct_constructors.get(&def_id).cloned() { - let accessible_ctor = self.is_accessible(ctor_vis); + let accessible_ctor = self.is_accessible_from(ctor_vis, self.current_module); if is_expected(ctor_def) && !accessible_ctor { err.span_label( span, @@ -532,11 +536,12 @@ impl<'a> Resolver<'a> { // Look for associated items in the current trait. if let Some((module, _)) = self.current_trait_ref { + let parent_scope = &self.parent_scope(); if let Ok(binding) = self.resolve_ident_in_module( ModuleOrUniformRoot::Module(module), ident, ns, - None, + parent_scope, false, module.span, ) { @@ -553,7 +558,9 @@ impl<'a> Resolver<'a> { None } +} +impl<'a> Resolver<'a> { /// Lookup typo candidate in scope for a macro or import. fn early_lookup_typo_candidate( &mut self, @@ -569,9 +576,10 @@ impl<'a> Resolver<'a> { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); if filter_fn(res) { for derive in &parent_scope.derives { - let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope }; + let parent_scope = + &ParentScope { derives: Vec::new(), ..*parent_scope }; if let Ok((Some(ext), _)) = this.resolve_macro_path( - derive, Some(MacroKind::Derive), &parent_scope, false, false + derive, Some(MacroKind::Derive), parent_scope, false, false ) { suggestions.extend(ext.helper_attrs.iter().map(|name| { TypoSuggestion::from_res(*name, res) @@ -682,7 +690,9 @@ impl<'a> Resolver<'a> { _ => None, } } +} +impl<'a> LateResolutionVisitor<'a, '_> { fn lookup_typo_candidate( &mut self, path: &[Segment], @@ -750,7 +760,7 @@ impl<'a> Resolver<'a> { } else { // Search in module. let mod_path = &path[..path.len() - 1]; - if let PathResult::Module(module) = self.resolve_path_without_parent_scope( + if let PathResult::Module(module) = self.resolve_path( mod_path, Some(TypeNS), false, span, CrateLint::No ) { if let ModuleOrUniformRoot::Module(module) = module { @@ -774,7 +784,9 @@ impl<'a> Resolver<'a> { _ => None, } } +} +impl<'a> Resolver<'a> { fn lookup_import_candidates_from_module(&mut self, lookup_ident: Ident, namespace: Namespace, @@ -969,7 +981,7 @@ impl<'a> Resolver<'a> { ) { let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind); let suggestion = self.early_lookup_typo_candidate( - ScopeSet::Macro(macro_kind), &parent_scope, ident, is_expected + ScopeSet::Macro(macro_kind), parent_scope, ident, is_expected ); add_typo_suggestion(err, suggestion, ident.span); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ce2bc79ff6034..e11413fcda9ea 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -59,6 +59,7 @@ use log::debug; use std::cell::{Cell, RefCell}; use std::{cmp, fmt, iter, mem, ptr}; +use std::ops::{Deref, DerefMut}; use std::collections::BTreeSet; use std::mem::replace; use rustc_data_structures::ptr_key::PtrKey; @@ -537,35 +538,22 @@ enum PathSource<'a> { TupleStruct, // `m::A::B` in `::B::C`. TraitItem(Namespace), - // Path in `pub(path)` - Visibility, } impl<'a> PathSource<'a> { fn namespace(self) -> Namespace { match self { - PathSource::Type | PathSource::Trait(_) | PathSource::Struct | - PathSource::Visibility => TypeNS, + PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS, PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS, PathSource::TraitItem(ns) => ns, } } - fn global_by_default(self) -> bool { - match self { - PathSource::Visibility => true, - PathSource::Type | PathSource::Expr(..) | PathSource::Pat | - PathSource::Struct | PathSource::TupleStruct | - PathSource::Trait(_) | PathSource::TraitItem(..) => false, - } - } - fn defer_to_typeck(self) -> bool { match self { PathSource::Type | PathSource::Expr(..) | PathSource::Pat | PathSource::Struct | PathSource::TupleStruct => true, - PathSource::Trait(_) | PathSource::TraitItem(..) | - PathSource::Visibility => false, + PathSource::Trait(_) | PathSource::TraitItem(..) => false, } } @@ -576,7 +564,6 @@ impl<'a> PathSource<'a> { PathSource::Pat => "unit struct/variant or constant", PathSource::Struct => "struct, variant or union type", PathSource::TupleStruct => "tuple struct/variant", - PathSource::Visibility => "module", PathSource::TraitItem(ns) => match ns { TypeNS => "associated type", ValueNS => "method or associated constant", @@ -655,10 +642,6 @@ impl<'a> PathSource<'a> { Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true, _ => false, }, - PathSource::Visibility => match res { - Res::Def(DefKind::Mod, _) => true, - _ => false, - }, } } @@ -675,8 +658,6 @@ impl<'a> PathSource<'a> { __diagnostic_used!(E0574); __diagnostic_used!(E0575); __diagnostic_used!(E0576); - __diagnostic_used!(E0577); - __diagnostic_used!(E0578); match (self, has_unexpected_resolution) { (PathSource::Trait(_), true) => "E0404", (PathSource::Trait(_), false) => "E0405", @@ -690,8 +671,6 @@ impl<'a> PathSource<'a> { (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531", (PathSource::TraitItem(..), true) => "E0575", (PathSource::TraitItem(..), false) => "E0576", - (PathSource::Visibility, true) => "E0577", - (PathSource::Visibility, false) => "E0578", } } } @@ -801,8 +780,80 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { } } +struct LateResolutionVisitor<'a, 'b> { + resolver: &'b mut Resolver<'a>, + + /// The module that represents the current item scope. + current_module: Module<'a>, + + /// The current set of local scopes for types and values. + /// FIXME #4948: Reuse ribs to avoid allocation. + ribs: PerNS>>, + + /// The current set of local scopes, for labels. + label_ribs: Vec>, + + /// The trait that the current context can refer to. + current_trait_ref: Option<(Module<'a>, TraitRef)>, + + /// The current trait's associated types' ident, used for diagnostic suggestions. + current_trait_assoc_types: Vec, + + /// The current self type if inside an impl (used for better errors). + current_self_type: Option, + + /// The current self item if inside an ADT (used for better errors). + current_self_item: Option, + + /// A list of labels as of yet unused. Labels will be removed from this map when + /// they are used (in a `break` or `continue` statement) + unused_labels: FxHashMap, + + /// Only used for better errors on `fn(): fn()`. + current_type_ascription: Vec, +} + +impl<'a, 'b> LateResolutionVisitor<'a, '_> { + fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> { + let graph_root = resolver.graph_root; + LateResolutionVisitor { + resolver, + current_module: graph_root, + ribs: PerNS { + value_ns: vec![Rib::new(ModuleRibKind(graph_root))], + type_ns: vec![Rib::new(ModuleRibKind(graph_root))], + macro_ns: vec![Rib::new(ModuleRibKind(graph_root))], + }, + label_ribs: Vec::new(), + current_trait_ref: None, + current_trait_assoc_types: Vec::new(), + current_self_type: None, + current_self_item: None, + unused_labels: Default::default(), + current_type_ascription: Vec::new(), + } + } + + fn parent_scope(&self) -> ParentScope<'a> { + ParentScope { module: self.current_module, ..self.dummy_parent_scope() } + } +} + +impl<'a> Deref for LateResolutionVisitor<'a, '_> { + type Target = Resolver<'a>; + fn deref(&self) -> &Self::Target { + self.resolver + } +} + +impl<'a> DerefMut for LateResolutionVisitor<'a, '_> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.resolver + } +} + /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. -impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { +impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { fn visit_item(&mut self, item: &'tcx Item) { self.resolve_item(item); } @@ -1587,28 +1638,6 @@ pub struct Resolver<'a> { /// All non-determined imports. indeterminate_imports: Vec<&'a ImportDirective<'a>>, - /// The module that represents the current item scope. - current_module: Module<'a>, - - /// The current set of local scopes for types and values. - /// FIXME #4948: Reuse ribs to avoid allocation. - ribs: PerNS>>, - - /// The current set of local scopes, for labels. - label_ribs: Vec>, - - /// The trait that the current context can refer to. - current_trait_ref: Option<(Module<'a>, TraitRef)>, - - /// The current trait's associated types' ident, used for diagnostic suggestions. - current_trait_assoc_types: Vec, - - /// The current self type if inside an impl (used for better errors). - current_self_type: Option, - - /// The current self item if inside an ADT (used for better errors). - current_self_item: Option, - /// FIXME: Refactor things so that these fields are passed through arguments and not resolver. /// We are resolving a last import segment during import validation. last_import_segment: bool, @@ -1655,10 +1684,6 @@ pub struct Resolver<'a> { pub maybe_unused_trait_imports: NodeSet, pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, - /// A list of labels as of yet unused. Labels will be removed from this map when - /// they are used (in a `break` or `continue` statement) - pub unused_labels: FxHashMap, - /// Privacy errors are delayed until the end in order to deduplicate them. privacy_errors: Vec>, /// Ambiguity errors are delayed for deduplication. @@ -1703,9 +1728,6 @@ pub struct Resolver<'a> { /// it's not used during normal resolution, only for better error reporting. struct_constructors: DefIdMap<(Res, ty::Visibility)>, - /// Only used for better errors on `fn(): fn()`. - current_type_ascription: Vec, - injected_crate: Option>, /// Features enabled for this crate. @@ -1872,8 +1894,8 @@ impl<'a> Resolver<'a> { let span = path.span; let path = Segment::from_path(&path); // FIXME(Manishearth): intra-doc links won't get warned of epoch changes. - match self.resolve_path_without_parent_scope(&path, Some(namespace), true, - span, CrateLint::No) { + let parent_scope = &self.dummy_parent_scope(); + match self.resolve_path(&path, Some(namespace), parent_scope, true, span, CrateLint::No) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => Ok(module.res().unwrap()), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => @@ -1969,18 +1991,6 @@ impl<'a> Resolver<'a> { determined_imports: Vec::new(), indeterminate_imports: Vec::new(), - current_module: graph_root, - ribs: PerNS { - value_ns: vec![Rib::new(ModuleRibKind(graph_root))], - type_ns: vec![Rib::new(ModuleRibKind(graph_root))], - macro_ns: vec![Rib::new(ModuleRibKind(graph_root))], - }, - label_ribs: Vec::new(), - - current_trait_ref: None, - current_trait_assoc_types: Vec::new(), - current_self_type: None, - current_self_item: None, last_import_segment: false, blacklisted_binding: None, @@ -2002,8 +2012,6 @@ impl<'a> Resolver<'a> { maybe_unused_trait_imports: Default::default(), maybe_unused_extern_crates: Vec::new(), - unused_labels: FxHashMap::default(), - privacy_errors: Vec::new(), ambiguity_errors: Vec::new(), use_injections: Vec::new(), @@ -2036,7 +2044,6 @@ impl<'a> Resolver<'a> { unused_macros: Default::default(), proc_macro_stubs: Default::default(), special_derives: Default::default(), - current_type_ascription: Vec::new(), injected_crate: None, active_features: features.declared_lib_features.iter().map(|(feat, ..)| *feat) @@ -2089,10 +2096,13 @@ impl<'a> Resolver<'a> { /// Entry point to crate resolution. pub fn resolve_crate(&mut self, krate: &Crate) { ImportResolver { resolver: self }.finalize_imports(); - self.current_module = self.graph_root; - self.finalize_current_module_macro_resolutions(); - visit::walk_crate(self, krate); + self.finalize_current_module_macro_resolutions(self.graph_root); + let mut late_resolution_visitor = LateResolutionVisitor::new(self); + visit::walk_crate(&mut late_resolution_visitor, krate); + for (id, span) in late_resolution_visitor.unused_labels.iter() { + self.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); + } check_unused::check_crate(self, krate); self.report_errors(krate); @@ -2287,7 +2297,9 @@ impl<'a> Resolver<'a> { None } +} +impl<'a> Resolver<'a> { /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope. /// More specifically, we proceed up the hierarchy of scopes and return the binding for /// `ident` in the first scope that defines it (or None if no scopes define it). @@ -2308,8 +2320,10 @@ impl<'a> Resolver<'a> { fn resolve_ident_in_lexical_scope(&mut self, mut ident: Ident, ns: Namespace, + parent_scope: &ParentScope<'a>, record_used_id: Option, - path_span: Span) + path_span: Span, + ribs: &[Rib<'a>]) -> Option> { assert!(ns == TypeNS || ns == ValueNS); if ident.name == kw::Invalid { @@ -2331,23 +2345,23 @@ impl<'a> Resolver<'a> { // Walk backwards up the ribs in scope. let record_used = record_used_id.is_some(); let mut module = self.graph_root; - for i in (0 .. self.ribs[ns].len()).rev() { - debug!("walk rib\n{:?}", self.ribs[ns][i].bindings); + for i in (0 .. ribs.len()).rev() { + debug!("walk rib\n{:?}", ribs[i].bindings); // Use the rib kind to determine whether we are resolving parameters // (modern hygiene) or local variables (legacy hygiene). - let rib_ident = if let AssocItemRibKind | ItemRibKind = self.ribs[ns][i].kind { + let rib_ident = if let AssocItemRibKind | ItemRibKind = ribs[i].kind { modern_ident } else { ident }; - if let Some(res) = self.ribs[ns][i].bindings.get(&rib_ident).cloned() { + if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Res( - self.validate_res_from_ribs(ns, i, res, record_used, path_span), + self.validate_res_from_ribs(i, res, record_used, path_span, ribs), )); } - module = match self.ribs[ns][i].kind { + module = match ribs[i].kind { ModuleRibKind(module) => module, MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => { // If an invocation of this macro created `ident`, give up on `ident` @@ -2358,10 +2372,12 @@ impl<'a> Resolver<'a> { _ => continue, }; + let item = self.resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(module), ident, ns, + parent_scope, record_used, path_span, ); @@ -2386,16 +2402,15 @@ impl<'a> Resolver<'a> { self.hygienic_lexical_parent(module, &mut ident.span) }; module = unwrap_or!(opt_module, break); - let orig_current_module = self.current_module; - self.current_module = module; // Lexical resolutions can never be a privacy error. + let adjusted_parent_scope = &ParentScope { module, ..parent_scope.clone() }; let result = self.resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(module), ident, ns, + adjusted_parent_scope, record_used, path_span, ); - self.current_module = orig_current_module; match result { Ok(binding) => { @@ -2433,6 +2448,7 @@ impl<'a> Resolver<'a> { ModuleOrUniformRoot::Module(prelude), ident, ns, + parent_scope, false, path_span, ) { @@ -2498,7 +2514,7 @@ impl<'a> Resolver<'a> { module: ModuleOrUniformRoot<'a>, ident: Ident, ns: Namespace, - parent_scope: Option<&ParentScope<'a>>, + parent_scope: &ParentScope<'a>, record_used: bool, path_span: Span ) -> Result<&'a NameBinding<'a>, Determinacy> { @@ -2512,15 +2528,18 @@ impl<'a> Resolver<'a> { module: ModuleOrUniformRoot<'a>, mut ident: Ident, ns: Namespace, - parent_scope: Option<&ParentScope<'a>>, + parent_scope: &ParentScope<'a>, record_used: bool, path_span: Span ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { - let orig_current_module = self.current_module; + let tmp_parent_scope; + let mut adjusted_parent_scope = parent_scope; match module { - ModuleOrUniformRoot::Module(module) => { - if let Some(def) = ident.span.modernize_and_adjust(module.expansion) { - self.current_module = self.macro_def_scope(def); + ModuleOrUniformRoot::Module(m) => { + if let Some(def) = ident.span.modernize_and_adjust(m.expansion) { + tmp_parent_scope = + ParentScope { module: self.macro_def_scope(def), ..parent_scope.clone() }; + adjusted_parent_scope = &tmp_parent_scope; } } ModuleOrUniformRoot::ExternPrelude => { @@ -2532,9 +2551,8 @@ impl<'a> Resolver<'a> { } } let result = self.resolve_ident_in_module_unadjusted_ext( - module, ident, ns, parent_scope, false, record_used, path_span, + module, ident, ns, adjusted_parent_scope, false, record_used, path_span, ); - self.current_module = orig_current_module; result } @@ -2587,7 +2605,9 @@ impl<'a> Resolver<'a> { } module } +} +impl<'a> LateResolutionVisitor<'a, '_> { // AST resolution // // We maintain a list of value ribs and type ribs. @@ -2606,8 +2626,32 @@ impl<'a> Resolver<'a> { // generate a fake "implementation scope" containing all the // implementations thus found, for compatibility with old resolve pass. + fn resolve_ident_in_lexical_scope(&mut self, + ident: Ident, + ns: Namespace, + record_used_id: Option, + path_span: Span) + -> Option> { + self.resolver.resolve_ident_in_lexical_scope( + ident, ns, &self.parent_scope(), record_used_id, path_span, &self.ribs[ns] + ) + } + + fn resolve_path( + &mut self, + path: &[Segment], + opt_ns: Option, // `None` indicates a module path in import + record_used: bool, + path_span: Span, + crate_lint: CrateLint, + ) -> PathResult<'a> { + self.resolver.resolve_path_with_ribs( + path, opt_ns, &self.parent_scope(), record_used, path_span, crate_lint, &self.ribs + ) + } + pub fn with_scope(&mut self, id: NodeId, f: F) -> T - where F: FnOnce(&mut Resolver<'_>) -> T + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T { let id = self.definitions.local_def_id(id); let module = self.module_map.get(&id).cloned(); // clones a reference @@ -2617,7 +2661,7 @@ impl<'a> Resolver<'a> { self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); - self.finalize_current_module_macro_resolutions(); + self.resolver.finalize_current_module_macro_resolutions(self.current_module); let ret = f(self); self.current_module = orig_module; @@ -2827,7 +2871,7 @@ impl<'a> Resolver<'a> { } fn with_generic_param_rib<'b, F>(&'b mut self, generic_params: GenericParameters<'a, 'b>, f: F) - where F: FnOnce(&mut Resolver<'_>) + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) { debug!("with_generic_param_rib"); match generic_params { @@ -2901,7 +2945,7 @@ impl<'a> Resolver<'a> { } fn with_label_rib(&mut self, f: F) - where F: FnOnce(&mut Resolver<'_>) + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) { self.label_ribs.push(Rib::new(NormalRibKind)); f(self); @@ -2909,7 +2953,7 @@ impl<'a> Resolver<'a> { } fn with_item_rib(&mut self, f: F) - where F: FnOnce(&mut Resolver<'_>) + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) { self.ribs[ValueNS].push(Rib::new(ItemRibKind)); self.ribs[TypeNS].push(Rib::new(ItemRibKind)); @@ -2919,7 +2963,7 @@ impl<'a> Resolver<'a> { } fn with_constant_rib(&mut self, f: F) - where F: FnOnce(&mut Resolver<'_>) + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) { debug!("with_constant_rib"); self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind)); @@ -2930,7 +2974,7 @@ impl<'a> Resolver<'a> { } fn with_current_self_type(&mut self, self_type: &Ty, f: F) -> T - where F: FnOnce(&mut Resolver<'_>) -> T + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T { // Handle nested impls (inside fn bodies) let previous_value = replace(&mut self.current_self_type, Some(self_type.clone())); @@ -2940,7 +2984,7 @@ impl<'a> Resolver<'a> { } fn with_current_self_item(&mut self, self_item: &Item, f: F) -> T - where F: FnOnce(&mut Resolver<'_>) -> T + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T { let previous_value = replace(&mut self.current_self_item, Some(self_item.id)); let result = f(self); @@ -2950,7 +2994,7 @@ impl<'a> Resolver<'a> { /// When evaluating a `trait` use its associated types' idents for suggestionsa in E0412. fn with_trait_items(&mut self, trait_items: &Vec, f: F) -> T - where F: FnOnce(&mut Resolver<'_>) -> T + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) -> T { let trait_assoc_types = replace( &mut self.current_trait_assoc_types, @@ -2966,7 +3010,7 @@ impl<'a> Resolver<'a> { /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). fn with_optional_trait_ref(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T - where F: FnOnce(&mut Resolver<'_>, Option) -> T + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>, Option) -> T { let mut new_val = None; let mut new_id = None; @@ -2984,7 +3028,7 @@ impl<'a> Resolver<'a> { new_id = Some(res.def_id()); let span = trait_ref.path.span; if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = - self.resolve_path_without_parent_scope( + self.resolve_path( &path, Some(TypeNS), false, @@ -3003,7 +3047,7 @@ impl<'a> Resolver<'a> { } fn with_self_rib(&mut self, self_res: Res, f: F) - where F: FnOnce(&mut Resolver<'_>) + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) { let mut self_type_rib = Rib::new(NormalRibKind); @@ -3015,7 +3059,7 @@ impl<'a> Resolver<'a> { } fn with_self_struct_ctor_rib(&mut self, impl_id: DefId, f: F) - where F: FnOnce(&mut Resolver<'_>) + where F: FnOnce(&mut LateResolutionVisitor<'_, '_>) { let self_res = Res::SelfCtor(impl_id); let mut self_type_rib = Rib::new(NormalRibKind); @@ -3053,8 +3097,9 @@ impl<'a> Resolver<'a> { this.with_self_struct_ctor_rib(item_def_id, |this| { debug!("resolve_implementation with_self_struct_ctor_rib"); for impl_item in impl_items { - this.resolve_visibility(&impl_item.vis); - + this.resolver.resolve_visibility( + &impl_item.vis, &this.parent_scope() + ); // We also need a new scope for the impl item type parameters. let generic_params = HasGenericParams(&impl_item.generics, AssocItemRibKind); @@ -3129,11 +3174,12 @@ impl<'a> Resolver<'a> { // If there is a TraitRef in scope for an impl, then the method must be in the // trait. if let Some((module, _)) = self.current_trait_ref { + let parent_scope = &self.parent_scope(); if self.resolve_ident_in_module( ModuleOrUniformRoot::Module(module), ident, ns, - None, + parent_scope, false, span, ).is_err() { @@ -3282,7 +3328,7 @@ impl<'a> Resolver<'a> { self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module))); self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module))); self.current_module = anonymous_module; - self.finalize_current_module_macro_resolutions(); + self.resolver.finalize_current_module_macro_resolutions(self.current_module); } else { self.ribs[ValueNS].push(Rib::new(NormalRibKind)); } @@ -3497,7 +3543,6 @@ impl<'a> Resolver<'a> { ns, span, source.defer_to_typeck(), - source.global_by_default(), crate_lint, ) { Some(partial_res) if partial_res.unresolved_segments() == 0 => { @@ -3510,7 +3555,8 @@ impl<'a> Resolver<'a> { if let Res::Def(DefKind::Struct, def_id) = partial_res.base_res() { if let Some((ctor_res, ctor_vis)) = self.struct_constructors.get(&def_id).cloned() { - if is_expected(ctor_res) && self.is_accessible(ctor_vis) { + if is_expected(ctor_res) && + self.is_accessible_from(ctor_vis, self.current_module) { let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; self.session.buffer_lint(lint, id, span, "private struct constructors are not usable through \ @@ -3540,8 +3586,7 @@ impl<'a> Resolver<'a> { let cl = CrateLint::No; let ns = Some(ns); if let PathResult::Module(_) | PathResult::NonModule(_) = - self.resolve_path_without_parent_scope(&std_path, ns, false, span, cl) - { + self.resolve_path(&std_path, ns, false, span, cl) { // check if we wrote `str::from_utf8` instead of `std::str::from_utf8` let item_span = path.iter().last().map(|segment| segment.ident.span) .unwrap_or(span); @@ -3678,13 +3723,12 @@ impl<'a> Resolver<'a> { primary_ns: Namespace, span: Span, defer_to_typeck: bool, - global_by_default: bool, crate_lint: CrateLint, ) -> Option { let mut fin_res = None; for (i, ns) in [primary_ns, TypeNS, ValueNS].iter().cloned().enumerate() { if i == 0 || ns != primary_ns { - match self.resolve_qpath(id, qself, path, ns, span, global_by_default, crate_lint) { + match self.resolve_qpath(id, qself, path, ns, span, crate_lint) { // If defer_to_typeck, then resolution > no resolution, // otherwise full resolution > partial resolution > no resolution. Some(partial_res) if partial_res.unresolved_segments() == 0 || @@ -3700,10 +3744,9 @@ impl<'a> Resolver<'a> { if qself.is_none() { let path_seg = |seg: &Segment| ast::PathSegment::from_ident(seg.ident); let path = Path { segments: path.iter().map(path_seg).collect(), span }; - let parent_scope = - ParentScope { module: self.current_module, ..self.dummy_parent_scope() }; + let parent_scope = &self.parent_scope(); if let Ok((_, res)) = - self.resolve_macro_path(&path, None, &parent_scope, false, false) { + self.resolve_macro_path(&path, None, parent_scope, false, false) { return Some(PartialRes::new(res)); } } @@ -3719,18 +3762,15 @@ impl<'a> Resolver<'a> { path: &[Segment], ns: Namespace, span: Span, - global_by_default: bool, crate_lint: CrateLint, ) -> Option { debug!( - "resolve_qpath(id={:?}, qself={:?}, path={:?}, \ - ns={:?}, span={:?}, global_by_default={:?})", + "resolve_qpath(id={:?}, qself={:?}, path={:?}, ns={:?}, span={:?})", id, qself, path, ns, span, - global_by_default, ); if let Some(qself) = qself { @@ -3779,13 +3819,7 @@ impl<'a> Resolver<'a> { )); } - let result = match self.resolve_path_without_parent_scope( - &path, - Some(ns), - true, - span, - crate_lint, - ) { + let result = match self.resolve_path(&path, Some(ns), true, span, crate_lint) { PathResult::NonModule(path_res) => path_res, PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { PartialRes::new(module.res().unwrap()) @@ -3820,11 +3854,11 @@ impl<'a> Resolver<'a> { PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; - if path.len() > 1 && !global_by_default && result.base_res() != Res::Err && + if path.len() > 1 && result.base_res() != Res::Err && path[0].ident.name != kw::PathRoot && path[0].ident.name != kw::DollarCrate { let unqualified_result = { - match self.resolve_path_without_parent_scope( + match self.resolve_path( &[*path.last().unwrap()], Some(ns), false, @@ -3845,23 +3879,24 @@ impl<'a> Resolver<'a> { Some(result) } +} - fn resolve_path_without_parent_scope( +impl<'a> Resolver<'a> { + fn resolve_path( &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import + parent_scope: &ParentScope<'a>, record_used: bool, path_span: Span, crate_lint: CrateLint, ) -> PathResult<'a> { - // Macro and import paths must have full parent scope available during resolution, - // other paths will do okay with parent module alone. - assert!(opt_ns != None && opt_ns != Some(MacroNS)); - let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() }; - self.resolve_path(path, opt_ns, &parent_scope, record_used, path_span, crate_lint) + self.resolve_path_with_ribs( + path, opt_ns, parent_scope, record_used, path_span, crate_lint, &Default::default() + ) } - fn resolve_path( + fn resolve_path_with_ribs( &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import @@ -3869,11 +3904,11 @@ impl<'a> Resolver<'a> { record_used: bool, path_span: Span, crate_lint: CrateLint, + ribs: &PerNS>>, ) -> PathResult<'a> { let mut module = None; let mut allow_super = true; let mut second_binding = None; - self.current_module = parent_scope.module; debug!( "resolve_path(path={:?}, opt_ns={:?}, record_used={:?}, \ @@ -3910,7 +3945,7 @@ impl<'a> Resolver<'a> { if allow_super && name == kw::Super { let mut ctxt = ident.span.ctxt().modern(); let self_module = match i { - 0 => Some(self.resolve_self(&mut ctxt, self.current_module)), + 0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)), _ => match module { Some(ModuleOrUniformRoot::Module(module)) => Some(module), _ => None, @@ -3935,7 +3970,7 @@ impl<'a> Resolver<'a> { if name == kw::SelfLower { let mut ctxt = ident.span.ctxt().modern(); module = Some(ModuleOrUniformRoot::Module( - self.resolve_self(&mut ctxt, self.current_module))); + self.resolve_self(&mut ctxt, parent_scope.module))); continue; } if name == kw::PathRoot && ident.span.rust_2018() { @@ -3980,7 +4015,9 @@ impl<'a> Resolver<'a> { } let binding = if let Some(module) = module { - self.resolve_ident_in_module(module, ident, ns, None, record_used, path_span) + self.resolve_ident_in_module( + module, ident, ns, parent_scope, record_used, path_span + ) } else if opt_ns.is_none() || opt_ns == Some(MacroNS) { assert!(ns == TypeNS); let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module }; @@ -3989,7 +4026,9 @@ impl<'a> Resolver<'a> { } else { let record_used_id = if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None }; - match self.resolve_ident_in_lexical_scope(ident, ns, record_used_id, path_span) { + match self.resolve_ident_in_lexical_scope( + ident, ns, parent_scope, record_used_id, path_span, &ribs[ns] + ) { // we found a locally-imported or available item/module Some(LexicalScopeBinding::Item(binding)) => Ok(binding), // we found a local variable or type param @@ -4176,17 +4215,17 @@ impl<'a> Resolver<'a> { // Validate a local resolution (from ribs). fn validate_res_from_ribs( &mut self, - ns: Namespace, rib_index: usize, res: Res, record_used: bool, span: Span, + all_ribs: &[Rib<'a>], ) -> Res { debug!("validate_res_from_ribs({:?})", res); - let ribs = &self.ribs[ns][rib_index + 1..]; + let ribs = &all_ribs[rib_index + 1..]; // An invalid forward use of a type parameter from a previous default. - if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind { + if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind { if record_used { resolve_error(self, span, ResolutionError::ForwardDeclaredTyParam); } @@ -4195,7 +4234,7 @@ impl<'a> Resolver<'a> { } // An invalid use of a type parameter as the type of a const parameter. - if let TyParamAsConstParamTy = self.ribs[ns][rib_index].kind { + if let TyParamAsConstParamTy = all_ribs[rib_index].kind { if record_used { resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam); } @@ -4288,9 +4327,11 @@ impl<'a> Resolver<'a> { } res } +} +impl<'a> LateResolutionVisitor<'a, '_> { fn with_resolved_label(&mut self, label: Option