From 907120637ec1c28f116e612266cdb83cb5a854a9 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 11 Nov 2016 10:51:15 +0000 Subject: [PATCH 1/8] Add field `module.unresolved_invocations`. --- src/librustc_resolve/build_reduced_graph.rs | 4 +++- src/librustc_resolve/lib.rs | 4 ++++ src/librustc_resolve/macros.rs | 1 + src/librustc_resolve/resolve_imports.rs | 8 ++++++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 99e7a9042c0ce..2caa78a95ef96 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -638,7 +638,9 @@ pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { - let invocation = self.resolver.invocations[&Mark::from_placeholder_id(id)]; + let mark = Mark::from_placeholder_id(id); + self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark); + let invocation = self.resolver.invocations[&mark]; invocation.module.set(self.resolver.current_module); invocation.legacy_scope.set(self.legacy_scope); invocation diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 73b7b185b2409..8f743cb6d06c5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -799,6 +799,9 @@ pub struct ModuleS<'a> { resolutions: RefCell>>>, + // Macro invocations that can expand into items in this module. + unresolved_invocations: RefCell>, + no_implicit_prelude: bool, glob_importers: RefCell>>, @@ -822,6 +825,7 @@ impl<'a> ModuleS<'a> { kind: kind, normal_ancestor_id: None, resolutions: RefCell::new(FxHashMap()), + unresolved_invocations: RefCell::new(FxHashSet()), no_implicit_prelude: false, glob_importers: RefCell::new(Vec::new()), globs: RefCell::new((Vec::new())), diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index f30c129c48fd2..afbe6f0d518b9 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -131,6 +131,7 @@ impl<'a> base::Resolver for Resolver<'a> { self.collect_def_ids(invocation, expansion); self.current_module = invocation.module.get(); + self.current_module.unresolved_invocations.borrow_mut().remove(&mark); let mut visitor = BuildReducedGraphVisitor { resolver: self, legacy_scope: LegacyScope::Invocation(invocation), diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 5d66caec31b3e..44ce48fe615f7 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -192,7 +192,7 @@ impl<'a> Resolver<'a> { } // If the resolution doesn't depend on glob definability, check privacy and return. - if let Some(result) = self.try_result(&resolution, ns) { + if let Some(result) = self.try_result(&resolution, module, ns) { return result.and_then(|binding| { if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) || binding.is_extern_crate() { // c.f. issue #37020 @@ -222,7 +222,7 @@ impl<'a> Resolver<'a> { // Returns Some(the resolution of the name), or None if the resolution depends // on whether more globs can define the name. - fn try_result(&mut self, resolution: &NameResolution<'a>, ns: Namespace) + fn try_result(&mut self, resolution: &NameResolution<'a>, module: Module<'a>, ns: Namespace) -> Option>> { match resolution.binding { Some(binding) if !binding.is_glob_import() => @@ -250,6 +250,10 @@ impl<'a> Resolver<'a> { SingleImports::MaybeOne(_) | SingleImports::None => {}, } + if !module.unresolved_invocations.borrow().is_empty() { + return Some(Indeterminate); + } + resolution.binding.map(Success) } From 641274f9072a3c2b5400d99d671d64ef2d696624 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 10 Nov 2016 10:11:25 +0000 Subject: [PATCH 2/8] Resolve imports during expansion. --- src/librustc_driver/driver.rs | 2 -- src/librustc_resolve/lib.rs | 3 ++- src/librustc_resolve/macros.rs | 5 +++++ src/librustc_resolve/resolve_imports.rs | 25 ++++++------------------- src/libsyntax/ext/base.rs | 2 ++ src/libsyntax/ext/expand.rs | 13 +++++++++++-- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 2dd83f7082359..5466c8871d491 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -755,8 +755,6 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, || ast_validation::check_crate(sess, &krate)); time(sess.time_passes(), "name resolution", || -> CompileResult { - resolver.resolve_imports(); - // Since import resolution will eventually happen in expansion, // don't perform `after_expand` until after import resolution. after_expand(&krate)?; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8f743cb6d06c5..d2f2b07886100 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -76,7 +76,7 @@ use std::fmt; use std::mem::replace; use std::rc::Rc; -use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution}; +use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; use macros::{InvocationData, LegacyBinding, LegacyScope}; // NB: This module needs to be declared first so diagnostics are @@ -1335,6 +1335,7 @@ 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; visit::walk_crate(self, krate); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index afbe6f0d518b9..82f271e10b95a 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -10,6 +10,7 @@ use {Module, ModuleKind, Resolver}; use build_reduced_graph::BuildReducedGraphVisitor; +use resolve_imports::ImportResolver; use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}; use rustc::hir::def::{Def, Export}; use rustc::hir::map::{self, DefCollector}; @@ -185,6 +186,10 @@ impl<'a> base::Resolver for Resolver<'a> { self.macros_at_scope.insert(id, macros); } + fn resolve_imports(&mut self) { + ImportResolver { resolver: self }.resolve_imports() + } + fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option { for i in 0..attrs.len() { let name = intern(&attrs[i].name()); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 44ce48fe615f7..159b5706ec107 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -32,12 +32,6 @@ use syntax_pos::Span; use std::cell::{Cell, RefCell}; use std::mem; -impl<'a> Resolver<'a> { - pub fn resolve_imports(&mut self) { - ImportResolver { resolver: self }.resolve_imports(); - } -} - /// Contains data for specific types of import directives. #[derive(Clone, Debug)] pub enum ImportDirectiveSubclass<'a> { @@ -399,8 +393,8 @@ impl<'a> Resolver<'a> { } } -struct ImportResolver<'a, 'b: 'a> { - resolver: &'a mut Resolver<'b>, +pub struct ImportResolver<'a, 'b: 'a> { + pub resolver: &'a mut Resolver<'b>, } impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> { @@ -433,28 +427,21 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { /// Resolves all imports for the crate. This method performs the fixed- /// point iteration. - fn resolve_imports(&mut self) { - let mut i = 0; + pub fn resolve_imports(&mut self) { let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1; - while self.indeterminate_imports.len() < prev_num_indeterminates { prev_num_indeterminates = self.indeterminate_imports.len(); - debug!("(resolving imports) iteration {}, {} imports left", i, prev_num_indeterminates); - - let mut imports = Vec::new(); - ::std::mem::swap(&mut imports, &mut self.indeterminate_imports); - - for import in imports { + for import in mem::replace(&mut self.indeterminate_imports, Vec::new()) { match self.resolve_import(&import) { Failed(_) => self.determined_imports.push(import), Indeterminate => self.indeterminate_imports.push(import), Success(()) => self.determined_imports.push(import), } } - - i += 1; } + } + pub fn finalize_imports(&mut self) { for module in self.arenas.local_modules().iter() { self.finalize_resolutions_in(module); } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b4ac576f57a53..7f66b060052ea 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -524,6 +524,7 @@ pub trait Resolver { fn add_ext(&mut self, ident: ast::Ident, ext: Rc); fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec); + fn resolve_imports(&mut self); fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option; fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy>; @@ -547,6 +548,7 @@ impl Resolver for DummyResolver { fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc) {} fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec) {} + fn resolve_imports(&mut self) {} fn find_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) -> Result, Determinacy> { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 877b312539f92..8e0c3ce8448da 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -222,6 +222,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.current_expansion.depth = 0; let (expansion, mut invocations) = self.collect_invocations(expansion); + self.resolve_imports(); invocations.reverse(); let mut expansions = Vec::new(); @@ -230,9 +231,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { loop { let invoc = if let Some(invoc) = invocations.pop() { invoc - } else if undetermined_invocations.is_empty() { - break } else { + self.resolve_imports(); + if undetermined_invocations.is_empty() { break } invocations = mem::replace(&mut undetermined_invocations, Vec::new()); force = !mem::replace(&mut progress, false); continue @@ -292,6 +293,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { expansion.fold_with(&mut placeholder_expander) } + fn resolve_imports(&mut self) { + if self.monotonic { + let err_count = self.cx.parse_sess.span_diagnostic.err_count(); + self.cx.resolver.resolve_imports(); + self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count; + } + } + fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec) { let result = { let mut collector = InvocationCollector { From 83aac43f520463ea7fe86fe73bb1cc8f7e22abaf Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 7 Nov 2016 22:08:26 +0000 Subject: [PATCH 3/8] Refactor `Resolver::builtin_macros` to use `NameBinding`s instead of `DefId`s. --- src/librustc_resolve/build_reduced_graph.rs | 12 +++++++----- src/librustc_resolve/lib.rs | 2 +- src/librustc_resolve/macros.rs | 18 ++++++++++++------ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 2caa78a95ef96..4e631a2076b20 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -518,10 +518,12 @@ impl<'b> Resolver<'b> { module.populated.set(true) } - fn legacy_import_macro(&mut self, name: Name, def: Def, span: Span, allow_shadowing: bool) { - self.used_crates.insert(def.def_id().krate); + fn legacy_import_macro( + &mut self, name: Name, binding: &'b NameBinding<'b>, span: Span, allow_shadowing: bool, + ) { + self.used_crates.insert(binding.def().def_id().krate); self.macro_names.insert(name); - if self.builtin_macros.insert(name, def.def_id()).is_some() && !allow_shadowing { + if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing { let msg = format!("`{}` is already in scope", name); let note = "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)"; @@ -548,13 +550,13 @@ impl<'b> Resolver<'b> { if let Some(span) = legacy_imports.import_all { module.for_each_child(|name, ns, binding| if ns == MacroNS { - self.legacy_import_macro(name, binding.def(), span, allow_shadowing); + self.legacy_import_macro(name, binding, span, allow_shadowing); }); } else { for (name, span) in legacy_imports.imports { let result = self.resolve_name_in_module(module, name, MacroNS, false, None); if let Success(binding) = result { - self.legacy_import_macro(name, binding.def(), span, allow_shadowing); + self.legacy_import_macro(name, binding, span, allow_shadowing); } else { span_err!(self.session, span, E0469, "imported macro not found"); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d2f2b07886100..d8fb56018a1c1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1115,7 +1115,7 @@ pub struct Resolver<'a> { pub exported_macros: Vec, crate_loader: &'a mut CrateLoader, macro_names: FxHashSet, - builtin_macros: FxHashMap, + builtin_macros: FxHashMap>, lexical_macro_resolutions: Vec<(Name, LegacyScope<'a>)>, macro_map: FxHashMap>, macro_exports: Vec, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 82f271e10b95a..8c6a1ab49ecb8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {Module, ModuleKind, Resolver}; +use {Module, ModuleKind, NameBinding, NameBindingKind, Resolver}; use build_reduced_graph::BuildReducedGraphVisitor; use resolve_imports::ImportResolver; use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}; use rustc::hir::def::{Def, Export}; use rustc::hir::map::{self, DefCollector}; +use rustc::ty; use std::cell::Cell; use std::rc::Rc; use syntax::ast; @@ -28,7 +29,7 @@ use syntax::parse::token::intern; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::Visitor; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; #[derive(Clone)] pub struct InvocationData<'a> { @@ -179,7 +180,12 @@ impl<'a> base::Resolver for Resolver<'a> { index: DefIndex::new(self.macro_map.len()), }; self.macro_map.insert(def_id, ext); - self.builtin_macros.insert(ident.name, def_id); + let binding = self.arenas.alloc_name_binding(NameBinding { + kind: NameBindingKind::Def(Def::Macro(def_id)), + span: DUMMY_SP, + vis: ty::Visibility::PrivateExternal, + }); + self.builtin_macros.insert(ident.name, binding); } fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec) { @@ -193,8 +199,8 @@ impl<'a> base::Resolver for Resolver<'a> { fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option { for i in 0..attrs.len() { let name = intern(&attrs[i].name()); - match self.builtin_macros.get(&name) { - Some(&def_id) => match *self.get_macro(Def::Macro(def_id)) { + match self.builtin_macros.get(&name).cloned() { + Some(binding) => match *self.get_macro(binding.def()) { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { return Some(attrs.remove(i)) } @@ -273,7 +279,7 @@ impl<'a> Resolver<'a> { if let Some(scope) = possible_time_travel { self.lexical_macro_resolutions.push((name, scope)); } - self.builtin_macros.get(&name).cloned().map(|def_id| self.get_macro(Def::Macro(def_id))) + self.builtin_macros.get(&name).cloned().map(|binding| self.get_macro(binding.def())) } fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) { From 1bbf7a43d3c9f35d7066c5382fa2db898c1e467a Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 7 Nov 2016 22:23:26 +0000 Subject: [PATCH 4/8] Add field `expansion: Mark` to `NameBinding`. --- src/librustc_resolve/build_reduced_graph.rs | 100 ++++++++++++-------- src/librustc_resolve/lib.rs | 2 + src/librustc_resolve/macros.rs | 1 + src/librustc_resolve/resolve_imports.rs | 8 +- 4 files changed, 68 insertions(+), 43 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 4e631a2076b20..bfbc5b3163ac1 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -45,15 +45,25 @@ use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; -impl<'a> ToNameBinding<'a> for (Module<'a>, Span, ty::Visibility) { +impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) { fn to_name_binding(self) -> NameBinding<'a> { - NameBinding { kind: NameBindingKind::Module(self.0), span: self.1, vis: self.2 } + NameBinding { + kind: NameBindingKind::Module(self.0), + vis: self.1, + span: self.2, + expansion: self.3, + } } } -impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) { +impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) { fn to_name_binding(self) -> NameBinding<'a> { - NameBinding { kind: NameBindingKind::Def(self.0), span: self.1, vis: self.2 } + NameBinding { + kind: NameBindingKind::Def(self.0), + vis: self.1, + span: self.2, + expansion: self.3, + } } } @@ -148,8 +158,9 @@ impl<'b> Resolver<'b> { } let subclass = ImportDirectiveSubclass::single(binding.name, source.name); - let span = view_path.span; - self.add_import_directive(module_path, subclass, span, item.id, vis); + self.add_import_directive( + module_path, subclass, view_path.span, item.id, vis, expansion, + ); } ViewPathList(_, ref source_items) => { // Make sure there's at most one `mod` import in the list. @@ -196,8 +207,10 @@ impl<'b> Resolver<'b> { } }; let subclass = ImportDirectiveSubclass::single(rename, name); - let (span, id) = (source_item.span, source_item.node.id); - self.add_import_directive(module_path, subclass, span, id, vis); + let id = source_item.node.id; + self.add_import_directive( + module_path, subclass, source_item.span, id, vis, expansion, + ); } } ViewPathGlob(_) => { @@ -205,8 +218,9 @@ impl<'b> Resolver<'b> { is_prelude: is_prelude, max_vis: Cell::new(ty::Visibility::PrivateExternal), }; - let span = view_path.span; - self.add_import_directive(module_path, subclass, span, item.id, vis); + self.add_import_directive( + module_path, subclass, view_path.span, item.id, vis, expansion, + ); } } } @@ -217,7 +231,7 @@ impl<'b> Resolver<'b> { // n.b. we don't need to look at the path option here, because cstore already did let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap(); let module = self.get_extern_crate_root(crate_id); - let binding = (module, sp, ty::Visibility::Public).to_name_binding(); + let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(); let binding = self.arenas.alloc_name_binding(binding); let directive = self.arenas.alloc_import_directive(ImportDirective { id: item.id, @@ -227,6 +241,7 @@ impl<'b> Resolver<'b> { span: item.span, module_path: Vec::new(), vis: Cell::new(vis), + expansion: expansion, }); let imported_binding = self.import(binding, directive); self.define(parent, name, TypeNS, imported_binding); @@ -245,7 +260,7 @@ impl<'b> Resolver<'b> { normal_ancestor_id: Some(item.id), ..ModuleS::new(Some(parent), ModuleKind::Def(def, name)) }); - self.define(parent, name, TypeNS, (module, sp, vis)); + self.define(parent, name, TypeNS, (module, vis, sp, expansion)); self.module_map.insert(item.id, module); // Descend into the module. @@ -258,30 +273,30 @@ impl<'b> Resolver<'b> { ItemKind::Static(_, m, _) => { let mutbl = m == Mutability::Mutable; let def = Def::Static(self.definitions.local_def_id(item.id), mutbl); - self.define(parent, name, ValueNS, (def, sp, vis)); + self.define(parent, name, ValueNS, (def, vis, sp, expansion)); } ItemKind::Const(..) => { let def = Def::Const(self.definitions.local_def_id(item.id)); - self.define(parent, name, ValueNS, (def, sp, vis)); + self.define(parent, name, ValueNS, (def, vis, sp, expansion)); } ItemKind::Fn(..) => { let def = Def::Fn(self.definitions.local_def_id(item.id)); - self.define(parent, name, ValueNS, (def, sp, vis)); + self.define(parent, name, ValueNS, (def, vis, sp, expansion)); } // These items live in the type namespace. ItemKind::Ty(..) => { let def = Def::TyAlias(self.definitions.local_def_id(item.id)); - self.define(parent, name, TypeNS, (def, sp, vis)); + self.define(parent, name, TypeNS, (def, vis, sp, expansion)); } ItemKind::Enum(ref enum_definition, _) => { let def = Def::Enum(self.definitions.local_def_id(item.id)); let module = self.new_module(parent, ModuleKind::Def(def, name), true); - self.define(parent, name, TypeNS, (module, sp, vis)); + self.define(parent, name, TypeNS, (module, vis, sp, expansion)); for variant in &(*enum_definition).variants { - self.build_reduced_graph_for_variant(variant, module, vis); + self.build_reduced_graph_for_variant(variant, module, vis, expansion); } } @@ -289,14 +304,14 @@ impl<'b> Resolver<'b> { ItemKind::Struct(ref struct_def, _) => { // Define a name in the type namespace. let def = Def::Struct(self.definitions.local_def_id(item.id)); - self.define(parent, name, TypeNS, (def, sp, vis)); + self.define(parent, name, TypeNS, (def, vis, sp, expansion)); // If this is a tuple or unit struct, define a name // in the value namespace as well. if !struct_def.is_struct() { let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), CtorKind::from_ast(struct_def)); - self.define(parent, name, ValueNS, (ctor_def, sp, vis)); + self.define(parent, name, ValueNS, (ctor_def, vis, sp, expansion)); } // Record field names for error reporting. @@ -310,7 +325,7 @@ impl<'b> Resolver<'b> { ItemKind::Union(ref vdata, _) => { let def = Def::Union(self.definitions.local_def_id(item.id)); - self.define(parent, name, TypeNS, (def, sp, vis)); + self.define(parent, name, TypeNS, (def, vis, sp, expansion)); // Record field names for error reporting. let field_names = vdata.fields().iter().filter_map(|field| { @@ -329,7 +344,7 @@ impl<'b> Resolver<'b> { // Add all the items within to a new module. let module = self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), name), true); - self.define(parent, name, TypeNS, (module, sp, vis)); + self.define(parent, name, TypeNS, (module, vis, sp, expansion)); self.current_module = module; } ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"), @@ -338,27 +353,28 @@ impl<'b> Resolver<'b> { // Constructs the reduced graph for one variant. Variants exist in the // type and value namespaces. - fn build_reduced_graph_for_variant(&mut self, - variant: &Variant, - parent: Module<'b>, - vis: ty::Visibility) { + fn build_reduced_graph_for_variant( + &mut self, variant: &Variant, parent: Module<'b>, vis: ty::Visibility, expansion: Mark, + ) { let name = variant.node.name.name; let def_id = self.definitions.local_def_id(variant.node.data.id()); // Define a name in the type namespace. let def = Def::Variant(def_id); - self.define(parent, name, TypeNS, (def, variant.span, vis)); + self.define(parent, name, TypeNS, (def, vis, variant.span, expansion)); // Define a constructor name in the value namespace. // Braced variants, unlike structs, generate unusable names in // value namespace, they are reserved for possible future use. let ctor_kind = CtorKind::from_ast(&variant.node.data); let ctor_def = Def::VariantCtor(def_id, ctor_kind); - self.define(parent, name, ValueNS, (ctor_def, variant.span, vis)); + self.define(parent, name, ValueNS, (ctor_def, vis, variant.span, expansion)); } /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(&mut self, foreign_item: &ForeignItem) { + fn build_reduced_graph_for_foreign_item( + &mut self, foreign_item: &ForeignItem, expansion: Mark, + ) { let parent = self.current_module; let name = foreign_item.ident.name; @@ -371,7 +387,7 @@ impl<'b> Resolver<'b> { } }; let vis = self.resolve_visibility(&foreign_item.vis); - self.define(parent, name, ValueNS, (def, foreign_item.span, vis)); + self.define(parent, name, ValueNS, (def, vis, foreign_item.span, expansion)); } fn build_reduced_graph_for_block(&mut self, block: &Block) { @@ -404,24 +420,24 @@ impl<'b> Resolver<'b> { match def { Def::Mod(..) | Def::Enum(..) => { let module = self.new_module(parent, ModuleKind::Def(def, name), false); - self.define(parent, name, TypeNS, (module, DUMMY_SP, vis)); + self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root())); } Def::Variant(..) => { - self.define(parent, name, TypeNS, (def, DUMMY_SP, vis)); + self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root())); } Def::VariantCtor(..) => { - self.define(parent, name, ValueNS, (def, DUMMY_SP, vis)); + self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::AssociatedConst(..) | Def::Method(..) => { - self.define(parent, name, ValueNS, (def, DUMMY_SP, vis)); + self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Trait(..) => { let module = self.new_module(parent, ModuleKind::Def(def, name), false); - self.define(parent, name, TypeNS, (module, DUMMY_SP, vis)); + self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root())); // If this is a trait, add all the trait item names to the trait info. let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id); @@ -433,27 +449,27 @@ impl<'b> Resolver<'b> { } } Def::TyAlias(..) | Def::AssociatedTy(..) => { - self.define(parent, name, TypeNS, (def, DUMMY_SP, vis)); + self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Struct(..) => { - self.define(parent, name, TypeNS, (def, DUMMY_SP, vis)); + self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root())); // Record field names for error reporting. let field_names = self.session.cstore.struct_field_names(def_id); self.insert_field_names(def_id, field_names); } Def::StructCtor(..) => { - self.define(parent, name, ValueNS, (def, DUMMY_SP, vis)); + self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Union(..) => { - self.define(parent, name, TypeNS, (def, DUMMY_SP, vis)); + self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root())); // Record field names for error reporting. let field_names = self.session.cstore.struct_field_names(def_id); self.insert_field_names(def_id, field_names); } Def::Macro(..) => { - self.define(parent, name, MacroNS, (def, DUMMY_SP, vis)); + self.define(parent, name, MacroNS, (def, vis, DUMMY_SP, Mark::root())); } Def::Local(..) | Def::PrimTy(..) | @@ -695,7 +711,7 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> { } fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { - self.resolver.build_reduced_graph_for_foreign_item(foreign_item); + self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion); visit::walk_foreign_item(self, foreign_item); } @@ -732,7 +748,7 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> { self.resolver.trait_item_map.insert((item.ident.name, def_id), is_static_method); let vis = ty::Visibility::Public; - self.resolver.define(parent, item.ident.name, ns, (def, item.span, vis)); + self.resolver.define(parent, item.ident.name, ns, (def, vis, item.span, self.expansion)); self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor visit::walk_trait_item(self, item); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d8fb56018a1c1..4164f3a897d64 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -881,6 +881,7 @@ impl<'a> fmt::Debug for ModuleS<'a> { #[derive(Clone, Debug)] pub struct NameBinding<'a> { kind: NameBindingKind<'a>, + expansion: Mark, span: Span, vis: ty::Visibility, } @@ -1304,6 +1305,7 @@ impl<'a> Resolver<'a> { arenas: arenas, dummy_binding: arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(Def::Err), + expansion: Mark::root(), span: DUMMY_SP, vis: ty::Visibility::Public, }), diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 8c6a1ab49ecb8..2d434d660ea5a 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -184,6 +184,7 @@ impl<'a> base::Resolver for Resolver<'a> { kind: NameBindingKind::Def(Def::Macro(def_id)), span: DUMMY_SP, vis: ty::Visibility::PrivateExternal, + expansion: Mark::root(), }); self.builtin_macros.insert(ident.name, binding); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 159b5706ec107..01d09a3b7c4bb 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -26,6 +26,7 @@ use rustc::hir::def::*; use syntax::ast::{Ident, NodeId, Name}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; +use syntax::ext::hygiene::Mark; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; @@ -70,6 +71,7 @@ pub struct ImportDirective<'a> { pub subclass: ImportDirectiveSubclass<'a>, pub span: Span, pub vis: Cell, + pub expansion: Mark, } impl<'a> ImportDirective<'a> { @@ -257,7 +259,8 @@ impl<'a> Resolver<'a> { subclass: ImportDirectiveSubclass<'a>, span: Span, id: NodeId, - vis: ty::Visibility) { + vis: ty::Visibility, + expansion: Mark) { let current_module = self.current_module; let directive = self.arenas.alloc_import_directive(ImportDirective { parent: current_module, @@ -267,6 +270,7 @@ impl<'a> Resolver<'a> { span: span, id: id, vis: Cell::new(vis), + expansion: expansion, }); self.indeterminate_imports.push(directive); @@ -310,6 +314,7 @@ impl<'a> Resolver<'a> { }, span: directive.span, vis: vis, + expansion: directive.expansion, } } @@ -336,6 +341,7 @@ impl<'a> Resolver<'a> { binding.vis }, span: old_binding.span, + expansion: Mark::root(), })); } else if !old_binding.vis.is_at_least(binding.vis, this) { // We are glob-importing the same item but with greater visibility. From b25c063caa5e4ab8202527e3cfcfe04196e0836f Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 10 Nov 2016 06:19:54 +0000 Subject: [PATCH 5/8] Refactor out `PerNS`. --- src/librustc_resolve/build_reduced_graph.rs | 15 +- src/librustc_resolve/check_unused.rs | 6 +- src/librustc_resolve/lib.rs | 144 +++++++------ src/librustc_resolve/resolve_imports.rs | 195 ++++++++---------- .../blind-item-block-item-shadow.rs | 2 +- src/test/compile-fail/double-type-import.rs | 2 +- 6 files changed, 186 insertions(+), 178 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index bfbc5b3163ac1..5917a1a0d1759 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -15,7 +15,7 @@ use macros::{InvocationData, LegacyScope}; use resolve_imports::ImportDirective; -use resolve_imports::ImportDirectiveSubclass::{self, GlobImport}; +use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; use {Resolver, Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use ResolveResult::Success; @@ -37,6 +37,7 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::ext::base::SyntaxExtension; +use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::expand::mark_tts; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -157,7 +158,11 @@ impl<'b> Resolver<'b> { .emit(); } - let subclass = ImportDirectiveSubclass::single(binding.name, source.name); + let subclass = SingleImport { + target: binding.name, + source: source.name, + result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), + }; self.add_import_directive( module_path, subclass, view_path.span, item.id, vis, expansion, ); @@ -206,7 +211,11 @@ impl<'b> Resolver<'b> { (module_path.to_vec(), name, rename) } }; - let subclass = ImportDirectiveSubclass::single(rename, name); + let subclass = SingleImport { + target: rename, + source: name, + result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), + }; let id = source_item.node.id; self.add_import_directive( module_path, subclass, source_item.span, id, vis, expansion, diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 36e05a433414e..492c5e695bbbb 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -22,7 +22,6 @@ use std::ops::{Deref, DerefMut}; use Resolver; -use Namespace::{TypeNS, ValueNS}; use rustc::lint; use rustc::util::nodemap::NodeMap; @@ -56,8 +55,9 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { // We have information about whether `use` (import) directives are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) { - if !self.used_imports.contains(&(id, TypeNS)) && - !self.used_imports.contains(&(id, ValueNS)) { + let mut used = false; + self.per_ns(|this, ns| used |= this.used_imports.contains(&(id, ns))); + if !used { if self.maybe_unused_trait_imports.contains(&id) { // Check later. return; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4164f3a897d64..af72977024253 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -536,6 +536,33 @@ pub enum Namespace { MacroNS, } +#[derive(Clone, Default, Debug)] +pub struct PerNS { + value_ns: T, + type_ns: T, +} + +impl ::std::ops::Index for PerNS { + type Output = T; + fn index(&self, ns: Namespace) -> &T { + match ns { + ValueNS => &self.value_ns, + TypeNS => &self.type_ns, + MacroNS => unreachable!(), + } + } +} + +impl ::std::ops::IndexMut for PerNS { + fn index_mut(&mut self, ns: Namespace) -> &mut T { + match ns { + ValueNS => &mut self.value_ns, + TypeNS => &mut self.type_ns, + MacroNS => unreachable!(), + } + } +} + impl<'a> Visitor for Resolver<'a> { fn visit_item(&mut self, item: &Item) { self.resolve_item(item); @@ -612,7 +639,7 @@ impl<'a> Visitor for Resolver<'a> { }; // Create a value rib for the function. - self.value_ribs.push(Rib::new(rib_kind)); + self.ribs[ValueNS].push(Rib::new(rib_kind)); // Create a label rib for the function. self.label_ribs.push(Rib::new(rib_kind)); @@ -642,7 +669,7 @@ impl<'a> Visitor for Resolver<'a> { debug!("(resolving function) leaving function"); self.label_ribs.pop(); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); } } @@ -1049,12 +1076,9 @@ pub struct Resolver<'a> { // The module that represents the current item scope. current_module: Module<'a>, - // The current set of local scopes, for values. + // The current set of local scopes for types and values. // FIXME #4948: Reuse ribs to avoid allocation. - value_ribs: Vec>, - - // The current set of local scopes, for types. - type_ribs: Vec>, + ribs: PerNS>>, // The current set of local scopes, for labels. label_ribs: Vec>, @@ -1273,8 +1297,10 @@ impl<'a> Resolver<'a> { indeterminate_imports: Vec::new(), current_module: graph_root, - value_ribs: vec![Rib::new(ModuleRibKind(graph_root))], - type_ribs: vec![Rib::new(ModuleRibKind(graph_root))], + ribs: PerNS { + value_ns: vec![Rib::new(ModuleRibKind(graph_root))], + type_ns: vec![Rib::new(ModuleRibKind(graph_root))], + }, label_ribs: Vec::new(), current_trait_ref: None, @@ -1335,6 +1361,13 @@ impl<'a> Resolver<'a> { } } + fn per_ns T>(&mut self, mut f: F) -> PerNS { + PerNS { + type_ns: f(self, TypeNS), + value_ns: f(self, ValueNS), + } + } + /// Entry point to crate resolution. pub fn resolve_crate(&mut self, krate: &Crate) { ImportResolver { resolver: self }.finalize_imports(); @@ -1354,14 +1387,6 @@ impl<'a> Resolver<'a> { }) } - fn get_ribs<'b>(&'b mut self, ns: Namespace) -> &'b mut Vec> { - match ns { - ValueNS => &mut self.value_ribs, - TypeNS => &mut self.type_ribs, - MacroNS => panic!("The macro namespace has no ribs"), - } - } - fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) -> bool /* true if an error was reported */ { // track extern crates for unused_extern_crate lint @@ -1577,8 +1602,8 @@ impl<'a> Resolver<'a> { } // Walk backwards up the ribs in scope. - for i in (0 .. self.get_ribs(ns).len()).rev() { - if let Some(def) = self.get_ribs(ns)[i].bindings.get(&ident).cloned() { + for i in (0 .. self.ribs[ns].len()).rev() { + if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::LocalDef(LocalDef { ribs: Some((ns, i)), @@ -1586,7 +1611,7 @@ impl<'a> Resolver<'a> { })); } - if let ModuleRibKind(module) = self.get_ribs(ns)[i].kind { + if let ModuleRibKind(module) = self.ribs[ns][i].kind { let name = ident.name; let item = self.resolve_name_in_module(module, name, ns, true, record_used); if let Success(binding) = item { @@ -1604,7 +1629,7 @@ impl<'a> Resolver<'a> { } } - if let MacroDefinition(mac) = self.get_ribs(ns)[i].kind { + if let MacroDefinition(mac) = self.ribs[ns][i].kind { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. let (source_ctxt, source_macro) = ident.ctxt.source(); @@ -1689,14 +1714,14 @@ impl<'a> Resolver<'a> { if let Some(module) = module { // Move down in the graph. let orig_module = replace(&mut self.current_module, module); - self.value_ribs.push(Rib::new(ModuleRibKind(module))); - self.type_ribs.push(Rib::new(ModuleRibKind(module))); + self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); + self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); f(self); self.current_module = orig_module; - self.value_ribs.pop(); - self.type_ribs.pop(); + self.ribs[ValueNS].pop(); + self.ribs[TypeNS].pop(); } else { f(self); } @@ -1871,7 +1896,7 @@ impl<'a> Resolver<'a> { function_type_rib.bindings.insert(Ident::with_empty_ctxt(name), def); self.record_def(type_parameter.id, PathResolution::new(def)); } - self.type_ribs.push(function_type_rib); + self.ribs[TypeNS].push(function_type_rib); } NoTypeParameters => { @@ -1882,7 +1907,7 @@ impl<'a> Resolver<'a> { f(self); if let HasTypeParameters(..) = type_parameters { - self.type_ribs.pop(); + self.ribs[TypeNS].pop(); } } @@ -1897,11 +1922,11 @@ impl<'a> Resolver<'a> { fn with_constant_rib(&mut self, f: F) where F: FnOnce(&mut Resolver) { - self.value_ribs.push(Rib::new(ConstantItemRibKind)); - self.type_ribs.push(Rib::new(ConstantItemRibKind)); + self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind)); + self.ribs[TypeNS].push(Rib::new(ConstantItemRibKind)); f(self); - self.type_ribs.pop(); - self.value_ribs.pop(); + self.ribs[TypeNS].pop(); + self.ribs[ValueNS].pop(); } fn resolve_trait_reference(&mut self, @@ -2011,9 +2036,9 @@ impl<'a> Resolver<'a> { // plain insert (no renaming, types are not currently hygienic....) self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def); - self.type_ribs.push(self_type_rib); + self.ribs[TypeNS].push(self_type_rib); f(self); - self.type_ribs.pop(); + self.ribs[TypeNS].pop(); } fn resolve_implementation(&mut self, @@ -2167,7 +2192,7 @@ impl<'a> Resolver<'a> { } fn resolve_arm(&mut self, arm: &Arm) { - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); let mut bindings_list = FxHashMap(); for pattern in &arm.pats { @@ -2181,7 +2206,7 @@ impl<'a> Resolver<'a> { walk_list!(self, visit_expr, &arm.guard); self.visit_expr(&arm.body); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); } fn resolve_block(&mut self, block: &Block) { @@ -2193,11 +2218,11 @@ impl<'a> Resolver<'a> { let mut num_macro_definition_ribs = 0; if let Some(anonymous_module) = anonymous_module { debug!("(resolving block) found anonymous module, moving down"); - self.value_ribs.push(Rib::new(ModuleRibKind(anonymous_module))); - self.type_ribs.push(Rib::new(ModuleRibKind(anonymous_module))); + self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module))); + self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module))); self.current_module = anonymous_module; } else { - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); } // Descend into the block. @@ -2205,7 +2230,7 @@ impl<'a> Resolver<'a> { if let Some(marks) = self.macros_at_scope.remove(&stmt.id) { num_macro_definition_ribs += marks.len() as u32; for mark in marks { - self.value_ribs.push(Rib::new(MacroDefinition(mark))); + self.ribs[ValueNS].push(Rib::new(MacroDefinition(mark))); self.label_ribs.push(Rib::new(MacroDefinition(mark))); } } @@ -2216,12 +2241,12 @@ impl<'a> Resolver<'a> { // Move back up. self.current_module = orig_module; for _ in 0 .. num_macro_definition_ribs { - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); self.label_ribs.pop(); } - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); if let Some(_) = anonymous_module { - self.type_ribs.pop(); + self.ribs[TypeNS].pop(); } debug!("(resolving block) leaving block"); } @@ -2340,7 +2365,7 @@ impl<'a> Resolver<'a> { Some(..) if pat_src == PatternSource::Match => { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. - def = self.value_ribs.last_mut().unwrap().bindings[&ident.node]; + def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node]; } Some(..) => { span_bug!(ident.span, "two bindings with the same name from \ @@ -2350,7 +2375,7 @@ impl<'a> Resolver<'a> { // A completely fresh binding, add to the lists if it's valid. if ident.node.name != keywords::Invalid.name() { bindings.insert(ident.node, outer_pat_id); - self.value_ribs.last_mut().unwrap().bindings.insert(ident.node, def); + self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident.node, def); } } } @@ -2634,9 +2659,8 @@ impl<'a> Resolver<'a> { // Resolve a local definition, potentially adjusting for closures. fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option { let ribs = match local_def.ribs { - Some((TypeNS, i)) => &self.type_ribs[i + 1..], - Some((ValueNS, i)) => &self.value_ribs[i + 1..], - _ => &[] as &[_], + Some((ns, i)) => &self.ribs[ns][i + 1..], + None => &[] as &[_], }; let mut def = local_def.def; match def { @@ -2798,8 +2822,8 @@ impl<'a> Resolver<'a> { where F: FnOnce(&mut Resolver<'a>) -> T, { self.with_empty_ribs(|this| { - this.value_ribs.push(Rib::new(ModuleRibKind(module))); - this.type_ribs.push(Rib::new(ModuleRibKind(module))); + this.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); + this.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); f(this) }) } @@ -2807,13 +2831,11 @@ impl<'a> Resolver<'a> { fn with_empty_ribs(&mut self, f: F) -> T where F: FnOnce(&mut Resolver<'a>) -> T, { - let value_ribs = replace(&mut self.value_ribs, Vec::new()); - let type_ribs = replace(&mut self.type_ribs, Vec::new()); + let ribs = replace(&mut self.ribs, PerNS::>::default()); let label_ribs = replace(&mut self.label_ribs, Vec::new()); let result = f(self); - self.value_ribs = value_ribs; - self.type_ribs = type_ribs; + self.ribs = ribs; self.label_ribs = label_ribs; result } @@ -2865,7 +2887,7 @@ impl<'a> Resolver<'a> { return SuggestionType::Macro(format!("{}!", macro_name)); } - let names = self.value_ribs + let names = self.ribs[ValueNS] .iter() .rev() .flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name)); @@ -2968,7 +2990,7 @@ impl<'a> Resolver<'a> { } else { let mut method_scope = false; let mut is_static = false; - self.value_ribs.iter().rev().all(|rib| { + self.ribs[ValueNS].iter().rev().all(|rib| { method_scope = match rib.kind { MethodRibKind(is_static_) => { is_static = is_static_; @@ -3079,10 +3101,10 @@ impl<'a> Resolver<'a> { ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { self.visit_expr(subexpression); - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); self.resolve_pattern(pattern, PatternSource::IfLet, &mut FxHashMap()); self.visit_block(if_block); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); optional_else.as_ref().map(|expr| self.visit_expr(expr)); } @@ -3096,22 +3118,22 @@ impl<'a> Resolver<'a> { ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => { self.visit_expr(subexpression); - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); self.resolve_pattern(pattern, PatternSource::WhileLet, &mut FxHashMap()); self.resolve_labeled_block(label, expr.id, block); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); } ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => { self.visit_expr(subexpression); - self.value_ribs.push(Rib::new(NormalRibKind)); + self.ribs[ValueNS].push(Rib::new(NormalRibKind)); self.resolve_pattern(pattern, PatternSource::For, &mut FxHashMap()); self.resolve_labeled_block(label, expr.id, block); - self.value_ribs.pop(); + self.ribs[ValueNS].pop(); } ExprKind::Field(ref subexpression, _) => { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 01d09a3b7c4bb..f04f3bf45ee93 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -10,8 +10,8 @@ use self::ImportDirectiveSubclass::*; -use Module; -use Namespace::{self, TypeNS, ValueNS}; +use {Module, PerNS}; +use Namespace::{self, TypeNS}; use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding}; use ResolveResult; use ResolveResult::*; @@ -39,8 +39,7 @@ pub enum ImportDirectiveSubclass<'a> { SingleImport { target: Name, source: Name, - value_result: Cell, Determinacy>>, - type_result: Cell, Determinacy>>, + result: PerNS, Determinacy>>>, }, GlobImport { is_prelude: bool, @@ -50,17 +49,6 @@ pub enum ImportDirectiveSubclass<'a> { ExternCrate, } -impl<'a> ImportDirectiveSubclass<'a> { - pub fn single(target: Name, source: Name) -> Self { - SingleImport { - target: target, - source: source, - type_result: Cell::new(Err(Undetermined)), - value_result: Cell::new(Err(Undetermined)), - } - } -} - /// One import directive. #[derive(Debug,Clone)] pub struct ImportDirective<'a> { @@ -276,10 +264,10 @@ impl<'a> Resolver<'a> { self.indeterminate_imports.push(directive); match directive.subclass { SingleImport { target, .. } => { - for &ns in &[ValueNS, TypeNS] { - let mut resolution = self.resolution(current_module, target, ns).borrow_mut(); + self.per_ns(|this, ns| { + let mut resolution = this.resolution(current_module, target, ns).borrow_mut(); resolution.single_imports.add_directive(directive); - } + }); } // We don't add prelude imports to the globs since they only affect lexical scopes, // which are not relevant to import resolution. @@ -397,6 +385,18 @@ impl<'a> Resolver<'a> { t } + + // Define a "dummy" resolution containing a Def::Err as a placeholder for a + // failed resolution + fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) { + if let SingleImport { target, .. } = directive.subclass { + let dummy_binding = self.dummy_binding; + let dummy_binding = self.import(dummy_binding, directive); + self.per_ns(|this, ns| { + let _ = this.try_define(directive.parent, target, ns, dummy_binding.clone()); + }); + } + } } pub struct ImportResolver<'a, 'b: 'a> { @@ -481,17 +481,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } - // Define a "dummy" resolution containing a Def::Err as a placeholder for a - // failed resolution - fn import_dummy_binding(&mut self, directive: &'b ImportDirective<'b>) { - if let SingleImport { target, .. } = directive.subclass { - let dummy_binding = self.dummy_binding; - let dummy_binding = self.import(dummy_binding, directive); - let _ = self.try_define(directive.parent, target, ValueNS, dummy_binding.clone()); - let _ = self.try_define(directive.parent, target, TypeNS, dummy_binding); - } - } - /// Attempts to resolve the given import. The return value indicates /// failure if we're certain the name does not exist, indeterminate if we /// don't know whether the name exists at the moment due to other @@ -523,9 +512,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { }; directive.imported_module.set(Some(module)); - let (source, target, value_result, type_result) = match directive.subclass { - SingleImport { source, target, ref value_result, ref type_result } => - (source, target, value_result, type_result), + let (source, target, result) = match directive.subclass { + SingleImport { source, target, ref result } => (source, target, result), GlobImport { .. } => { self.resolve_glob_import(directive); return Success(()); @@ -534,46 +522,45 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { }; let mut indeterminate = false; - for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] { - if let Err(Undetermined) = result.get() { - result.set({ - match self.resolve_name_in_module(module, source, ns, false, None) { + self.per_ns(|this, ns| { + if let Err(Undetermined) = result[ns].get() { + result[ns].set({ + match this.resolve_name_in_module(module, source, ns, false, None) { Success(binding) => Ok(binding), Indeterminate => Err(Undetermined), Failed(_) => Err(Determined), } }); } else { - continue + return }; - match result.get() { + match result[ns].get() { Err(Undetermined) => indeterminate = true, Err(Determined) => { - self.update_resolution(directive.parent, target, ns, |_, resolution| { + this.update_resolution(directive.parent, target, ns, |_, resolution| { resolution.single_imports.directive_failed() }); } Ok(binding) if !binding.is_importable() => { let msg = format!("`{}` is not directly importable", target); - struct_span_err!(self.session, directive.span, E0253, "{}", &msg) + struct_span_err!(this.session, directive.span, E0253, "{}", &msg) .span_label(directive.span, &format!("cannot be imported directly")) .emit(); // Do not import this illegal binding. Import a dummy binding and pretend // everything is fine - self.import_dummy_binding(directive); - return Success(()); + this.import_dummy_binding(directive); } Ok(binding) => { - let imported_binding = self.import(binding, directive); - let conflict = self.try_define(directive.parent, target, ns, imported_binding); + let imported_binding = this.import(binding, directive); + let conflict = this.try_define(directive.parent, target, ns, imported_binding); if let Err(old_binding) = conflict { - let binding = &self.import(binding, directive); - self.report_conflict(directive.parent, target, ns, binding, old_binding); + let binding = &this.import(binding, directive); + this.report_conflict(directive.parent, target, ns, binding, old_binding); } } } - } + }); if indeterminate { Indeterminate } else { Success(()) } } @@ -601,9 +588,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { }, }; - let (name, value_result, type_result) = match directive.subclass { - SingleImport { source, ref value_result, ref type_result, .. } => - (source, value_result.get(), type_result.get()), + let (name, result) = match directive.subclass { + SingleImport { source, ref result, .. } => (source, result), GlobImport { .. } if module.def_id() == directive.parent.def_id() => { // Importing a module into itself is not allowed. let msg = "Cannot glob-import a module into itself.".into(); @@ -621,21 +607,27 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { _ => unreachable!(), }; - for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] { - if let Ok(binding) = result { - if self.record_use(name, ns, binding, directive.span) { - self.resolution(module, name, ns).borrow_mut().binding = - Some(self.dummy_binding); + let mut all_ns_err = true; + self.per_ns(|this, ns| { + if let Ok(binding) = result[ns].get() { + all_ns_err = false; + if this.record_use(name, ns, binding, directive.span) { + this.resolution(module, name, ns).borrow_mut().binding = + Some(this.dummy_binding); } } - } + }); - if value_result.is_err() && type_result.is_err() { - let (value_result, type_result); - value_result = self.resolve_name_in_module(module, name, ValueNS, false, Some(span)); - type_result = self.resolve_name_in_module(module, name, TypeNS, false, Some(span)); + if all_ns_err { + let mut all_ns_failed = true; + self.per_ns(|this, ns| { + match this.resolve_name_in_module(module, name, ns, false, Some(span)) { + Success(_) => all_ns_failed = false, + _ => {} + } + }); - return if let (Failed(_), Failed(_)) = (value_result, type_result) { + return if all_ns_failed { let resolutions = module.resolutions.borrow(); let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| { if *n == name { return None; } // Never suggest the same name @@ -663,64 +655,49 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } - let session = self.session; - let reexport_error = || { - let msg = format!("`{}` is private, and cannot be reexported", name); - let note_msg = - format!("consider marking `{}` as `pub` in the imported module", name); - struct_span_err!(session, directive.span, E0364, "{}", &msg) - .span_note(directive.span, ¬e_msg) - .emit(); - }; - - let extern_crate_lint = || { - let msg = format!("extern crate `{}` is private, and cannot be reexported \ - (error E0364), consider declaring with `pub`", - name); - session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg); - }; - - match (value_result, type_result) { - // All namespaces must be re-exported with extra visibility for an error to occur. - (Ok(value_binding), Ok(type_binding)) => { + let mut reexport_error = None; + let mut any_successful_reexport = false; + self.per_ns(|this, ns| { + if let Ok(binding) = result[ns].get() { let vis = directive.vis.get(); - if !value_binding.pseudo_vis().is_at_least(vis, self) && - !type_binding.pseudo_vis().is_at_least(vis, self) { - reexport_error(); - } else if type_binding.is_extern_crate() && - !type_binding.vis.is_at_least(vis, self) { - extern_crate_lint(); - } - } - - (Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => { - reexport_error(); - } - - (_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => { - if binding.is_extern_crate() { - extern_crate_lint(); + if !binding.pseudo_vis().is_at_least(vis, this) { + reexport_error = Some((ns, binding)); } else { - struct_span_err!(self.session, directive.span, E0365, - "`{}` is private, and cannot be reexported", name) - .span_label(directive.span, &format!("reexport of private `{}`", name)) - .note(&format!("consider declaring type or module `{}` with `pub`", name)) - .emit(); + any_successful_reexport = true; } } + }); - _ => {} + // All namespaces must be re-exported with extra visibility for an error to occur. + if !any_successful_reexport { + let (ns, binding) = reexport_error.unwrap(); + if ns == TypeNS && binding.is_extern_crate() { + let msg = format!("extern crate `{}` is private, and cannot be reexported \ + (error E0364), consider declaring with `pub`", + name); + self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg); + } else if ns == TypeNS { + struct_span_err!(self.session, directive.span, E0365, + "`{}` is private, and cannot be reexported", name) + .span_label(directive.span, &format!("reexport of private `{}`", name)) + .note(&format!("consider declaring type or module `{}` with `pub`", name)) + .emit(); + } else { + let msg = format!("`{}` is private, and cannot be reexported", name); + let note_msg = + format!("consider marking `{}` as `pub` in the imported module", name); + struct_span_err!(self.session, directive.span, E0364, "{}", &msg) + .span_note(directive.span, ¬e_msg) + .emit(); + } } // Record what this import resolves to for later uses in documentation, // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. - let def = match type_result.ok().map(NameBinding::def) { - Some(def) => def, - None => value_result.ok().map(NameBinding::def).unwrap(), - }; - let path_resolution = PathResolution::new(def); - self.def_map.insert(directive.id, path_resolution); + self.per_ns(|this, ns| if let Some(binding) = result[ns].get().ok() { + this.def_map.entry(directive.id).or_insert(PathResolution::new(binding.def())); + }); debug!("(resolving single import) successfully resolved import"); return Success(()); diff --git a/src/test/compile-fail/blind-item-block-item-shadow.rs b/src/test/compile-fail/blind-item-block-item-shadow.rs index a26b9e3c7aa2a..2d53aee39e95d 100644 --- a/src/test/compile-fail/blind-item-block-item-shadow.rs +++ b/src/test/compile-fail/blind-item-block-item-shadow.rs @@ -14,6 +14,6 @@ fn main() { { struct Bar; use foo::Bar; - //~^ ERROR a value named `Bar` has already been defined in this block + //~^ ERROR a type named `Bar` has already been defined in this block } } diff --git a/src/test/compile-fail/double-type-import.rs b/src/test/compile-fail/double-type-import.rs index e51ef5e32e81c..760612c05ce49 100644 --- a/src/test/compile-fail/double-type-import.rs +++ b/src/test/compile-fail/double-type-import.rs @@ -11,7 +11,7 @@ mod foo { pub use self::bar::X; use self::bar::X; - //~^ ERROR a value named `X` has already been imported in this module + //~^ ERROR a type named `X` has already been imported in this module mod bar { pub struct X; From 9c886500801fe7cbdc4c9a7dfd2294df8b10db8b Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 10 Nov 2016 10:29:36 +0000 Subject: [PATCH 6/8] Add feature `use_extern_macros`. --- src/librustc_resolve/build_reduced_graph.rs | 12 +- src/librustc_resolve/lib.rs | 80 ++++++----- src/librustc_resolve/macros.rs | 150 ++++++++++++++++---- src/librustc_resolve/resolve_imports.rs | 125 ++++++++-------- src/libsyntax/feature_gate.rs | 2 + src/test/compile-fail/imports/duplicate.rs | 4 +- 6 files changed, 238 insertions(+), 135 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 5917a1a0d1759..6816789cf2846 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -504,9 +504,11 @@ impl<'b> Resolver<'b> { }) } - pub fn get_macro(&mut self, def: Def) -> Rc { - let def_id = match def { - Def::Macro(def_id) => def_id, + pub fn get_macro(&mut self, binding: &'b NameBinding<'b>) -> Rc { + let def_id = match binding.kind { + NameBindingKind::Def(Def::Macro(def_id)) => def_id, + NameBindingKind::Import { binding, .. } => return self.get_macro(binding), + NameBindingKind::Ambiguity { b1, .. } => return self.get_macro(b1), _ => panic!("Expected Def::Macro(..)"), }; if let Some(ext) = self.macro_map.get(&def_id) { @@ -579,7 +581,7 @@ impl<'b> Resolver<'b> { }); } else { for (name, span) in legacy_imports.imports { - let result = self.resolve_name_in_module(module, name, MacroNS, false, None); + let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None); if let Success(binding) = result { self.legacy_import_macro(name, binding, span, allow_shadowing); } else { @@ -589,7 +591,7 @@ impl<'b> Resolver<'b> { } for (name, span) in legacy_imports.reexports { self.used_crates.insert(module.def_id().unwrap().krate); - let result = self.resolve_name_in_module(module, name, MacroNS, false, None); + let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None); if let Success(binding) = result { self.macro_exports.push(Export { name: name, def: binding.def() }); } else { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index af72977024253..a3a60e4f6d754 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -540,6 +540,7 @@ pub enum Namespace { pub struct PerNS { value_ns: T, type_ns: T, + macro_ns: Option, } impl ::std::ops::Index for PerNS { @@ -548,7 +549,7 @@ impl ::std::ops::Index for PerNS { match ns { ValueNS => &self.value_ns, TypeNS => &self.type_ns, - MacroNS => unreachable!(), + MacroNS => self.macro_ns.as_ref().unwrap(), } } } @@ -558,7 +559,7 @@ impl ::std::ops::IndexMut for PerNS { match ns { ValueNS => &mut self.value_ns, TypeNS => &mut self.type_ns, - MacroNS => unreachable!(), + MacroNS => self.macro_ns.as_mut().unwrap(), } } } @@ -675,7 +676,7 @@ impl<'a> Visitor for Resolver<'a> { pub type ErrorMessage = Option<(Span, String)>; -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, Debug)] pub enum ResolveResult { Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message. Indeterminate, // Couldn't determine due to unresolved globs. @@ -683,14 +684,6 @@ pub enum ResolveResult { } impl ResolveResult { - fn and_then ResolveResult>(self, f: F) -> ResolveResult { - match self { - Failed(msg) => Failed(msg), - Indeterminate => Indeterminate, - Success(t) => f(t), - } - } - fn success(self) -> Option { match self { Success(t) => Some(t), @@ -825,6 +818,7 @@ pub struct ModuleS<'a> { normal_ancestor_id: Option, resolutions: RefCell>>>, + legacy_macro_resolutions: RefCell>, // Macro invocations that can expand into items in this module. unresolved_invocations: RefCell>, @@ -852,6 +846,7 @@ impl<'a> ModuleS<'a> { kind: kind, normal_ancestor_id: None, resolutions: RefCell::new(FxHashMap()), + legacy_macro_resolutions: RefCell::new(Vec::new()), unresolved_invocations: RefCell::new(FxHashSet()), no_implicit_prelude: false, glob_importers: RefCell::new(Vec::new()), @@ -943,6 +938,7 @@ struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>); struct AmbiguityError<'a> { span: Span, name: Name, + lexical: bool, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>, } @@ -1001,7 +997,7 @@ impl<'a> NameBinding<'a> { fn is_glob_import(&self) -> bool { match self.kind { NameBindingKind::Import { directive, .. } => directive.is_glob(), - NameBindingKind::Ambiguity { .. } => true, + NameBindingKind::Ambiguity { b1, .. } => b1.is_glob_import(), _ => false, } } @@ -1136,6 +1132,7 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, new_import_semantics: bool, // true if `#![feature(item_like_imports)]` + use_extern_macros: bool, // true if `#![feature(use_extern_macros)]` pub exported_macros: Vec, crate_loader: &'a mut CrateLoader, @@ -1300,6 +1297,7 @@ impl<'a> Resolver<'a> { ribs: PerNS { value_ns: vec![Rib::new(ModuleRibKind(graph_root))], type_ns: vec![Rib::new(ModuleRibKind(graph_root))], + macro_ns: None, }, label_ribs: Vec::new(), @@ -1336,6 +1334,7 @@ impl<'a> Resolver<'a> { vis: ty::Visibility::Public, }), new_import_semantics: session.features.borrow().item_like_imports, + use_extern_macros: session.features.borrow().use_extern_macros, exported_macros: Vec::new(), crate_loader: crate_loader, @@ -1365,6 +1364,10 @@ impl<'a> Resolver<'a> { PerNS { type_ns: f(self, TypeNS), value_ns: f(self, ValueNS), + macro_ns: match self.use_extern_macros { + true => Some(f(self, MacroNS)), + false => None, + }, } } @@ -1403,8 +1406,9 @@ impl<'a> Resolver<'a> { } NameBindingKind::Import { .. } => false, NameBindingKind::Ambiguity { b1, b2 } => { - let ambiguity_error = AmbiguityError { span: span, name: name, b1: b1, b2: b2 }; - self.ambiguity_errors.push(ambiguity_error); + self.ambiguity_errors.push(AmbiguityError { + span: span, name: name, lexical: false, b1: b1, b2: b2, + }); true } _ => false @@ -1438,7 +1442,7 @@ impl<'a> Resolver<'a> { -> ResolveResult> { fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>) -> Option> { - match this.resolve_name_in_module(module, needle, TypeNS, false, None) { + match this.resolve_name_in_module(module, needle, TypeNS, false, false, None) { Success(binding) if binding.is_extern_crate() => Some(module), _ => if let (&ModuleKind::Def(..), Some(parent)) = (&module.kind, module.parent) { search_parent_externals(this, needle, parent) @@ -1456,7 +1460,7 @@ impl<'a> Resolver<'a> { // modules as we go. while index < module_path_len { let name = module_path[index].name; - match self.resolve_name_in_module(search_module, name, TypeNS, false, span) { + match self.resolve_name_in_module(search_module, name, TypeNS, false, false, span) { Failed(_) => { let segment_name = name.as_str(); let module_name = module_to_string(search_module); @@ -1613,7 +1617,7 @@ impl<'a> Resolver<'a> { if let ModuleRibKind(module) = self.ribs[ns][i].kind { let name = ident.name; - let item = self.resolve_name_in_module(module, name, ns, true, record_used); + let item = self.resolve_name_in_module(module, name, ns, true, false, record_used); if let Success(binding) = item { // The ident resolves to an item. return Some(LexicalScopeBinding::Item(binding)); @@ -1622,7 +1626,7 @@ impl<'a> Resolver<'a> { if let ModuleKind::Block(..) = module.kind { // We can see through blocks } else if !module.no_implicit_prelude { return self.prelude.and_then(|prelude| { - self.resolve_name_in_module(prelude, name, ns, false, None).success() + self.resolve_name_in_module(prelude, name, ns, false, false, None).success() }).map(LexicalScopeBinding::Item) } else { return None; @@ -1717,6 +1721,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(); f(self); self.current_module = orig_module; @@ -2221,6 +2226,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(); } else { self.ribs[ValueNS].push(Rib::new(NormalRibKind)); } @@ -2754,8 +2760,7 @@ impl<'a> Resolver<'a> { let module_path = segments.split_last().unwrap().1.iter().map(|ps| ps.identifier).collect::>(); - let containing_module; - match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) { + let module = match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) { Failed(err) => { if let Some((span, msg)) = err { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); @@ -2763,14 +2768,11 @@ impl<'a> Resolver<'a> { return Err(true); } Indeterminate => return Err(false), - Success(resulting_module) => { - containing_module = resulting_module; - } - } + Success(module) => module, + }; let name = segments.last().unwrap().identifier.name; - let result = - self.resolve_name_in_module(containing_module, name, namespace, false, Some(span)); + let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span)); result.success().ok_or(false) } @@ -2782,10 +2784,9 @@ impl<'a> Resolver<'a> { where T: Named, { let module_path = segments.split_last().unwrap().1.iter().map(T::ident).collect::>(); - let root_module = self.graph_root; + let root = self.graph_root; - let containing_module; - match self.resolve_module_path_from_root(root_module, &module_path, 0, Some(span)) { + let module = match self.resolve_module_path_from_root(root, &module_path, 0, Some(span)) { Failed(err) => { if let Some((span, msg)) = err { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); @@ -2795,14 +2796,11 @@ impl<'a> Resolver<'a> { Indeterminate => return Err(false), - Success(resulting_module) => { - containing_module = resulting_module; - } - } + Success(module) => module, + }; let name = segments.last().unwrap().ident().name; - let result = - self.resolve_name_in_module(containing_module, name, namespace, false, Some(span)); + let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span)); result.success().ok_or(false) } @@ -3383,14 +3381,18 @@ impl<'a> Resolver<'a> { self.report_shadowing_errors(); let mut reported_spans = FxHashSet(); - for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors { + for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors { if !reported_spans.insert(span) { continue } let msg1 = format!("`{}` could resolve to the name imported here", name); let msg2 = format!("`{}` could also resolve to the name imported here", name); self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)) .span_note(b1.span, &msg1) .span_note(b2.span, &msg2) - .note(&format!("Consider adding an explicit import of `{}` to disambiguate", name)) + .note(&if lexical || !b1.is_glob_import() { + "macro-expanded macro imports do not shadow".to_owned() + } else { + format!("consider adding an explicit import of `{}` to disambiguate", name) + }) .emit(); } @@ -3413,12 +3415,12 @@ impl<'a> Resolver<'a> { fn report_shadowing_errors(&mut self) { for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { - self.resolve_macro_name(scope, name); + self.resolve_legacy_scope(scope, name, true); } let mut reported_errors = FxHashSet(); for binding in replace(&mut self.disallowed_shadowing, Vec::new()) { - if self.resolve_macro_name(binding.parent, binding.name).is_some() && + if self.resolve_legacy_scope(binding.parent, binding.name, false).is_some() && reported_errors.insert((binding.name, binding.span)) { let msg = format!("`{}` is already in scope", binding.name); self.session.struct_span_err(binding.span, &msg) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 2d434d660ea5a..56d76272e235a 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {Module, ModuleKind, NameBinding, NameBindingKind, Resolver}; +use {Module, ModuleKind, NameBinding, NameBindingKind, Resolver, AmbiguityError}; +use Namespace::{self, MacroNS}; +use ResolveResult::{Success, Indeterminate, Failed}; use build_reduced_graph::BuildReducedGraphVisitor; use resolve_imports::ImportResolver; use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}; @@ -17,7 +19,7 @@ use rustc::hir::map::{self, DefCollector}; use rustc::ty; use std::cell::Cell; use std::rc::Rc; -use syntax::ast; +use syntax::ast::{self, Name}; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{NormalTT, SyntaxExtension}; @@ -85,6 +87,11 @@ pub struct LegacyBinding<'a> { pub span: Span, } +pub enum MacroBinding<'a> { + Legacy(&'a LegacyBinding<'a>), + Modern(&'a NameBinding<'a>), +} + impl<'a> base::Resolver for Resolver<'a> { fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() @@ -140,6 +147,7 @@ impl<'a> base::Resolver for Resolver<'a> { expansion: mark, }; expansion.visit_with(&mut visitor); + self.current_module.unresolved_invocations.borrow_mut().remove(&mark); invocation.expansion.set(visitor.legacy_scope); } @@ -201,7 +209,7 @@ impl<'a> base::Resolver for Resolver<'a> { for i in 0..attrs.len() { let name = intern(&attrs[i].name()); match self.builtin_macros.get(&name).cloned() { - Some(binding) => match *self.get_macro(binding.def()) { + Some(binding) => match *self.get_macro(binding) { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { return Some(attrs.remove(i)) } @@ -225,25 +233,77 @@ impl<'a> base::Resolver for Resolver<'a> { if let LegacyScope::Expansion(parent) = invocation.legacy_scope.get() { invocation.legacy_scope.set(LegacyScope::simplify_expansion(parent)); } - self.resolve_macro_name(invocation.legacy_scope.get(), name).ok_or_else(|| { - if force { - let msg = format!("macro undefined: '{}!'", name); - let mut err = self.session.struct_span_err(path.span, &msg); - self.suggest_macro_name(&name.as_str(), &mut err); - err.emit(); - Determinacy::Determined - } else { - Determinacy::Undetermined - } - }) + + self.current_module = invocation.module.get(); + let result = match self.resolve_legacy_scope(invocation.legacy_scope.get(), name, false) { + Some(MacroBinding::Legacy(binding)) => Ok(binding.ext.clone()), + Some(MacroBinding::Modern(binding)) => Ok(self.get_macro(binding)), + None => match self.resolve_in_item_lexical_scope(name, MacroNS, None) { + Some(binding) => Ok(self.get_macro(binding)), + None => return Err(if force { + let msg = format!("macro undefined: '{}!'", name); + let mut err = self.session.struct_span_err(path.span, &msg); + self.suggest_macro_name(&name.as_str(), &mut err); + err.emit(); + Determinacy::Determined + } else { + Determinacy::Undetermined + }), + }, + }; + + if self.use_extern_macros { + self.current_module.legacy_macro_resolutions.borrow_mut() + .push((scope, name, path.span)); + } + result } } impl<'a> Resolver<'a> { - pub fn resolve_macro_name(&mut self, mut scope: LegacyScope<'a>, name: ast::Name) - -> Option> { + // Resolve the name in the module's lexical scope, excluding non-items. + fn resolve_in_item_lexical_scope( + &mut self, name: Name, ns: Namespace, record_used: Option, + ) -> Option<&'a NameBinding<'a>> { + let mut module = self.current_module; + let mut potential_expanded_shadower = None; + loop { + // Since expanded macros may not shadow the lexical scope (enforced below), + // we can ignore unresolved invocations (indicated by the penultimate argument). + match self.resolve_name_in_module(module, name, ns, true, true, record_used) { + Success(binding) => { + let span = match record_used { + Some(span) => span, + None => return Some(binding), + }; + if let Some(shadower) = potential_expanded_shadower { + self.ambiguity_errors.push(AmbiguityError { + span: span, name: name, b1: shadower, b2: binding, lexical: true, + }); + return Some(shadower); + } else if binding.expansion == Mark::root() { + return Some(binding); + } else { + potential_expanded_shadower = Some(binding); + } + }, + Indeterminate => return None, + Failed(..) => {} + } + + match module.kind { + ModuleKind::Block(..) => module = module.parent.unwrap(), + ModuleKind::Def(..) => return potential_expanded_shadower, + } + } + } + + pub fn resolve_legacy_scope( + &mut self, mut scope: LegacyScope<'a>, name: ast::Name, record_used: bool, + ) -> Option> { let mut possible_time_travel = None; let mut relative_depth: u32 = 0; + let mut binding = None; loop { scope = match scope { LegacyScope::Empty => break, @@ -262,25 +322,59 @@ impl<'a> Resolver<'a> { relative_depth = relative_depth.saturating_sub(1); invocation.legacy_scope.get() } - LegacyScope::Binding(binding) => { - if binding.name == name { - if let Some(scope) = possible_time_travel { - // Check for disallowed shadowing later - self.lexical_macro_resolutions.push((name, scope)); - } else if relative_depth > 0 { - self.disallowed_shadowing.push(binding); + LegacyScope::Binding(potential_binding) => { + if potential_binding.name == name { + if (!self.use_extern_macros || record_used) && relative_depth > 0 { + self.disallowed_shadowing.push(potential_binding); } - return Some(binding.ext.clone()); + binding = Some(potential_binding); + break } - binding.parent + potential_binding.parent } }; } - if let Some(scope) = possible_time_travel { - self.lexical_macro_resolutions.push((name, scope)); + let binding = match binding { + Some(binding) => MacroBinding::Legacy(binding), + None => match self.builtin_macros.get(&name).cloned() { + Some(binding) => MacroBinding::Modern(binding), + None => return None, + }, + }; + + if !self.use_extern_macros { + if let Some(scope) = possible_time_travel { + // Check for disallowed shadowing later + self.lexical_macro_resolutions.push((name, scope)); + } + } + + Some(binding) + } + + pub fn finalize_current_module_macro_resolutions(&mut self) { + let module = self.current_module; + for &(mark, name, span) in module.legacy_macro_resolutions.borrow().iter() { + let legacy_scope = self.invocations[&mark].legacy_scope.get(); + let legacy_resolution = self.resolve_legacy_scope(legacy_scope, name, true); + let resolution = self.resolve_in_item_lexical_scope(name, MacroNS, Some(span)); + let (legacy_resolution, resolution) = match (legacy_resolution, resolution) { + (Some(legacy_resolution), Some(resolution)) => (legacy_resolution, resolution), + _ => continue, + }; + let (legacy_span, participle) = match legacy_resolution { + MacroBinding::Modern(binding) if binding.def() == resolution.def() => continue, + MacroBinding::Modern(binding) => (binding.span, "imported"), + MacroBinding::Legacy(binding) => (binding.span, "defined"), + }; + let msg1 = format!("`{}` could resolve to the macro {} here", name, participle); + let msg2 = format!("`{}` could also resolve to the macro imported here", name); + self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)) + .span_note(legacy_span, &msg1) + .span_note(resolution.span, &msg2) + .emit(); } - self.builtin_macros.get(&name).cloned().map(|binding| self.get_macro(binding.def())) } fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index f04f3bf45ee93..d0ce1acaadf62 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -11,7 +11,7 @@ use self::ImportDirectiveSubclass::*; use {Module, PerNS}; -use Namespace::{self, TypeNS}; +use Namespace::{self, TypeNS, MacroNS}; use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding}; use ResolveResult; use ResolveResult::*; @@ -142,6 +142,7 @@ impl<'a> Resolver<'a> { name: Name, ns: Namespace, allow_private_imports: bool, + ignore_unresolved_invocations: bool, record_used: Option) -> ResolveResult<&'a NameBinding<'a>> { self.populate_module_if_necessary(module); @@ -175,70 +176,65 @@ impl<'a> Resolver<'a> { return resolution.binding.map(Success).unwrap_or(Failed(None)); } - // If the resolution doesn't depend on glob definability, check privacy and return. - if let Some(result) = self.try_result(&resolution, module, ns) { - return result.and_then(|binding| { - if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) || - binding.is_extern_crate() { // c.f. issue #37020 - Success(binding) - } else { - Failed(None) - } - }); - } + let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { + let usable = + this.is_accessible(binding.vis) && !is_disallowed_private_import(binding) || + binding.is_extern_crate(); // c.f. issue #37020 + if usable { Success(binding) } else { Failed(None) } + }; - // Check if the globs are determined - for directive in module.globs.borrow().iter() { - if self.is_accessible(directive.vis.get()) { - if let Some(module) = directive.imported_module.get() { - let result = self.resolve_name_in_module(module, name, ns, true, None); - if let Indeterminate = result { - return Indeterminate; - } - } else { - return Indeterminate; - } + // Items and single imports are not shadowable. + if let Some(binding) = resolution.binding { + if !binding.is_glob_import() { + return check_usable(self, binding); } } - Failed(None) - } - - // Returns Some(the resolution of the name), or None if the resolution depends - // on whether more globs can define the name. - fn try_result(&mut self, resolution: &NameResolution<'a>, module: Module<'a>, ns: Namespace) - -> Option>> { - match resolution.binding { - Some(binding) if !binding.is_glob_import() => - return Some(Success(binding)), // Items and single imports are not shadowable. - _ => {} - }; - // Check if a single import can still define the name. match resolution.single_imports { - SingleImports::AtLeastOne => return Some(Indeterminate), + SingleImports::AtLeastOne => return Indeterminate, SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => { let module = match directive.imported_module.get() { Some(module) => module, - None => return Some(Indeterminate), + None => return Indeterminate, }; let name = match directive.subclass { SingleImport { source, .. } => source, _ => unreachable!(), }; - match self.resolve_name_in_module(module, name, ns, true, None) { + match self.resolve_name_in_module(module, name, ns, true, false, None) { Failed(_) => {} - _ => return Some(Indeterminate), + _ => return Indeterminate, } } SingleImports::MaybeOne(_) | SingleImports::None => {}, } - if !module.unresolved_invocations.borrow().is_empty() { - return Some(Indeterminate); + let no_unresolved_invocations = + ignore_unresolved_invocations || module.unresolved_invocations.borrow().is_empty(); + match resolution.binding { + // In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`). + Some(binding) if no_unresolved_invocations || ns == MacroNS => + return check_usable(self, binding), + None if no_unresolved_invocations => {} + _ => return Indeterminate, } - resolution.binding.map(Success) + // Check if the globs are determined + for directive in module.globs.borrow().iter() { + if self.is_accessible(directive.vis.get()) { + if let Some(module) = directive.imported_module.get() { + let result = self.resolve_name_in_module(module, name, ns, true, false, None); + if let Indeterminate = result { + return Indeterminate; + } + } else { + return Indeterminate; + } + } + } + + Failed(None) } // Add an import directive to the current module. @@ -315,29 +311,26 @@ impl<'a> Resolver<'a> { self.update_resolution(module, name, ns, |this, resolution| { if let Some(old_binding) = resolution.binding { if binding.is_glob_import() { - if !this.new_import_semantics || !old_binding.is_glob_import() { + if !this.new_import_semantics { resolution.duplicate_globs.push(binding); + } else if !old_binding.is_glob_import() && + !(ns == MacroNS && old_binding.expansion != Mark::root()) { } else if binding.def() != old_binding.def() { - resolution.binding = Some(this.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Ambiguity { - b1: old_binding, - b2: binding, - }, - vis: if old_binding.vis.is_at_least(binding.vis, this) { - old_binding.vis - } else { - binding.vis - }, - span: old_binding.span, - expansion: Mark::root(), - })); + resolution.binding = Some(this.ambiguity(old_binding, binding)); } else if !old_binding.vis.is_at_least(binding.vis, this) { // We are glob-importing the same item but with greater visibility. resolution.binding = Some(binding); } } else if old_binding.is_glob_import() { - resolution.duplicate_globs.push(old_binding); - resolution.binding = Some(binding); + if !this.new_import_semantics { + resolution.duplicate_globs.push(old_binding); + resolution.binding = Some(binding); + } else if ns == MacroNS && binding.expansion != Mark::root() && + binding.def() != old_binding.def() { + resolution.binding = Some(this.ambiguity(binding, old_binding)); + } else { + resolution.binding = Some(binding); + } } else { return Err(old_binding); } @@ -349,6 +342,16 @@ impl<'a> Resolver<'a> { }) } + pub fn ambiguity(&mut self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>) + -> &'a NameBinding<'a> { + self.arenas.alloc_name_binding(NameBinding { + kind: NameBindingKind::Ambiguity { b1: b1, b2: b2 }, + vis: if b1.vis.is_at_least(b2.vis, self) { b1.vis } else { b2.vis }, + span: b1.span, + expansion: Mark::root(), + }) + } + // Use `f` to mutate the resolution of the name in the module. // If the resolution becomes a success, define it in the module's glob importers. fn update_resolution(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T @@ -525,7 +528,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { self.per_ns(|this, ns| { if let Err(Undetermined) = result[ns].get() { result[ns].set({ - match this.resolve_name_in_module(module, source, ns, false, None) { + match this.resolve_name_in_module(module, source, ns, false, false, None) { Success(binding) => Ok(binding), Indeterminate => Err(Undetermined), Failed(_) => Err(Determined), @@ -621,7 +624,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if all_ns_err { let mut all_ns_failed = true; self.per_ns(|this, ns| { - match this.resolve_name_in_module(module, name, ns, false, Some(span)) { + match this.resolve_name_in_module(module, name, ns, false, false, Some(span)) { Success(_) => all_ns_failed = false, _ => {} } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 27f720b760998..ea66fdc31cf08 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -314,6 +314,8 @@ declare_features! ( // Allows #[link(..., cfg(..))] (active, link_cfg, "1.14.0", Some(37406)), + + (active, use_extern_macros, "1.15.0", Some(35896)), ); declare_features! ( diff --git a/src/test/compile-fail/imports/duplicate.rs b/src/test/compile-fail/imports/duplicate.rs index fb61bb8e489be..faf85a523e8fb 100644 --- a/src/test/compile-fail/imports/duplicate.rs +++ b/src/test/compile-fail/imports/duplicate.rs @@ -46,9 +46,9 @@ mod g { fn main() { e::foo(); f::foo(); //~ ERROR `foo` is ambiguous - //~| NOTE Consider adding an explicit import of `foo` to disambiguate + //~| NOTE consider adding an explicit import of `foo` to disambiguate g::foo(); //~ ERROR `foo` is ambiguous - //~| NOTE Consider adding an explicit import of `foo` to disambiguate + //~| NOTE consider adding an explicit import of `foo` to disambiguate } mod ambiguous_module_errors { From d8722f3fe138804dc2cef4764405a17f0f759808 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 12 Nov 2016 09:38:12 +0000 Subject: [PATCH 7/8] Add tests. --- .../imports/auxiliary/two_macros.rs | 15 +++++ src/test/compile-fail/imports/macros.rs | 55 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/test/compile-fail/imports/auxiliary/two_macros.rs create mode 100644 src/test/compile-fail/imports/macros.rs diff --git a/src/test/compile-fail/imports/auxiliary/two_macros.rs b/src/test/compile-fail/imports/auxiliary/two_macros.rs new file mode 100644 index 0000000000000..2ac8e3ef983da --- /dev/null +++ b/src/test/compile-fail/imports/auxiliary/two_macros.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_export] +macro_rules! m { ($($t:tt)*) => { $($t)* } } + +#[macro_export] +macro_rules! n { ($($t:tt)*) => { $($t)* } } diff --git a/src/test/compile-fail/imports/macros.rs b/src/test/compile-fail/imports/macros.rs new file mode 100644 index 0000000000000..c11d2aab7c625 --- /dev/null +++ b/src/test/compile-fail/imports/macros.rs @@ -0,0 +1,55 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:two_macros.rs + +#![feature(item_like_imports, use_extern_macros)] + +extern crate two_macros; // two identity macros `m` and `n` + +mod foo { + pub use two_macros::n as m; +} + +mod m1 { + m!(use two_macros::*;); + use foo::m; // This shadows the glob import +} + +mod m2 { + use two_macros::*; //~ NOTE could also resolve + m! { //~ ERROR ambiguous + //~| NOTE macro-expanded macro imports do not shadow + use foo::m; //~ NOTE could resolve to the name imported here + //~^^^ NOTE in this expansion + } +} + +mod m3 { + use two_macros::m; //~ NOTE could also resolve + fn f() { + use two_macros::n as m; // This shadows the above import + m!(); + } + + fn g() { + m! { //~ ERROR ambiguous + //~| NOTE macro-expanded macro imports do not shadow + use two_macros::n as m; //~ NOTE could resolve to the name imported here + //~^^^ NOTE in this expansion + } + } +} + +mod m4 { + macro_rules! m { () => {} } //~ NOTE could resolve to the macro defined here + use two_macros::m; //~ NOTE could also resolve to the macro imported here + m!(); //~ ERROR ambiguous +} From 6cb33a089fc4727bc070899f57aab3be1b215785 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 17 Nov 2016 08:16:32 +0000 Subject: [PATCH 8/8] Cleanup formatting. --- src/librustc_resolve/build_reduced_graph.rs | 35 +++++++++++---------- src/librustc_resolve/macros.rs | 16 ++++++---- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 6816789cf2846..627c72ff8c925 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -362,9 +362,11 @@ impl<'b> Resolver<'b> { // Constructs the reduced graph for one variant. Variants exist in the // type and value namespaces. - fn build_reduced_graph_for_variant( - &mut self, variant: &Variant, parent: Module<'b>, vis: ty::Visibility, expansion: Mark, - ) { + fn build_reduced_graph_for_variant(&mut self, + variant: &Variant, + parent: Module<'b>, + vis: ty::Visibility, + expansion: Mark) { let name = variant.node.name.name; let def_id = self.definitions.local_def_id(variant.node.data.id()); @@ -381,22 +383,20 @@ impl<'b> Resolver<'b> { } /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item( - &mut self, foreign_item: &ForeignItem, expansion: Mark, - ) { + fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) { let parent = self.current_module; - let name = foreign_item.ident.name; + let name = item.ident.name; - let def = match foreign_item.node { + let def = match item.node { ForeignItemKind::Fn(..) => { - Def::Fn(self.definitions.local_def_id(foreign_item.id)) + Def::Fn(self.definitions.local_def_id(item.id)) } ForeignItemKind::Static(_, m) => { - Def::Static(self.definitions.local_def_id(foreign_item.id), m) + Def::Static(self.definitions.local_def_id(item.id), m) } }; - let vis = self.resolve_visibility(&foreign_item.vis); - self.define(parent, name, ValueNS, (def, vis, foreign_item.span, expansion)); + let vis = self.resolve_visibility(&item.vis); + self.define(parent, name, ValueNS, (def, vis, item.span, expansion)); } fn build_reduced_graph_for_block(&mut self, block: &Block) { @@ -415,8 +415,7 @@ impl<'b> Resolver<'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, - child: Export) { + fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: Export) { let name = child.name; let def = child.def; let def_id = def.def_id(); @@ -545,9 +544,11 @@ impl<'b> Resolver<'b> { module.populated.set(true) } - fn legacy_import_macro( - &mut self, name: Name, binding: &'b NameBinding<'b>, span: Span, allow_shadowing: bool, - ) { + fn legacy_import_macro(&mut self, + name: Name, + binding: &'b NameBinding<'b>, + span: Span, + allow_shadowing: bool) { self.used_crates.insert(binding.def().def_id().krate); self.macro_names.insert(name); if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 56d76272e235a..524d491a464e2 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -262,9 +262,11 @@ impl<'a> base::Resolver for Resolver<'a> { impl<'a> Resolver<'a> { // Resolve the name in the module's lexical scope, excluding non-items. - fn resolve_in_item_lexical_scope( - &mut self, name: Name, ns: Namespace, record_used: Option, - ) -> Option<&'a NameBinding<'a>> { + fn resolve_in_item_lexical_scope(&mut self, + name: Name, + ns: Namespace, + record_used: Option) + -> Option<&'a NameBinding<'a>> { let mut module = self.current_module; let mut potential_expanded_shadower = None; loop { @@ -298,9 +300,11 @@ impl<'a> Resolver<'a> { } } - pub fn resolve_legacy_scope( - &mut self, mut scope: LegacyScope<'a>, name: ast::Name, record_used: bool, - ) -> Option> { + pub fn resolve_legacy_scope(&mut self, + mut scope: LegacyScope<'a>, + name: Name, + record_used: bool) + -> Option> { let mut possible_time_travel = None; let mut relative_depth: u32 = 0; let mut binding = None;