]> git.lizzy.rs Git - rust.git/commitdiff
Make builtin derives a SyntaxExtension
authorJosh Driver <keeperofdakeys@gmail.com>
Mon, 23 Jan 2017 15:01:49 +0000 (01:31 +1030)
committerJosh Driver <keeperofdakeys@gmail.com>
Sat, 4 Feb 2017 23:01:01 +0000 (09:31 +1030)
This allows builtin derives to be registered and
resolved, just like other derive types.

src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax_ext/deriving/decodable.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/lib.rs

index edf74e1fe19f155d0a19075f42d50f4fb45ef801..231e2e6205cf8a3966b97c6df27b21aae1bcd945 100644 (file)
@@ -10,7 +10,7 @@
 
 pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT};
 
-use ast::{self, Attribute, Name, PatKind};
+use ast::{self, Attribute, Name, PatKind, MetaItem};
 use attr::HasAttrs;
 use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
 use syntax_pos::{Span, ExpnId, NO_EXPANSION};
@@ -471,6 +471,9 @@ fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
     }
 }
 
+pub type BuiltinDeriveFn =
+    for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
+
 /// An enum representing the different kinds of syntax extensions.
 pub enum SyntaxExtension {
     /// A syntax extension that is attached to an item and creates new items
@@ -508,6 +511,9 @@ pub enum SyntaxExtension {
     IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
 
     CustomDerive(Box<MultiItemModifier>),
+
+    /// An attribute-like procedural macro that derives a builtin trait.
+    BuiltinDerive(BuiltinDeriveFn),
 }
 
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
index 226625ebc8e5e4fd0cf501ac92ca1145e7029506..0e5d94e03810f62d78880dfa967b1bf3b1d6ed32 100644 (file)
@@ -370,7 +370,7 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
                 self.parse_expansion(tok_result, kind, name, attr.span)
             }
-            SyntaxExtension::CustomDerive(_) => {
+            SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
                 self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name));
                 kind.dummy(attr.span)
             }
@@ -440,7 +440,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 return kind.dummy(span);
             }
 
-            SyntaxExtension::CustomDerive(..) => {
+            SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
                 self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname));
                 return kind.dummy(span);
             }
index e2634c60dcaad0cd8f16ab3e824c8a54e8b7ccbb..6359d642d157cf4159c955e784f476aca4126e8e 100644 (file)
@@ -35,6 +35,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                                  mitem: &MetaItem,
                                  item: &Annotatable,
                                  push: &mut FnMut(Annotatable)) {
+    deriving::warn_if_deprecated(cx, span, "Decodable");
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
 }
 
index 092738ab8a03d372333f6272ae608e775cc9d617..a276193e81b979de9df1cd96701f9fb359d03527 100644 (file)
@@ -112,6 +112,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
                                  mitem: &MetaItem,
                                  item: &Annotatable,
                                  push: &mut FnMut(Annotatable)) {
+    deriving::warn_if_deprecated(cx, span, "Encodable");
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
 }
 
index 096f6dfd5d8d86cbae0dc18d3c8a640ec70d1c04..30d0da588a5df0e6d3908d8069e6e35d854a7980 100644 (file)
 
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
+use std::rc::Rc;
 use syntax::ast::{self, MetaItem};
 use syntax::attr::HasAttrs;
 use syntax::codemap;
-use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
+use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver};
 use syntax::ext::build::AstBuilder;
 use syntax::feature_gate;
 use syntax::ptr::P;
@@ -292,7 +293,10 @@ pub fn expand_derive(cx: &mut ExtCtxt,
     for titem in traits.iter() {
         let tname = titem.word().unwrap().name();
         let name = Symbol::intern(&format!("derive({})", tname));
+        let tname_cx = ast::Ident::with_empty_ctxt(titem.name().unwrap());
         let mitem = cx.meta_word(titem.span, name);
+        let path = ast::Path::from_ident(titem.span, tname_cx);
+        let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap();
 
         let span = Span {
             expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
@@ -306,11 +310,15 @@ pub fn expand_derive(cx: &mut ExtCtxt,
             ..titem.span
         };
 
-        let my_item = Annotatable::Item(item);
-        expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| {
-            items.push(a);
-        });
-        item = my_item.expect_item();
+        if let SyntaxExtension::BuiltinDerive(ref func) = *ext {
+            let my_item = Annotatable::Item(item);
+            func(cx, span, &mitem, &my_item, &mut |a| {
+                items.push(a)
+            });
+            item = my_item.expect_item();
+        } else {
+            unreachable!();
+        }
     }
 
     items.insert(0, Annotatable::Item(item));
@@ -326,21 +334,13 @@ pub fn is_builtin_trait(name: ast::Name) -> bool {
             }
         }
 
-        fn expand_builtin(name: &str,
-                          ecx: &mut ExtCtxt,
-                          span: Span,
-                          mitem: &MetaItem,
-                          item: &Annotatable,
-                          push: &mut FnMut(Annotatable)) {
-            match name {
-                $(
-                    $name => {
-                        warn_if_deprecated(ecx, span, $name);
-                        $func(ecx, span, mitem, item, push);
-                    }
-                )*
-                _ => panic!("not a builtin derive mode: {}", name),
-            }
+        pub fn register_builtin_derives(resolver: &mut Resolver) {
+            $(
+                resolver.add_ext(
+                    ast::Ident::with_empty_ctxt(Symbol::intern($name)),
+                    Rc::new(SyntaxExtension::BuiltinDerive($func))
+                );
+            )*
         }
     }
 }
index ebec23d0901a0409ea705cf3db7cbe7fa1275204..e872cfaeacb7b512542c79bbc43cc19e04679418 100644 (file)
@@ -57,6 +57,8 @@
 pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
                          user_exts: Vec<NamedSyntaxExtension>,
                          enable_quotes: bool) {
+    deriving::register_builtin_derives(resolver);
+
     let mut register = |name, ext| {
         resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
     };