Skip to content
4 changes: 3 additions & 1 deletion src/librustc/plugin/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ 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::{IdentTT, Decorator, MultiDecorator, Modifier, MultiModifier, MacroRulesTT};
use syntax::ext::base::{MacroExpanderFn};
use syntax::codemap::Span;
use syntax::parse::token;
Expand Down Expand Up @@ -76,11 +76,13 @@ 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, _) => NormalTT(ext, Some(self.krate_span)),
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
Decorator(ext) => Decorator(ext),
MultiDecorator(ext) => MultiDecorator(ext),
Modifier(ext) => Modifier(ext),
MultiModifier(ext) => MultiModifier(ext),
MacroRulesTT => {
Expand Down
52 changes: 47 additions & 5 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ use fold::Folder;
use std::collections::HashMap;
use std::rc::Rc;

#[unstable(feature = "rustc_private")]
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
pub trait ItemDecorator {
fn expand(&self,
ecx: &mut ExtCtxt,
Expand All @@ -38,6 +40,9 @@ pub trait ItemDecorator {
push: Box<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, Box<FnMut(P<ast::Item>)>)
{
Expand All @@ -51,6 +56,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,
Expand All @@ -60,9 +67,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,
Expand Down Expand Up @@ -146,6 +157,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: Box<FnMut(Annotatable)>);
}

impl<F> MultiItemDecorator for F
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, Box<FnMut(Annotatable)>)
{
fn expand(&self,
ecx: &mut ExtCtxt,
sp: Span,
meta_item: &ast::MetaItem,
item: &Annotatable,
push: Box<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.
Expand Down Expand Up @@ -393,12 +427,20 @@ 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")]
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")]
Modifier(Box<ItemModifier + 'static>),

/// A syntax extension that is attached to an item and modifies it
Expand Down Expand Up @@ -466,9 +508,9 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
builtin_normal_expander(
ext::log_syntax::expand_syntax_ext));
syntax_expanders.insert(intern("derive"),
Decorator(box ext::deriving::expand_meta_derive));
MultiDecorator(box ext::deriving::expand_meta_derive));
syntax_expanders.insert(intern("deriving"),
Decorator(box ext::deriving::expand_deprecated_deriving));
MultiDecorator(box ext::deriving::expand_deprecated_deriving));

if ecfg.enable_quotes {
// Quasi-quoting expanders
Expand Down Expand Up @@ -529,7 +571,7 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
builtin_normal_expander(
ext::cfg::expand_cfg));
syntax_expanders.insert(intern("cfg_attr"),
Modifier(box ext::cfg_attr::expand));
MultiModifier(box ext::cfg_attr::expand));
syntax_expanders.insert(intern("trace_macros"),
builtin_normal_expander(
ext::trace_macros::expand_trace_macros));
Expand Down
61 changes: 52 additions & 9 deletions src/libsyntax/ext/cfg_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,70 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast;
use ast::{self, TraitItem, ImplItem};
use attr;
use codemap::Span;
use ext::base::ExtCtxt;
use ext::base::{Annotatable, ExtCtxt};
use ext::build::AstBuilder;
use ptr::P;

pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P<ast::Item>) -> P<ast::Item> {
macro_rules! fold_annotatable {
($ann:expr, $item:ident => $oper:expr) => (
match $ann {
Annotatable::Item(it) => {
let mut $item = (*it).clone();
$oper;
Annotatable::Item(P($item))
}
Annotatable::TraitItem(it) => {
match it {
TraitItem::RequiredMethod(mut $item) => {
$oper;
Annotatable::TraitItem(TraitItem::RequiredMethod($item))
}
TraitItem::ProvidedMethod(pm) => {
let mut $item = (*pm).clone();
$oper;
Annotatable::TraitItem(TraitItem::ProvidedMethod(P($item)))
}
TraitItem::TypeTraitItem(at) => {
let mut $item = (*at).clone();
$oper;
Annotatable::TraitItem(TraitItem::TypeTraitItem(P($item)))
}
}
}
Annotatable::ImplItem(it) => {
match it {
ImplItem::MethodImplItem(pm) => {
let mut $item = (*pm).clone();
$oper;
Annotatable::ImplItem(ImplItem::MethodImplItem(P($item)))
}
ImplItem::TypeImplItem(at) => {
let mut $item = (*at).clone();
$oper;
Annotatable::ImplItem(ImplItem::TypeImplItem(P($item)))
}
}
}
}
);
}

pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, ann: Annotatable) -> Annotatable {
let (cfg, attr) = match mi.node {
ast::MetaList(_, ref mis) if mis.len() == 2 => (&mis[0], &mis[1]),
_ => {
cx.span_err(sp, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
return it;
return ann;
}
};

let mut out = (*it).clone();
if attr::cfg_matches(&cx.parse_sess.span_diagnostic, cx.cfg.as_slice(), &**cfg) {
out.attrs.push(cx.attribute(attr.span, attr.clone()));
let attr = cx.attribute(attr.span, attr.clone());
fold_annotatable!(ann, item => item.attrs.push(attr))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nick29581 Is this implementation of the fold_annotatable macro OK?

} else {
ann
}

P(out)
}

29 changes: 19 additions & 10 deletions src/libsyntax/ext/deriving/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@
//! 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, MetaList, MetaNameValue, MetaWord};
use ext::base::ExtCtxt;
use ast::{MetaItem, MetaList, MetaNameValue, MetaWord};
use ext::base::{Annotatable, ExtCtxt};
use codemap::Span;
use ptr::P;

pub mod bounds;
pub mod clone;
Expand All @@ -43,16 +42,26 @@ pub mod generic;
pub fn expand_deprecated_deriving(cx: &mut ExtCtxt,
span: Span,
_: &MetaItem,
_: &Item,
_: Box<FnMut(P<Item>)>) {
_: &Annotatable,
_: Box<FnMut(Annotatable)>) {
cx.span_err(span, "`deriving` has been renamed to `derive`");
}

pub fn expand_meta_derive(cx: &mut ExtCtxt,
_span: Span,
span: Span,
mitem: &MetaItem,
item: &Item,
mut push: Box<FnMut(P<Item>)>) {
annotatable: &Annotatable,
mut push: Box<FnMut(Annotatable)>)
{
// Derive can only be applied to items
let item = match annotatable {
&Annotatable::Item(ref it) => it.clone(),
_ => {
cx.span_err(span, "`derive` can only be applied to items");
return;
}
};

match mitem.node {
MetaNameValue(_, ref l) => {
cx.span_err(l.span, "unexpected value in `derive`");
Expand All @@ -70,8 +79,8 @@ pub fn expand_meta_derive(cx: &mut ExtCtxt,
MetaList(ref tname, _) |
MetaWord(ref tname) => {
macro_rules! expand {
($func:path) => ($func(cx, titem.span, &**titem, item,
|i| push(i)))
($func:path) => ($func(cx, titem.span, &**titem,
&*item, |i| push(Annotatable::Item(i))))
}

match tname.get() {
Expand Down
29 changes: 27 additions & 2 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ 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
Expand Down Expand Up @@ -1056,6 +1057,7 @@ 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> {
Expand Down Expand Up @@ -1092,7 +1094,30 @@ fn expand_annotatable(a: Annotatable,
dec.expand(fld.cx, attr.span, &*attr.node.value, &**it,
box |&mut: item| items.push(item));
decorator_items.extend(items.into_iter()
.flat_map(|item| expand_item(item, fld).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.get().to_string(),
format: MacroAttribute,
span: None
}
});

// 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,
box |&mut: ann| anns.push(ann));
decorator_items.extend(anns.into_iter()
.flat_map(|ann| expand_annotatable(ann, fld).into_iter()));

fld.cx.bt_pop();
}
Expand Down Expand Up @@ -1157,7 +1182,7 @@ 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
}

Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ impl<'a> State<'a> {
}

fn print_typedef(&mut self, typedef: &ast::Typedef) -> IoResult<()> {
try!(self.print_outer_attributes(&typedef.attrs[]));
try!(self.word_space("type"));
try!(self.print_ident(typedef.ident));
try!(space(&mut self.s));
Expand Down
Loading