Auto merge of #25024 - nrc:mulit-decor, r=sfackler
This commit is contained in:
commit
dd9dcc1e28
@ -14,8 +14,8 @@ use lint::{LintPassObject, LintId, Lint};
|
||||
use session::Session;
|
||||
|
||||
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
|
||||
use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
|
||||
use syntax::ext::base::MacroExpanderFn;
|
||||
use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MultiDecorator};
|
||||
use syntax::ext::base::{MacroExpanderFn, MacroRulesTT};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
@ -84,6 +84,7 @@ impl<'a> Registry<'a> {
|
||||
/// Register a syntax extension of any kind.
|
||||
///
|
||||
/// This is the most general hook into `libsyntax`'s expansion behavior.
|
||||
#[allow(deprecated)]
|
||||
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
|
||||
self.syntax_exts.push((name, match extension {
|
||||
NormalTT(ext, _, allow_internal_unstable) => {
|
||||
@ -93,6 +94,7 @@ impl<'a> Registry<'a> {
|
||||
IdentTT(ext, Some(self.krate_span), allow_internal_unstable)
|
||||
}
|
||||
Decorator(ext) => Decorator(ext),
|
||||
MultiDecorator(ext) => MultiDecorator(ext),
|
||||
Modifier(ext) => Modifier(ext),
|
||||
MultiModifier(ext) => MultiModifier(ext),
|
||||
MacroRulesTT => {
|
||||
|
@ -30,6 +30,8 @@ use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::default::Default;
|
||||
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
|
||||
pub trait ItemDecorator {
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
@ -39,6 +41,9 @@ pub trait ItemDecorator {
|
||||
push: &mut FnMut(P<ast::Item>));
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
|
||||
impl<F> ItemDecorator for F
|
||||
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, &mut FnMut(P<ast::Item>))
|
||||
{
|
||||
@ -52,6 +57,8 @@ impl<F> ItemDecorator for F
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
|
||||
pub trait ItemModifier {
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
@ -61,9 +68,13 @@ pub trait ItemModifier {
|
||||
-> P<ast::Item>;
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
|
||||
impl<F> ItemModifier for F
|
||||
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P<ast::Item>) -> P<ast::Item>
|
||||
{
|
||||
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
@ -112,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,
|
||||
@ -127,6 +148,29 @@ impl Annotatable {
|
||||
}
|
||||
}
|
||||
|
||||
// A more flexible ItemDecorator.
|
||||
pub trait MultiItemDecorator {
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
meta_item: &ast::MetaItem,
|
||||
item: Annotatable,
|
||||
push: &mut FnMut(Annotatable));
|
||||
}
|
||||
|
||||
impl<F> MultiItemDecorator for F
|
||||
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,
|
||||
push: &mut FnMut(Annotatable)) {
|
||||
(*self)(ecx, sp, meta_item, item, push)
|
||||
}
|
||||
}
|
||||
|
||||
// A more flexible ItemModifier (ItemModifier should go away, eventually, FIXME).
|
||||
// meta_item is the annotation, item is the item being modified, parent_item
|
||||
// is the impl or trait item is declared in if item is part of such a thing.
|
||||
@ -397,12 +441,22 @@ impl MacResult for DummyResult {
|
||||
pub enum SyntaxExtension {
|
||||
/// A syntax extension that is attached to an item and creates new items
|
||||
/// based upon it.
|
||||
///
|
||||
/// `#[derive(...)]` is an `ItemDecorator`.
|
||||
#[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
|
||||
/// based upon it.
|
||||
///
|
||||
/// `#[derive(...)]` is a `MultiItemDecorator`.
|
||||
MultiDecorator(Box<MultiItemDecorator + 'static>),
|
||||
|
||||
/// A syntax extension that is attached to an item and modifies it
|
||||
/// 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
|
||||
|
@ -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" },
|
||||
@ -46,5 +45,5 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
trait_def.expand(cx, mitem, &item, push);
|
||||
}
|
||||
|
@ -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));
|
||||
@ -47,7 +47,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
fn cs_clone(
|
||||
|
@ -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(
|
||||
@ -66,5 +66,5 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
||||
),
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
@ -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));
|
||||
@ -48,7 +48,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
@ -90,5 +90,5 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
|
||||
),
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
@ -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) => { {
|
||||
@ -80,7 +80,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
|
||||
],
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -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 {
|
||||
@ -87,7 +87,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
|
||||
|
@ -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));
|
||||
@ -46,7 +46,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
|
||||
),
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
|
||||
|
@ -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 {
|
||||
@ -163,7 +163,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
|
||||
|
@ -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;
|
||||
@ -380,41 +380,49 @@ impl<'a> TraitDef<'a> {
|
||||
pub fn expand(&self,
|
||||
cx: &mut ExtCtxt,
|
||||
mitem: &ast::MetaItem,
|
||||
item: &'a ast::Item,
|
||||
push: &mut FnMut(P<ast::Item>))
|
||||
item: &'a 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(ref 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,
|
||||
}
|
||||
}).cloned());
|
||||
push(P(ast::Item {
|
||||
attrs: attrs,
|
||||
..(*newitem).clone()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Given that we are deriving a trait `DerivedTrait` for a type like:
|
||||
|
@ -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,
|
||||
@ -52,7 +52,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
||||
hash_trait_def.expand(cx, mitem, item, push);
|
||||
hash_trait_def.expand(cx, mitem, &item, push);
|
||||
}
|
||||
|
||||
fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
|
||||
|
@ -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};
|
||||
use ast::{MetaItem, MetaWord};
|
||||
use attr::AttrMetaMethods;
|
||||
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier};
|
||||
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)::+) => (
|
||||
@ -78,42 +77,48 @@ pub mod ord;
|
||||
pub mod generic;
|
||||
|
||||
fn expand_derive(cx: &mut ExtCtxt,
|
||||
_: Span,
|
||||
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`");
|
||||
}
|
||||
|
||||
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");
|
||||
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;
|
||||
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`");
|
||||
}
|
||||
|
||||
// #[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)))));
|
||||
}
|
||||
let traits = mitem.meta_item_list().unwrap_or(&[]);
|
||||
if traits.is_empty() {
|
||||
cx.span_warn(mitem.span, "empty trait list in `derive`");
|
||||
}
|
||||
|
||||
item
|
||||
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;
|
||||
}
|
||||
|
||||
// #[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
|
||||
})
|
||||
}, |a| {
|
||||
cx.span_err(span, "`derive` can only be applied to items");
|
||||
a
|
||||
})
|
||||
}
|
||||
|
||||
@ -124,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 {
|
||||
|
@ -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));
|
||||
@ -67,7 +67,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
|
||||
|
@ -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))),
|
||||
@ -49,7 +49,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
|
||||
],
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
/// We use the debug builders to do the heavy lifting here
|
||||
|
@ -477,58 +477,6 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
|
||||
.into_iter().map(|i| i.expect_item()).collect()
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -1090,48 +1038,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()));
|
||||
|
||||
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 {
|
||||
@ -1185,38 +1092,105 @@ fn expand_annotatable(a: Annotatable,
|
||||
}
|
||||
};
|
||||
|
||||
new_items.push_all(decorator_items.into_iter().map(|i| Annotatable::Item(i)).collect());
|
||||
new_items.push_all(decorator_items);
|
||||
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,
|
||||
@ -1243,7 +1217,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,
|
||||
@ -1262,6 +1236,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 {
|
||||
|
@ -799,7 +799,6 @@ impl<'a> State<'a> {
|
||||
word(&mut self.s, ";")
|
||||
}
|
||||
|
||||
|
||||
/// Pretty-print an item
|
||||
pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
|
||||
try!(self.hardbreak_if_not_bol());
|
||||
|
@ -19,7 +19,7 @@ extern crate rustc;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ext::base::{Decorator, ExtCtxt};
|
||||
use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
|
||||
use syntax::ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
|
||||
@ -31,14 +31,14 @@ use rustc::plugin::Registry;
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_syntax_extension(
|
||||
token::intern("derive_TotalSum"),
|
||||
Decorator(box expand));
|
||||
MultiDecorator(box expand));
|
||||
}
|
||||
|
||||
fn expand(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: &ast::MetaItem,
|
||||
item: &ast::Item,
|
||||
push: &mut FnMut(P<ast::Item>)) {
|
||||
item: Annotatable,
|
||||
push: &mut FnMut(Annotatable)) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
attributes: vec![],
|
||||
@ -70,5 +70,5 @@ fn expand(cx: &mut ExtCtxt,
|
||||
],
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ extern crate rustc;
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ext::base::{Decorator, ExtCtxt};
|
||||
use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
|
||||
use syntax::ext::deriving::generic::{Substructure, Struct, EnumMatching};
|
||||
@ -33,14 +33,14 @@ use rustc::plugin::Registry;
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_syntax_extension(
|
||||
token::intern("derive_TotalSum"),
|
||||
Decorator(box expand));
|
||||
MultiDecorator(box expand));
|
||||
}
|
||||
|
||||
fn expand(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: &ast::MetaItem,
|
||||
item: &ast::Item,
|
||||
push: &mut FnMut(P<ast::Item>)) {
|
||||
item: Annotatable,
|
||||
push: &mut FnMut(Annotatable)) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
attributes: vec![],
|
||||
@ -61,7 +61,7 @@ fn expand(cx: &mut ExtCtxt,
|
||||
],
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
trait_def.expand(cx, mitem, &item, push)
|
||||
}
|
||||
|
||||
// Mostly copied from syntax::ext::deriving::hash
|
||||
|
@ -10,23 +10,20 @@
|
||||
|
||||
// force-host
|
||||
|
||||
#![feature(plugin_registrar, quote)]
|
||||
#![feature(box_syntax, rustc_private)]
|
||||
#![feature(plugin_registrar, quote, rustc_private)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate rustc;
|
||||
|
||||
use syntax::ast::{self, TokenTree, Item, MetaItem};
|
||||
use syntax::ast::{self, TokenTree, Item, MetaItem, ImplItem, TraitItem};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ext::base::*;
|
||||
use syntax::parse::token;
|
||||
use syntax::parse;
|
||||
use syntax::parse::{self, token};
|
||||
use syntax::ptr::P;
|
||||
use rustc::plugin::Registry;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! exported_macro { () => (2) }
|
||||
|
||||
macro_rules! unexported_macro { () => (3) }
|
||||
|
||||
#[plugin_registrar]
|
||||
@ -41,6 +38,10 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||
token::intern("into_multi_foo"),
|
||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
||||
MultiModifier(Box::new(expand_into_foo_multi)));
|
||||
reg.register_syntax_extension(
|
||||
token::intern("duplicate"),
|
||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
||||
MultiDecorator(Box::new(expand_duplicate)));
|
||||
}
|
||||
|
||||
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
||||
@ -103,4 +104,49 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
// Create a duplicate of the annotatable, based on the MetaItem
|
||||
fn expand_duplicate(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
mi: &MetaItem,
|
||||
it: Annotatable,
|
||||
push: &mut FnMut(Annotatable))
|
||||
{
|
||||
let copy_name = match mi.node {
|
||||
ast::MetaItem_::MetaList(_, ref xs) => {
|
||||
if let ast::MetaItem_::MetaWord(ref w) = xs[0].node {
|
||||
token::str_to_ident(&w)
|
||||
} else {
|
||||
cx.span_err(mi.span, "Expected word");
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
cx.span_err(mi.span, "Expected list");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Duplicate the item but replace its ident by the MetaItem
|
||||
match it.clone() {
|
||||
Annotatable::Item(it) => {
|
||||
let mut new_it = (*it).clone();
|
||||
new_it.attrs.clear();
|
||||
new_it.ident = copy_name;
|
||||
push(Annotatable::Item(P(new_it)));
|
||||
}
|
||||
Annotatable::ImplItem(it) => {
|
||||
let mut new_it = (*it).clone();
|
||||
new_it.attrs.clear();
|
||||
new_it.ident = copy_name;
|
||||
push(Annotatable::ImplItem(P(new_it)));
|
||||
}
|
||||
Annotatable::TraitItem(tt) => {
|
||||
let mut new_it = (*tt).clone();
|
||||
new_it.attrs.clear();
|
||||
new_it.ident = copy_name;
|
||||
push(Annotatable::TraitItem(P(new_it)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn foo() {}
|
||||
|
55
src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs
Normal file
55
src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(plugin, custom_attribute)]
|
||||
#![plugin(macro_crate_test)]
|
||||
|
||||
#[macro_use]
|
||||
#[no_link]
|
||||
extern crate macro_crate_test;
|
||||
|
||||
// The duplicate macro will create a copy of the item with the given identifier.
|
||||
|
||||
#[duplicate(MyCopy)]
|
||||
struct MyStruct {
|
||||
number: i32
|
||||
}
|
||||
|
||||
trait TestTrait {
|
||||
#[duplicate(TestType2)]
|
||||
type TestType;
|
||||
|
||||
#[duplicate(required_fn2)]
|
||||
fn required_fn(&self);
|
||||
|
||||
#[duplicate(provided_fn2)]
|
||||
fn provided_fn(&self) { }
|
||||
}
|
||||
|
||||
impl TestTrait for MyStruct {
|
||||
#[duplicate(TestType2)]
|
||||
type TestType = f64;
|
||||
|
||||
#[duplicate(required_fn2)]
|
||||
fn required_fn(&self) { }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = MyStruct { number: 42 };
|
||||
s.required_fn();
|
||||
s.required_fn2();
|
||||
s.provided_fn();
|
||||
s.provided_fn2();
|
||||
|
||||
let s = MyCopy { number: 42 };
|
||||
}
|
Loading…
Reference in New Issue
Block a user