diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-04-28 17:34:39 +1200 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-04-30 20:29:45 +1200 |
| commit | c0a42aecbc85298fb6351253c4cd1824567b7a42 (patch) | |
| tree | e0a195bfbacb4bf2385f5e98fde07429e9d1d211 /src/libsyntax | |
| parent | 0a4f9a26962d85d57a0b603ad324bd86fdd474cf (diff) | |
| download | rust-c0a42aecbc85298fb6351253c4cd1824567b7a42.tar.gz rust-c0a42aecbc85298fb6351253c4cd1824567b7a42.zip | |
WIP refactor expansion of decorators and move derive to MultiDecorator
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 20 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/bounds.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/clone.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/eq.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/ord.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/partial_eq.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/partial_ord.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/decodable.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/default.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/encodable.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/mod.rs | 71 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/hash.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/mod.rs | 80 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/primitive.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/show.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 288 |
16 files changed, 299 insertions, 277 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 3e54e43c029..2ecefef5104 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -123,6 +123,16 @@ impl Annotatable { } } + pub fn map_item_or<F, G>(self, mut f: F, mut or: G) -> Annotatable + where F: FnMut(P<ast::Item>) -> P<ast::Item>, + G: FnMut(Annotatable) -> Annotatable + { + match self { + Annotatable::Item(i) => Annotatable::Item(f(i)), + _ => or(self) + } + } + pub fn expect_trait_item(self) -> P<ast::TraitItem> { match self { Annotatable::TraitItem(i) => i, @@ -144,18 +154,18 @@ pub trait MultiItemDecorator { ecx: &mut ExtCtxt, sp: Span, meta_item: &ast::MetaItem, - item: &Annotatable, - push: &mut FnMut(Annotatable)); + item: Annotatable, + push: &mut FnMut(Annotatable)); } impl<F> MultiItemDecorator for F - where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, &mut FnMut(Annotatable)) + where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, Annotatable, &mut FnMut(Annotatable)) { fn expand(&self, ecx: &mut ExtCtxt, sp: Span, meta_item: &ast::MetaItem, - item: &Annotatable, + item: Annotatable, push: &mut FnMut(Annotatable)) { (*self)(ecx, sp, meta_item, item, push) } @@ -433,6 +443,7 @@ pub enum SyntaxExtension { /// based upon it. #[unstable(feature = "rustc_private")] #[deprecated(since = "1.0.0", reason = "replaced by MultiDecorator")] + #[allow(deprecated)] Decorator(Box<ItemDecorator + 'static>), /// A syntax extension that is attached to an item and creates new items @@ -445,6 +456,7 @@ pub enum SyntaxExtension { /// in-place. #[unstable(feature = "rustc_private")] #[deprecated(since = "1.0.0", reason = "replaced by MultiModifier")] + #[allow(deprecated)] Modifier(Box<ItemModifier + 'static>), /// A syntax extension that is attached to an item and modifies it diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index eb3debeac99..1300eb7ff3f 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -8,18 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item}; +use ast::MetaItem; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; -use ptr::P; pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt, span: Span, _: &MetaItem, - _: &Item, - _: &mut FnMut(P<Item>)) + _: Annotatable, + _: &mut FnMut(Annotatable)) { cx.span_err(span, "this unsafe trait should be implemented explicitly"); } @@ -27,8 +26,8 @@ pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt, pub fn expand_deriving_copy(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { let path = Path::new(vec![ if cx.use_std { "std" } else { "core" }, diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 97fc3f0bf56..935f0ae8a5e 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr}; +use ast::{MetaItem, Expr}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -20,8 +20,8 @@ use ptr::P; pub fn expand_deriving_clone(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index ce8f0a7b32b..d7142d657d4 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr}; +use ast::{MetaItem, Expr}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -20,8 +20,8 @@ use ptr::P; pub fn expand_deriving_eq(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { cs_same_method( diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 94cc0d9c493..6e52da2f332 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -9,9 +9,9 @@ // except according to those terms. use ast; -use ast::{MetaItem, Item, Expr}; +use ast::{MetaItem, Expr}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -21,8 +21,8 @@ use ptr::P; pub fn expand_deriving_ord(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); diff --git a/src/libsyntax/ext/deriving/cmp/partial_eq.rs b/src/libsyntax/ext/deriving/cmp/partial_eq.rs index 61eb81c6755..c31c91760e0 100644 --- a/src/libsyntax/ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax/ext/deriving/cmp/partial_eq.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr, self}; +use ast::{MetaItem, Expr, self}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -20,8 +20,8 @@ use ptr::P; pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { // structures are equal if all fields are equal, and non equal, if // any fields are not equal or if the enum variants are different diff --git a/src/libsyntax/ext/deriving/cmp/partial_ord.rs b/src/libsyntax/ext/deriving/cmp/partial_ord.rs index dbb779decac..9097e984dd6 100644 --- a/src/libsyntax/ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax/ext/deriving/cmp/partial_ord.rs @@ -11,9 +11,9 @@ pub use self::OrderingOp::*; use ast; -use ast::{MetaItem, Item, Expr}; +use ast::{MetaItem, Expr}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -23,8 +23,8 @@ use ptr::P; pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { macro_rules! md { ($name:expr, $op:expr, $equal:expr) => { { diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 0b31f06f87d..1ab51865652 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -11,9 +11,9 @@ //! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more. use ast; -use ast::{MetaItem, Item, Expr, MutMutable}; +use ast::{MetaItem, Expr, MutMutable}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -24,8 +24,8 @@ use ptr::P; pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize") } @@ -33,8 +33,8 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt, pub fn expand_deriving_decodable(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize") } @@ -42,8 +42,8 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>), + item: Annotatable, + push: &mut FnMut(Annotatable), krate: &'static str) { if !cx.use_std { diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index f04eaa08dea..b7b741290af 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr}; +use ast::{MetaItem, Expr}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -20,8 +20,8 @@ use ptr::P; pub fn expand_deriving_default(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 92944d64933..47acedbcb8a 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -88,9 +88,9 @@ //! } //! ``` -use ast::{MetaItem, Item, Expr, ExprRet, MutMutable}; +use ast::{MetaItem, Expr, ExprRet, MutMutable}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt,Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -100,8 +100,8 @@ use ptr::P; pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize") } @@ -109,8 +109,8 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt, pub fn expand_deriving_encodable(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") } @@ -118,8 +118,8 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>), + item: Annotatable, + push: &mut FnMut(Annotatable), krate: &'static str) { if !cx.use_std { diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 4c05cd973ff..222bbe2df6d 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -197,7 +197,7 @@ use ast::{EnumDef, Expr, Ident, Generics, StructDef}; use ast_util; use attr; use attr::AttrMetaMethods; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use codemap::{self, DUMMY_SP}; use codemap::Span; @@ -378,41 +378,48 @@ impl<'a> TraitDef<'a> { pub fn expand(&self, cx: &mut ExtCtxt, mitem: &ast::MetaItem, - item: &ast::Item, - push: &mut FnMut(P<ast::Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { - let newitem = match item.node { - ast::ItemStruct(ref struct_def, ref generics) => { - self.expand_struct_def(cx, - &**struct_def, - item.ident, - generics) - } - ast::ItemEnum(ref enum_def, ref generics) => { - self.expand_enum_def(cx, - enum_def, - &item.attrs[..], - item.ident, - generics) + match item { + Annotatable::Item(item) => { + let newitem = match item.node { + ast::ItemStruct(ref struct_def, ref generics) => { + self.expand_struct_def(cx, + &**struct_def, + item.ident, + generics) + } + ast::ItemEnum(ref enum_def, ref generics) => { + self.expand_enum_def(cx, + enum_def, + &item.attrs[..], + item.ident, + generics) + } + _ => { + cx.span_err(mitem.span, "`derive` may only be applied to structs and enums"); + return; + } + }; + // Keep the lint attributes of the previous item to control how the + // generated implementations are linted + let mut attrs = newitem.attrs.clone(); + attrs.extend(item.attrs.iter().filter(|a| { + match &a.name()[..] { + "allow" | "warn" | "deny" | "forbid" => true, + _ => false, + } + }).cloned()); + push(Annotatable::Item(P(ast::Item { + attrs: attrs, + ..(*newitem).clone() + }))) } _ => { - cx.span_err(mitem.span, "`derive` may only be applied to structs and enums"); - return; - } - }; - // Keep the lint attributes of the previous item to control how the - // generated implementations are linted - let mut attrs = newitem.attrs.clone(); - attrs.extend(item.attrs.iter().filter(|a| { - match &a.name()[..] { - "allow" | "warn" | "deny" | "forbid" => true, - _ => false, + cx.span_err(mitem.span, "`derive` may only be applied to structs and enums"); } - }).cloned()); - push(P(ast::Item { - attrs: attrs, - ..(*newitem).clone() - })) + } } /// Given that we are deriving a trait `DerivedTrait` for a type like: diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index b9835eda791..b1ec3f564f5 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr, MutMutable}; +use ast::{MetaItem, Expr, MutMutable}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -19,8 +19,8 @@ use ptr::P; pub fn expand_deriving_hash(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None, diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index bc4a7f90911..61848cca059 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -13,14 +13,13 @@ //! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is //! the standard library, and "std" is the core library. -use ast::{Item, MetaItem, MetaWord, MetaList, MetaNameValue}; +use ast::{MetaItem, MetaWord}; use attr::AttrMetaMethods; -use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier, Annotatable}; +use ext::base::{ExtCtxt, SyntaxEnv, MultiDecorator, MultiItemDecorator, MultiModifier, Annotatable}; use ext::build::AstBuilder; use feature_gate; use codemap::Span; use parse::token::{intern, intern_and_get_ident}; -use ptr::P; macro_rules! pathvec { ($($x:ident)::+) => ( @@ -80,41 +79,46 @@ pub mod generic; fn expand_derive(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: P<Item>) - -> P<Item> { - item.map(|mut item| { - if mitem.value_str().is_some() { - cx.span_err(mitem.span, "unexpected value in `derive`"); - } + annotatable: Annotatable) + -> Annotatable { + annotatable.map_item_or(|item| { + item.map(|mut item| { + if mitem.value_str().is_some() { + cx.span_err(mitem.span, "unexpected value in `derive`"); + } - let traits = mitem.meta_item_list().unwrap_or(&[]); - if traits.is_empty() { - cx.span_warn(mitem.span, "empty trait list in `derive`"); - } + let traits = mitem.meta_item_list().unwrap_or(&[]); + if traits.is_empty() { + cx.span_warn(mitem.span, "empty trait list in `derive`"); + } - for titem in traits.iter().rev() { - let tname = match titem.node { - MetaWord(ref tname) => tname, - _ => { - cx.span_err(titem.span, "malformed `derive` entry"); + for titem in traits.iter().rev() { + let tname = match titem.node { + MetaWord(ref tname) => tname, + _ => { + cx.span_err(titem.span, "malformed `derive` entry"); + continue; + } + }; + + if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) { + feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, + "custom_derive", + titem.span, + feature_gate::EXPLAIN_CUSTOM_DERIVE); continue; } - }; - - if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) { - feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, - "custom_derive", - titem.span, - feature_gate::EXPLAIN_CUSTOM_DERIVE); - continue; - } - // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar] - item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span, - intern_and_get_ident(&format!("derive_{}", tname))))); - } + // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar] + item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span, + intern_and_get_ident(&format!("derive_{}", tname))))); + } - item + item + }) + }, |a| { + cx.span_err(span, "`derive` can only be applied to items"); + a }) } @@ -125,24 +129,24 @@ macro_rules! derive_traits { $({ struct DeriveExtension; - impl ItemDecorator for DeriveExtension { + impl MultiItemDecorator for DeriveExtension { fn expand(&self, ecx: &mut ExtCtxt, sp: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) { + annotatable: Annotatable, + push: &mut FnMut(Annotatable)) { warn_if_deprecated(ecx, sp, $name); - $func(ecx, sp, mitem, item, push); + $func(ecx, sp, mitem, annotatable, push); } } env.insert(intern(concat!("derive_", $name)), - Decorator(Box::new(DeriveExtension))); + MultiDecorator(Box::new(DeriveExtension))); })+ env.insert(intern("derive"), - Modifier(Box::new(expand_derive))); + MultiModifier(Box::new(expand_derive))); } fn is_builtin_trait(name: &str) -> bool { diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index a972cfe1355..d218b8df153 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr}; +use ast::{MetaItem, Expr}; use ast; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -21,8 +21,8 @@ use ptr::P; pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 3ce1f6f12ce..5ace1b45b06 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -9,9 +9,9 @@ // except according to those terms. use ast; -use ast::{MetaItem, Item, Expr,}; +use ast::{MetaItem, Expr,}; use codemap::Span; -use ext::base::ExtCtxt; +use ext::base::{ExtCtxt, Annotatable}; use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; @@ -21,8 +21,8 @@ use ptr::P; pub fn expand_deriving_show(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P<Item>)) + item: Annotatable, + push: &mut FnMut(Annotatable)) { // &mut ::std::fmt::Formatter let fmtr = Ptr(Box::new(Literal(path_std!(cx, core::fmt::Formatter))), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 106d862042a..5033f406da0 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -477,59 +477,6 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander) .into_iter().map(|i| i.expect_item()).collect() } -#[allow(deprecated)] // This is needed because the `ItemModifier` trait is used -fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander) - -> P<ast::Item> { - // partition the attributes into ItemModifiers and others - let (modifiers, other_attrs) = modifiers(&it.attrs, fld); - - // update the attrs, leave everything else alone. Is this mutation really a good idea? - it = P(ast::Item { - attrs: other_attrs, - ..(*it).clone() - }); - - if modifiers.is_empty() { - let it = expand_item_multi_modifier(Annotatable::Item(it), fld); - return it.expect_item(); - } - - for attr in &modifiers { - let mname = attr.name(); - - match fld.cx.syntax_env.find(&intern(&mname)) { - Some(rc) => match *rc { - Modifier(ref mac) => { - attr::mark_used(attr); - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - name: mname.to_string(), - format: MacroAttribute, - span: None, - // attributes can do whatever they like, - // for now - allow_internal_unstable: true, - } - }); - it = mac.expand(fld.cx, attr.span, &*attr.node.value, it); - fld.cx.bt_pop(); - } - _ => unreachable!() - }, - _ => unreachable!() - } - } - - // Expansion may have added new ItemModifiers. - // It is possible, that an item modifier could expand to a multi-modifier or - // vice versa. In this case we will expand all modifiers before multi-modifiers, - // which might give an odd ordering. However, I think it is unlikely that the - // two kinds will be mixed, and I old-style multi-modifiers should be deprecated - // anyway. - expand_item_modifiers(it, fld) -} - /// Expand item_underscore fn expand_item_underscore(item: ast::Item_, fld: &mut MacroExpander) -> ast::Item_ { match item { @@ -1083,7 +1030,6 @@ impl<'a> Folder for PatIdentRenamer<'a> { } } -#[allow(deprecated)] // This is needed because the `Decorator` variant is used fn expand_annotatable(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> { @@ -1091,73 +1037,7 @@ fn expand_annotatable(a: Annotatable, let mut decorator_items = SmallVector::zero(); let mut new_attrs = Vec::new(); - for attr in a.attrs() { - let mname = attr.name(); - - match fld.cx.syntax_env.find(&intern(&mname)) { - Some(rc) => match *rc { - Decorator(ref dec) => { - let it = match a { - Annotatable::Item(ref it) => it, - // ItemDecorators are only implemented for Items. - _ => break, - }; - - attr::mark_used(attr); - - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - name: mname.to_string(), - format: MacroAttribute, - span: Some(attr.span), - // attributes can do whatever they like, - // for now. - allow_internal_unstable: true, - } - }); - - // we'd ideally decorator_items.push_all(expand_item(item, fld)), - // but that double-mut-borrows fld - let mut items: SmallVector<P<ast::Item>> = SmallVector::zero(); - dec.expand(fld.cx, attr.span, &*attr.node.value, &**it, - &mut |item| items.push(item)); - decorator_items.extend(items.into_iter() - .flat_map(|item| expand_item(item, fld).into_iter() - .map(|i| Annotatable::Item(i)))); - - fld.cx.bt_pop(); - } - MultiDecorator(ref dec) => { - attr::mark_used(attr); - - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - name: mname.to_string(), - format: MacroAttribute, - span: Some(attr.span), - // attributes can do whatever they like, - // for now. - allow_internal_unstable: true, - } - }); - - // we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)), - // but that double-mut-borrows fld - let mut anns: SmallVector<Annotatable> = SmallVector::zero(); - dec.expand(fld.cx, attr.span, &*attr.node.value, &a, - &mut |ann| anns.push(ann)); - decorator_items.extend(anns.into_iter() - .flat_map(|ann| expand_annotatable(ann, fld).into_iter())); - - fld.cx.bt_pop(); - } - _ => new_attrs.push((*attr).clone()), - }, - _ => new_attrs.push((*attr).clone()), - } - } + expand_decorators(a.clone(), fld, &mut decorator_items, &mut new_attrs); let mut new_items: SmallVector<Annotatable> = match a { Annotatable::Item(it) => match it.node { @@ -1215,34 +1095,101 @@ fn expand_annotatable(a: Annotatable, new_items } -// partition the attributes into ItemModifiers and others -fn modifiers(attrs: &Vec<ast::Attribute>, - fld: &MacroExpander) - -> (Vec<ast::Attribute>, Vec<ast::Attribute>) { - attrs.iter().cloned().partition(|attr| { - match fld.cx.syntax_env.find(&intern(&attr.name())) { - Some(rc) => match *rc { - Modifier(_) => true, - _ => false - }, - _ => false +// Partition a set of attributes into one kind of attribute, and other kinds. +macro_rules! partition { + ($fn_name: ident, $variant: ident) => { + #[allow(deprecated)] // The `allow` is needed because the `Modifier` variant might be used. + fn $fn_name(attrs: &[ast::Attribute], + fld: &MacroExpander) + -> (Vec<ast::Attribute>, Vec<ast::Attribute>) { + attrs.iter().cloned().partition(|attr| { + match fld.cx.syntax_env.find(&intern(&attr.name())) { + Some(rc) => match *rc { + $variant(..) => true, + _ => false + }, + _ => false + } + }) } - }) + } } -// partition the attributes into MultiModifiers and others -fn multi_modifiers(attrs: &[ast::Attribute], - fld: &MacroExpander) - -> (Vec<ast::Attribute>, Vec<ast::Attribute>) { - attrs.iter().cloned().partition(|attr| { - match fld.cx.syntax_env.find(&intern(&attr.name())) { +partition!(modifiers, Modifier); +partition!(multi_modifiers, MultiModifier); + + +#[allow(deprecated)] // The `allow` is needed because the `Decorator` variant is used. +fn expand_decorators(a: Annotatable, + fld: &mut MacroExpander, + decorator_items: &mut SmallVector<Annotatable>, + new_attrs: &mut Vec<ast::Attribute>) +{ + for attr in a.attrs() { + let mname = attr.name(); + match fld.cx.syntax_env.find(&intern(&mname)) { Some(rc) => match *rc { - MultiModifier(_) => true, - _ => false + Decorator(ref dec) => { + attr::mark_used(&attr); + + fld.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + name: mname.to_string(), + format: MacroAttribute, + span: Some(attr.span), + // attributes can do whatever they like, + // for now. + allow_internal_unstable: true, + } + }); + + // we'd ideally decorator_items.push_all(expand_item(item, fld)), + // but that double-mut-borrows fld + let mut items: SmallVector<Annotatable> = SmallVector::zero(); + dec.expand(fld.cx, + attr.span, + &attr.node.value, + &a.clone().expect_item(), + &mut |item| items.push(Annotatable::Item(item))); + decorator_items.extend(items.into_iter() + .flat_map(|ann| expand_annotatable(ann, fld).into_iter())); + + fld.cx.bt_pop(); + } + MultiDecorator(ref dec) => { + attr::mark_used(&attr); + + fld.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + name: mname.to_string(), + format: MacroAttribute, + span: Some(attr.span), + // attributes can do whatever they like, + // for now. + allow_internal_unstable: true, + } + }); + + // we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)), + // but that double-mut-borrows fld + let mut items: SmallVector<Annotatable> = SmallVector::zero(); + dec.expand(fld.cx, + attr.span, + &attr.node.value, + a.clone(), + &mut |ann| items.push(ann)); + decorator_items.extend(items.into_iter() + .flat_map(|ann| expand_annotatable(ann, fld).into_iter())); + + fld.cx.bt_pop(); + } + _ => new_attrs.push((*attr).clone()), }, - _ => false + _ => new_attrs.push((*attr).clone()), } - }) + } } fn expand_item_multi_modifier(mut it: Annotatable, @@ -1269,7 +1216,7 @@ fn expand_item_multi_modifier(mut it: Annotatable, callee: NameAndSpan { name: mname.to_string(), format: MacroAttribute, - span: None, + span: Some(attr.span), // attributes can do whatever they like, // for now allow_internal_unstable: true, @@ -1288,6 +1235,59 @@ fn expand_item_multi_modifier(mut it: Annotatable, expand_item_multi_modifier(it, fld) } +#[allow(deprecated)] // This is needed because the `ItemModifier` trait is used +fn expand_item_modifiers(mut it: P<ast::Item>, + fld: &mut MacroExpander) + -> P<ast::Item> { + // partition the attributes into ItemModifiers and others + let (modifiers, other_attrs) = modifiers(&it.attrs, fld); + + // update the attrs, leave everything else alone. Is this mutation really a good idea? + it = P(ast::Item { + attrs: other_attrs, + ..(*it).clone() + }); + + if modifiers.is_empty() { + let it = expand_item_multi_modifier(Annotatable::Item(it), fld); + return it.expect_item(); + } + + for attr in &modifiers { + let mname = attr.name(); + + match fld.cx.syntax_env.find(&intern(&mname)) { + Some(rc) => match *rc { + Modifier(ref mac) => { + attr::mark_used(attr); + fld.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + name: mname.to_string(), + format: MacroAttribute, + span: Some(attr.span), + // attributes can do whatever they like, + // for now + allow_internal_unstable: true, + } + }); + it = mac.expand(fld.cx, attr.span, &*attr.node.value, it); + fld.cx.bt_pop(); + } + _ => unreachable!() + }, + _ => unreachable!() + } + } + + // Expansion may have added new ItemModifiers. + // It is possible, that an item modifier could expand to a multi-modifier or + // vice versa. In this case we will expand all modifiers before multi-modifiers, + // which might give an odd ordering. However, I think it is unlikely that the + // two kinds will be mixed, and old-style multi-modifiers are deprecated. + expand_item_modifiers(it, fld) +} + fn expand_impl_item(ii: P<ast::ImplItem>, fld: &mut MacroExpander) -> SmallVector<P<ast::ImplItem>> { match ii.node { |
