about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-10-15 20:50:30 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-10-15 22:55:19 +0000
commit33e3da831c8b517c94d85599edf2bcd259128181 (patch)
treeb25e5b75bd810796d51d3c1bcea4e896971b57a0
parentd902963b6d58b8b79ec3e29a508b2b9e86716293 (diff)
downloadrust-33e3da831c8b517c94d85599edf2bcd259128181.tar.gz
rust-33e3da831c8b517c94d85599edf2bcd259128181.zip
Use the macro namespace for custom derives.
-rw-r--r--src/librustc/middle/cstore.rs3
-rw-r--r--src/librustc_metadata/macro_import.rs3
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs51
-rw-r--r--src/librustc_resolve/lib.rs3
-rw-r--r--src/librustc_resolve/macros.rs6
-rw-r--r--src/libsyntax/ext/base.rs4
-rw-r--r--src/libsyntax/ext/expand.rs15
-rw-r--r--src/libsyntax_ext/deriving/mod.rs24
8 files changed, 62 insertions, 47 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index dfd6256c357..b54862ae0ad 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -35,7 +35,6 @@ use session::Session;
 use session::search_paths::PathKind;
 use util::nodemap::{NodeSet, DefIdMap};
 use std::path::PathBuf;
-use std::rc::Rc;
 use syntax::ast;
 use syntax::attr;
 use syntax::ext::base::MultiItemModifier;
@@ -425,7 +424,7 @@ pub struct LoadedMacro {
 
 pub enum LoadedMacroKind {
     Def(ast::MacroDef),
-    CustomDerive(String, Rc<MultiItemModifier>),
+    CustomDerive(String, Box<MultiItemModifier>),
 }
 
 pub trait CrateLoader {
diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs
index 7cd03b2d5b9..3b1b2a4cd27 100644
--- a/src/librustc_metadata/macro_import.rs
+++ b/src/librustc_metadata/macro_import.rs
@@ -11,7 +11,6 @@
 //! Used by `rustc` when loading a crate with exported macros.
 
 use std::collections::HashSet;
-use std::rc::Rc;
 use std::env;
 use std::mem;
 
@@ -212,7 +211,7 @@ impl<'a> CrateLoader<'a> {
             fn register_custom_derive(&mut self,
                                       trait_name: &str,
                                       expand: fn(TokenStream) -> TokenStream) {
-                let derive = Rc::new(CustomDerive::new(expand));
+                let derive = Box::new(CustomDerive::new(expand));
                 self.0.push(LoadedMacro {
                     kind: LoadedMacroKind::CustomDerive(trait_name.to_string(), derive),
                     import_site: self.1,
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 5600669d45f..dac9e57be32 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -36,7 +36,7 @@ use syntax::parse::token;
 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::{MultiItemModifier, Resolver as SyntaxResolver};
+use syntax::ext::base::{SyntaxExtension, Resolver as SyntaxResolver};
 use syntax::ext::hygiene::Mark;
 use syntax::feature_gate::{self, emit_feature_err};
 use syntax::ext::tt::macro_rules;
@@ -195,22 +195,25 @@ impl<'b> Resolver<'b> {
                 // We need to error on `#[macro_use] extern crate` when it isn't at the
                 // crate root, because `$crate` won't work properly.
                 let is_crate_root = self.current_module.parent.is_none();
+                let import_macro = |this: &mut Self, name, ext, span| {
+                    let shadowing = this.builtin_macros.insert(name, Rc::new(ext)).is_some();
+                    if shadowing && expansion != Mark::root() {
+                        let msg = format!("`{}` is already in scope", name);
+                        this.session.struct_span_err(span, &msg)
+                            .note("macro-expanded `#[macro_use]`s may not shadow \
+                                   existing macros (see RFC 1560)")
+                            .emit();
+                    }
+                };
+
+                let mut custom_derive_crate = false;
                 for loaded_macro in self.crate_loader.load_macros(item, is_crate_root) {
                     match loaded_macro.kind {
                         LoadedMacroKind::Def(mut def) => {
-                            let name = def.ident.name;
                             if def.use_locally {
-                                let ext =
-                                    Rc::new(macro_rules::compile(&self.session.parse_sess, &def));
-                                if self.builtin_macros.insert(name, ext).is_some() &&
-                                   expansion != Mark::root() {
-                                    let msg = format!("`{}` is already in scope", name);
-                                    self.session.struct_span_err(loaded_macro.import_site, &msg)
-                                        .note("macro-expanded `#[macro_use]`s may not shadow \
-                                               existing macros (see RFC 1560)")
-                                        .emit();
-                                }
-                                self.macro_names.insert(name);
+                                self.macro_names.insert(def.ident.name);
+                                let ext = macro_rules::compile(&self.session.parse_sess, &def);
+                                import_macro(self, def.ident.name, ext, loaded_macro.import_site);
                             }
                             if def.export {
                                 def.id = self.next_node_id();
@@ -218,10 +221,19 @@ impl<'b> Resolver<'b> {
                             }
                         }
                         LoadedMacroKind::CustomDerive(name, ext) => {
-                            self.insert_custom_derive(&name, ext, item.span);
+                            custom_derive_crate = true;
+                            let ext = SyntaxExtension::CustomDerive(ext);
+                            import_macro(self, token::intern(&name), ext, loaded_macro.import_site);
                         }
                     }
                 }
+
+                if custom_derive_crate && !self.session.features.borrow().proc_macro {
+                    let issue = feature_gate::GateIssue::Language;
+                    let msg = "loading custom derive macro crates is experimentally supported";
+                    emit_feature_err(&self.session.parse_sess, "proc_macro", item.span, issue, msg);
+                }
+
                 self.crate_loader.process_item(item, &self.definitions);
 
                 // n.b. we don't need to look at the path option here, because cstore already did
@@ -504,17 +516,6 @@ impl<'b> Resolver<'b> {
 
         false
     }
-
-    fn insert_custom_derive(&mut self, name: &str, ext: Rc<MultiItemModifier>, sp: Span) {
-        if !self.session.features.borrow().proc_macro {
-            let sess = &self.session.parse_sess;
-            let msg = "loading custom derive macro crates is experimentally supported";
-            emit_feature_err(sess, "proc_macro", sp, feature_gate::GateIssue::Language, msg);
-        }
-        if self.derive_modes.insert(token::intern(name), ext).is_some() {
-            self.session.span_err(sp, &format!("cannot shadow existing derive mode `{}`", name));
-        }
-    }
 }
 
 pub struct BuildReducedGraphVisitor<'a, 'b: 'a> {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 6db844c1d03..21641a17bbf 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -53,7 +53,6 @@ use rustc::ty;
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet};
 
-use syntax::ext::base::MultiItemModifier;
 use syntax::ext::hygiene::Mark;
 use syntax::ast::{self, FloatTy};
 use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy};
@@ -1080,7 +1079,6 @@ pub struct Resolver<'a> {
     new_import_semantics: bool, // true if `#![feature(item_like_imports)]`
 
     pub exported_macros: Vec<ast::MacroDef>,
-    pub derive_modes: FnvHashMap<Name, Rc<MultiItemModifier>>,
     crate_loader: &'a mut CrateLoader,
     macro_names: FnvHashSet<Name>,
     builtin_macros: FnvHashMap<Name, Rc<SyntaxExtension>>,
@@ -1271,7 +1269,6 @@ impl<'a> Resolver<'a> {
             new_import_semantics: session.features.borrow().item_like_imports,
 
             exported_macros: Vec::new(),
-            derive_modes: FnvHashMap(),
             crate_loader: crate_loader,
             macro_names: FnvHashSet(),
             builtin_macros: FnvHashMap(),
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 6741197b79c..cf5ea236b3e 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -17,7 +17,7 @@ use std::cell::Cell;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::errors::DiagnosticBuilder;
-use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator, MultiItemModifier};
+use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
 use syntax::ext::base::{NormalTT, SyntaxExtension};
 use syntax::ext::expand::Expansion;
 use syntax::ext::hygiene::Mark;
@@ -186,10 +186,6 @@ impl<'a> base::Resolver for Resolver<'a> {
             }
         })
     }
-
-    fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option<Rc<MultiItemModifier>> {
-        self.derive_modes.get(&ident.name).cloned()
-    }
 }
 
 impl<'a> Resolver<'a> {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 99b883d26d8..11c6f87a655 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -508,6 +508,8 @@ pub enum SyntaxExtension {
     /// the block.
     ///
     IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
+
+    CustomDerive(Box<MultiItemModifier>),
 }
 
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
@@ -524,7 +526,6 @@ pub trait Resolver {
     fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy>;
-    fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option<Rc<MultiItemModifier>>;
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -545,7 +546,6 @@ impl Resolver for DummyResolver {
     fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
 
     fn find_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
-    fn resolve_derive_mode(&mut self, _ident: ast::Ident) -> Option<Rc<MultiItemModifier>> { None }
     fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy> {
         Err(Determinacy::Determined)
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 3a5b3ab8328..6aeb46fd522 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -364,7 +364,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
                 self.parse_expansion(tok_result, kind, name, attr.span)
             }
-            _ => unreachable!(),
+            SyntaxExtension::CustomDerive(_) => {
+                self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name));
+                kind.dummy(attr.span)
+            }
+            _ => {
+                let msg = &format!("macro `{}` may not be used in attributes", name);
+                self.cx.span_err(attr.span, &msg);
+                kind.dummy(attr.span)
+            }
         }
     }
 
@@ -439,6 +447,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 return kind.dummy(span);
             }
 
+            SyntaxExtension::CustomDerive(..) => {
+                self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname));
+                return kind.dummy(span);
+            }
+
             SyntaxExtension::ProcMacro(ref expandfun) => {
                 if ident.name != keywords::Invalid.name() {
                     let msg =
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 9f99919c895..07401d59a15 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -12,7 +12,7 @@
 
 use syntax::ast::{self, MetaItem};
 use syntax::attr::HasAttrs;
-use syntax::ext::base::{Annotatable, ExtCtxt};
+use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
 use syntax::ext::build::AstBuilder;
 use syntax::feature_gate;
 use syntax::codemap;
@@ -158,10 +158,14 @@ pub fn expand_derive(cx: &mut ExtCtxt,
         let tword = titem.word().unwrap();
         let tname = tword.name();
 
-        let derive_mode = ast::Ident::with_empty_ctxt(intern(&tname));
-        let derive_mode = cx.resolver.resolve_derive_mode(derive_mode);
-        if is_builtin_trait(&tname) || derive_mode.is_some() {
-            return true
+        if is_builtin_trait(&tname) || {
+            let derive_mode =
+                ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(intern(&tname)));
+            cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| {
+                if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false }
+            }).unwrap_or(false)
+        } {
+            return true;
         }
 
         if !cx.ecfg.enable_custom_derive() {
@@ -216,7 +220,9 @@ pub fn expand_derive(cx: &mut ExtCtxt,
                                  .next();
     if let Some((i, titem)) = macros_11_derive {
         let tname = ast::Ident::with_empty_ctxt(intern(&titem.name().unwrap()));
-        let ext = cx.resolver.resolve_derive_mode(tname).unwrap();
+        let path = ast::Path::from_ident(titem.span, tname);
+        let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap();
+
         traits.remove(i);
         if traits.len() > 0 {
             item = item.map(|mut i| {
@@ -232,7 +238,11 @@ pub fn expand_derive(cx: &mut ExtCtxt,
                                  intern_and_get_ident("derive"),
                                  vec![titem]);
         let item = Annotatable::Item(item);
-        return ext.expand(cx, mitem.span, &mitem, item)
+        if let SyntaxExtension::CustomDerive(ref ext) = *ext {
+            return ext.expand(cx, mitem.span, &mitem, item);
+        } else {
+            unreachable!()
+        }
     }
 
     // Ok, at this point we know that there are no old-style `#[derive_Foo]` nor