diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 63f643d7a2964..21c0f13baa4a9 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -833,7 +833,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { binding: &'a NameBinding<'a>, span: Span, allow_shadowing: bool) { - if self.macro_prelude.insert(name, binding).is_some() && !allow_shadowing { + if self.macro_use_prelude.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)"; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5cb615554ee68..98fbcd1fb183b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1278,6 +1278,13 @@ impl<'a> NameBinding<'a> { } } + fn macro_kind(&self) -> Option { + match self.def_ignoring_ambiguity() { + Def::Macro(_, kind) => Some(kind), + _ => None, + } + } + fn descr(&self) -> &'static str { if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() } } @@ -1440,7 +1447,8 @@ pub struct Resolver<'a, 'b: 'a> { crate_loader: &'a mut CrateLoader<'b>, macro_names: FxHashSet, - macro_prelude: FxHashMap>, + builtin_macros: FxHashMap>, + macro_use_prelude: FxHashMap>, unshadowable_attrs: FxHashMap>, pub all_macros: FxHashMap, macro_map: FxHashMap>, @@ -1757,7 +1765,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { crate_loader, macro_names: FxHashSet(), - macro_prelude: FxHashMap(), + builtin_macros: FxHashMap(), + macro_use_prelude: FxHashMap(), unshadowable_attrs: FxHashMap(), all_macros: FxHashMap(), macro_map: FxHashMap(), @@ -3340,10 +3349,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { }; } } - let is_global = self.macro_prelude.get(&path[0].name).cloned() - .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false); - if primary_ns != MacroNS && (is_global || - self.macro_names.contains(&path[0].modern())) { + if primary_ns != MacroNS && + (self.macro_names.contains(&path[0].modern()) || + self.builtin_macros.get(&path[0].name).cloned() + .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) || + self.macro_use_prelude.get(&path[0].name).cloned() + .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) { // Return some dummy definition, it's enough for error reporting. return Some( PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang)) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 93874ee0e85d5..b4c772cb8c63f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -214,7 +214,10 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { vis: ty::Visibility::Invisible, expansion: Mark::root(), }); - self.macro_prelude.insert(ident.name, binding); + if self.builtin_macros.insert(ident.name, binding).is_some() { + self.session.span_err(ident.span, + &format!("built-in macro `{}` was already defined", ident)); + } } fn add_unshadowable_attr(&mut self, ident: ast::Ident, ext: Lrc) { @@ -249,7 +252,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { attr::mark_known(&attrs[i]); } - match self.macro_prelude.get(&name).cloned() { + match self.builtin_macros.get(&name).cloned() { Some(binding) => match *binding.get_macro(self) { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { return Some(attrs.remove(i)) @@ -285,7 +288,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { } let trait_name = traits[j].segments[0].ident.name; let legacy_name = Symbol::intern(&format!("derive_{}", trait_name)); - if !self.macro_prelude.contains_key(&legacy_name) { + if !self.builtin_macros.contains_key(&legacy_name) { continue } let span = traits.remove(j).span; @@ -585,14 +588,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // (Macro NS) // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents // (open, not controlled). - // 2. Macro prelude (language, standard library, user-defined legacy plugins lumped into - // one set) (open, the open part is from macro expansions, not controlled). + // 2. `macro_use` prelude (open, the open part is from macro expansions, not controlled). // 2a. User-defined prelude from macro-use // (open, the open part is from macro expansions, not controlled). - // 2b. Standard library prelude, currently just a macro-use (closed, controlled) - // 2c. Language prelude, perhaps including builtin attributes - // (closed, controlled, except for legacy plugins). - // 3. Builtin attributes (closed, controlled). + // 2b. Standard library prelude is currently implemented as `macro-use` (closed, controlled) + // 3. Language prelude: builtin macros (closed, controlled, except for legacy plugins). + // 4. Language prelude: builtin attributes (closed, controlled). assert!(ns == TypeNS || ns == MacroNS); assert!(force || !record_used); // `record_used` implies `force` @@ -613,12 +614,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> { enum WhereToResolve<'a> { Module(Module<'a>), - MacroPrelude, + MacroUsePrelude, + BuiltinMacros, BuiltinAttrs, ExternPrelude, ToolPrelude, StdLibPrelude, - PrimitiveTypes, + BuiltinTypes, } // Go through all the scopes and try to resolve the name. @@ -639,8 +641,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.current_module = orig_current_module; binding.map(|binding| (binding, FromPrelude(false))) } - WhereToResolve::MacroPrelude => { - match self.macro_prelude.get(&ident.name).cloned() { + WhereToResolve::MacroUsePrelude => { + match self.macro_use_prelude.get(&ident.name).cloned() { + Some(binding) => Ok((binding, FromPrelude(true))), + None => Err(Determinacy::Determined), + } + } + WhereToResolve::BuiltinMacros => { + match self.builtin_macros.get(&ident.name).cloned() { Some(binding) => Ok((binding, FromPrelude(true))), None => Err(Determinacy::Determined), } @@ -708,7 +716,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } result } - WhereToResolve::PrimitiveTypes => { + WhereToResolve::BuiltinTypes => { if let Some(prim_ty) = self.primitive_type_table.primitive_types.get(&ident.name).cloned() { let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public, @@ -728,19 +736,20 @@ impl<'a, 'cl> Resolver<'a, 'cl> { None => { use_prelude = !module.no_implicit_prelude; if ns == MacroNS { - WhereToResolve::MacroPrelude + WhereToResolve::MacroUsePrelude } else { WhereToResolve::ExternPrelude } } } } - WhereToResolve::MacroPrelude => WhereToResolve::BuiltinAttrs, + WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros, + WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs, WhereToResolve::BuiltinAttrs => break, // nowhere else to search WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude, WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude, - WhereToResolve::StdLibPrelude => WhereToResolve::PrimitiveTypes, - WhereToResolve::PrimitiveTypes => break, // nowhere else to search + WhereToResolve::StdLibPrelude => WhereToResolve::BuiltinTypes, + WhereToResolve::BuiltinTypes => break, // nowhere else to search }; continue; @@ -958,14 +967,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { None // Then check global macros. }.or_else(|| { - // FIXME: get_macro needs an &mut Resolver, can we do it without cloning? - let macro_prelude = self.macro_prelude.clone(); - let names = macro_prelude.iter().filter_map(|(name, binding)| { - if binding.get_macro(self).kind() == kind { - Some(name) - } else { - None - } + let names = self.builtin_macros.iter().chain(self.macro_use_prelude.iter()) + .filter_map(|(name, binding)| { + if binding.macro_kind() == Some(kind) { Some(name) } else { None } }); find_best_match_for_name(names, name, None) // Then check modules.