about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-09-04 01:14:58 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-09-10 04:00:48 +0300
commita25c841e884517eb48b67c36326d31192aff82d9 (patch)
treeb6c137c5b19376d9c4c3fbca4551357adce31e46
parent2d4e34ca8bb1369f7e0eea4cb50e6faa0827a6e5 (diff)
downloadrust-a25c841e884517eb48b67c36326d31192aff82d9.tar.gz
rust-a25c841e884517eb48b67c36326d31192aff82d9.zip
resolve: Split macro prelude into built-in and user-defined parts
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs2
-rw-r--r--src/librustc_resolve/lib.rs23
-rw-r--r--src/librustc_resolve/macros.rs56
3 files changed, 48 insertions, 33 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 63f643d7a29..21c0f13baa4 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 5cb615554ee..98fbcd1fb18 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<MacroKind> {
+        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<Ident>,
-    macro_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
+    builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
+    macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
     unshadowable_attrs: FxHashMap<Name, &'a NameBinding<'a>>,
     pub all_macros: FxHashMap<Name, Def>,
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
@@ -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 93874ee0e85..b4c772cb8c6 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<SyntaxExtension>) {
@@ -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.