Skip to content

Deprecate ItemModifier and ItemDecorator traits #21265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
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