diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index edf74e1fe19..231e2e6205c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -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 @@ impl MacResult for DummyResult { } } +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, Option, bool), CustomDerive(Box), + + /// An attribute-like procedural macro that derives a builtin trait. + BuiltinDerive(BuiltinDeriveFn), } pub type NamedSyntaxExtension = (Name, SyntaxExtension); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 226625ebc8e..0e5d94e0381 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -370,7 +370,7 @@ 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) } - 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 @@ impl<'a, 'b> MacroExpander<'a, 'b> { 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); } diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index e2634c60dca..6359d642d15 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -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") } diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 092738ab8a0..a276193e81b 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -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") } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 096f6dfd5d8..30d0da588a5 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -10,10 +10,11 @@ //! 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 @@ macro_rules! derive_traits { } } - 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)) + ); + )* } } } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index ebec23d0901..e872cfaeacb 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -57,6 +57,8 @@ use syntax::symbol::Symbol; pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, user_exts: Vec, 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)); };