diff options
Diffstat (limited to 'src/libsyntax_ext')
| -rw-r--r-- | src/libsyntax_ext/deriving/custom.rs | 18 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/decodable.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/encodable.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/mod.rs | 257 | ||||
| -rw-r--r-- | src/libsyntax_ext/lib.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax_ext/proc_macro_registrar.rs | 8 |
6 files changed, 30 insertions, 264 deletions
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 2ce6fc03f77..974e86a5741 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -32,18 +32,18 @@ impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_mac(&mut self, _mac: &Mac) {} } -pub struct CustomDerive { +pub struct ProcMacroDerive { inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>, } -impl CustomDerive { - pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>) -> CustomDerive { - CustomDerive { inner: inner, attrs: attrs } +impl ProcMacroDerive { + pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>) -> ProcMacroDerive { + ProcMacroDerive { inner: inner, attrs: attrs } } } -impl MultiItemModifier for CustomDerive { +impl MultiItemModifier for ProcMacroDerive { fn expand(&self, ecx: &mut ExtCtxt, span: Span, @@ -54,7 +54,7 @@ impl MultiItemModifier for CustomDerive { Annotatable::Item(item) => item, Annotatable::ImplItem(_) | Annotatable::TraitItem(_) => { - ecx.span_err(span, "custom derive attributes may only be \ + ecx.span_err(span, "proc-macro derives may only be \ applied to struct/enum items"); return Vec::new() } @@ -63,7 +63,7 @@ impl MultiItemModifier for CustomDerive { ItemKind::Struct(..) | ItemKind::Enum(..) => {}, _ => { - ecx.span_err(span, "custom derive attributes may only be \ + ecx.span_err(span, "proc-macro derives may only be \ applied to struct/enum items"); return Vec::new() } @@ -81,7 +81,7 @@ impl MultiItemModifier for CustomDerive { let stream = match res { Ok(stream) => stream, Err(e) => { - let msg = "custom derive attribute panicked"; + let msg = "proc-macro derive panicked"; let mut err = ecx.struct_span_fatal(span, msg); if let Some(s) = e.downcast_ref::<String>() { err.help(&format!("message: {}", s)); @@ -100,7 +100,7 @@ impl MultiItemModifier for CustomDerive { Ok(new_items) => new_items, Err(_) => { // FIXME: handle this better - let msg = "custom derive produced unparseable tokens"; + let msg = "proc-macro derive produced unparseable tokens"; ecx.struct_span_fatal(span, msg).emit(); panic!(FatalError); } diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index e2634c60dca..498f2348b80 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -13,6 +13,7 @@ use deriving; use deriving::generic::*; use deriving::generic::ty::*; +use deriving::warn_if_deprecated; use syntax::ast; use syntax::ast::{Expr, MetaItem, Mutability}; @@ -35,6 +36,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { + 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..9d155c22ad0 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -91,6 +91,7 @@ use deriving; use deriving::generic::*; use deriving::generic::ty::*; +use deriving::warn_if_deprecated; use syntax::ast::{Expr, ExprKind, MetaItem, Mutability}; use syntax::ext::base::{Annotatable, ExtCtxt}; @@ -112,6 +113,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { + 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..3bceb02f3d6 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -10,12 +10,11 @@ //! The compiler code necessary to implement the `#[derive]` extensions. -use syntax::ast::{self, MetaItem}; -use syntax::attr::HasAttrs; +use std::rc::Rc; +use syntax::ast; 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; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -89,234 +88,6 @@ fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { } } -pub fn expand_derive(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - annotatable: Annotatable) - -> Vec<Annotatable> { - debug!("expand_derive: span = {:?}", span); - debug!("expand_derive: mitem = {:?}", mitem); - debug!("expand_derive: annotatable input = {:?}", annotatable); - let mut item = match annotatable { - Annotatable::Item(item) => item, - other => { - cx.span_err(span, "`derive` can only be applied to items"); - return vec![other] - } - }; - - let derive = Symbol::intern("derive"); - let mut derive_attrs = Vec::new(); - item = item.map_attrs(|attrs| { - let partition = attrs.into_iter().partition(|attr| attr.name() == derive); - derive_attrs = partition.0; - partition.1 - }); - - // Expand `#[derive]`s after other attribute macro invocations. - if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() { - return vec![Annotatable::Item(item.map_attrs(|mut attrs| { - attrs.push(cx.attribute(span, mitem.clone())); - attrs.extend(derive_attrs); - attrs - }))]; - } - - let get_traits = |mitem: &MetaItem, cx: &ExtCtxt| { - if mitem.value_str().is_some() { - cx.span_err(mitem.span, "unexpected value in `derive`"); - } - - let traits = mitem.meta_item_list().unwrap_or(&[]).to_owned(); - if traits.is_empty() { - cx.span_warn(mitem.span, "empty trait list in `derive`"); - } - traits - }; - - let mut traits = get_traits(mitem, cx); - for derive_attr in derive_attrs { - traits.extend(get_traits(&derive_attr.value, cx)); - } - - // First, weed out malformed #[derive] - traits.retain(|titem| { - if titem.word().is_none() { - cx.span_err(titem.span, "malformed `derive` entry"); - false - } else { - true - } - }); - - // Next, check for old-style #[derive(Foo)] - // - // These all get expanded to `#[derive_Foo]` and will get expanded first. If - // we actually add any attributes here then we return to get those expanded - // and then eventually we'll come back to finish off the other derive modes. - let mut new_attributes = Vec::new(); - traits.retain(|titem| { - let tword = titem.word().unwrap(); - let tname = tword.name(); - - if is_builtin_trait(tname) || { - let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(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() { - feature_gate::emit_feature_err(&cx.parse_sess, - "custom_derive", - titem.span, - feature_gate::GateIssue::Language, - feature_gate::EXPLAIN_CUSTOM_DERIVE); - } else { - let name = Symbol::intern(&format!("derive_{}", tname)); - if !cx.resolver.is_whitelisted_legacy_custom_derive(name) { - cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); - } - let mitem = cx.meta_word(titem.span, name); - new_attributes.push(cx.attribute(mitem.span, mitem)); - } - false - }); - if new_attributes.len() > 0 { - item = item.map(|mut i| { - i.attrs.extend(new_attributes); - if traits.len() > 0 { - let list = cx.meta_list(mitem.span, derive, traits); - i.attrs.push(cx.attribute(mitem.span, list)); - } - i - }); - return vec![Annotatable::Item(item)] - } - - // Now check for macros-1.1 style custom #[derive]. - // - // Expand each of them in order given, but *before* we expand any built-in - // derive modes. The logic here is to: - // - // 1. Collect the remaining `#[derive]` annotations into a list. If - // there are any left, attach a `#[derive]` attribute to the item - // that we're currently expanding with the remaining derive modes. - // 2. Manufacture a `#[derive(Foo)]` attribute to pass to the expander. - // 3. Expand the current item we're expanding, getting back a list of - // items that replace it. - // 4. Extend the returned list with the current list of items we've - // collected so far. - // 5. Return everything! - // - // If custom derive extensions end up threading through the `#[derive]` - // attribute, we'll get called again later on to continue expanding - // those modes. - let macros_11_derive = traits.iter() - .cloned() - .enumerate() - .filter(|&(_, ref name)| !is_builtin_trait(name.name().unwrap())) - .next(); - if let Some((i, titem)) = macros_11_derive { - let tname = ast::Ident::with_empty_ctxt(titem.name().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| { - let list = cx.meta_list(mitem.span, derive, traits); - i.attrs.push(cx.attribute(mitem.span, list)); - i - }); - } - let titem = cx.meta_list_item_word(titem.span, titem.name().unwrap()); - let mitem = cx.meta_list(titem.span, derive, vec![titem]); - let item = Annotatable::Item(item); - - let span = Span { - expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { - call_site: mitem.span, - callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(Symbol::intern(&format!("derive({})", tname))), - span: None, - allow_internal_unstable: false, - }, - }), - ..mitem.span - }; - - if let SyntaxExtension::CustomDerive(ref ext) = *ext { - return ext.expand(cx, span, &mitem, item); - } else { - unreachable!() - } - } - - // Ok, at this point we know that there are no old-style `#[derive_Foo]` nor - // any macros-1.1 style `#[derive(Foo)]`. Expand all built-in traits here. - - // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted) - // `#[structural_match]` attribute. - let (partial_eq, eq) = (Symbol::intern("PartialEq"), Symbol::intern("Eq")); - if traits.iter().any(|t| t.name() == Some(partial_eq)) && - traits.iter().any(|t| t.name() == Some(eq)) { - let structural_match = Symbol::intern("structural_match"); - let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); - let meta = cx.meta_word(span, structural_match); - item = item.map(|mut i| { - i.attrs.push(cx.attribute(span, meta)); - i - }); - } - - // RFC #1521. `Clone` can assume that `Copy` types' clone implementation is - // the same as the copy implementation. - // - // Add a marker attribute here picked up during #[derive(Clone)] - let (copy, clone) = (Symbol::intern("Copy"), Symbol::intern("Clone")); - if traits.iter().any(|t| t.name() == Some(clone)) && - traits.iter().any(|t| t.name() == Some(copy)) { - let marker = Symbol::intern("rustc_copy_clone_marker"); - let span = allow_unstable(cx, span, "derive(Copy, Clone)"); - let meta = cx.meta_word(span, marker); - item = item.map(|mut i| { - i.attrs.push(cx.attribute(span, meta)); - i - }); - } - - let mut items = Vec::new(); - for titem in traits.iter() { - let tname = titem.word().unwrap().name(); - let name = Symbol::intern(&format!("derive({})", tname)); - let mitem = cx.meta_word(titem.span, name); - - let span = Span { - expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { - call_site: titem.span, - callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(name), - span: None, - allow_internal_unstable: true, - }, - }), - ..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(); - } - - items.insert(0, Annotatable::Item(item)); - return items -} - macro_rules! derive_traits { ($( $name:expr => $func:path, )+) => { pub fn is_builtin_trait(name: ast::Name) -> bool { @@ -326,21 +97,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..7533171b085 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -24,7 +24,6 @@ #![feature(staged_api)] extern crate fmt_macros; -#[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -51,12 +50,14 @@ pub mod proc_macro_impl; use std::rc::Rc; use syntax::ast; -use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension}; +use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension}; use syntax::symbol::Symbol; 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)); }; @@ -112,8 +113,6 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, register(Symbol::intern("format_args"), NormalTT(Box::new(format::expand_format_args), None, true)); - register(Symbol::intern("derive"), MultiModifier(Box::new(deriving::expand_derive))); - for (name, ext) in user_exts { register(name, ext); } diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index c8af16e9242..325f09a83dd 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -27,7 +27,7 @@ use syntax_pos::{Span, DUMMY_SP}; use deriving; -struct CustomDerive { +struct ProcMacroDerive { trait_name: ast::Name, function_name: Ident, span: Span, @@ -40,7 +40,7 @@ struct AttrProcMacro { } struct CollectProcMacros<'a> { - derives: Vec<CustomDerive>, + derives: Vec<ProcMacroDerive>, attr_macros: Vec<AttrProcMacro>, in_root: bool, handler: &'a errors::Handler, @@ -176,7 +176,7 @@ impl<'a> CollectProcMacros<'a> { }; if self.in_root && item.vis == ast::Visibility::Public { - self.derives.push(CustomDerive { + self.derives.push(ProcMacroDerive { span: item.span, trait_name: trait_name, function_name: item.ident, @@ -319,7 +319,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { // } // } fn mk_registrar(cx: &mut ExtCtxt, - custom_derives: &[CustomDerive], + custom_derives: &[ProcMacroDerive], custom_attrs: &[AttrProcMacro]) -> P<ast::Item> { let eid = cx.codemap().record_expansion(ExpnInfo { call_site: DUMMY_SP, |
