diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-04-25 14:04:46 +1200 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-04-25 14:04:46 +1200 |
| commit | 0a62a05c6736dce542529cb1eb67fc54c0b70db4 (patch) | |
| tree | 5489a37f8b0991af0dce8bb1e6fb70474720d213 | |
| parent | f9e53c7f2c8285f3422ac7ac091349ce572c4baa (diff) | |
| parent | 143f2db3174103e459218958f567985b1f47944b (diff) | |
| download | rust-0a62a05c6736dce542529cb1eb67fc54c0b70db4.tar.gz rust-0a62a05c6736dce542529cb1eb67fc54c0b70db4.zip | |
Merge branch 'syntax' of https://github.com/aochagavia/rust into mulit-decor
Conflicts: src/librustc/plugin/registry.rs src/libsyntax/ext/base.rs src/libsyntax/ext/cfg_attr.rs src/libsyntax/ext/deriving/mod.rs src/libsyntax/ext/expand.rs src/libsyntax/print/pprust.rs src/test/auxiliary/macro_crate_test.rs
| -rw-r--r-- | src/librustc/plugin/registry.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 58 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/mod.rs | 20 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 32 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 1 | ||||
| -rw-r--r-- | src/test/auxiliary/macro_crate_test.rs | 83 | ||||
| -rw-r--r-- | src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs | 52 |
7 files changed, 239 insertions, 14 deletions
diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index 322b5d3a8cf..fccde9a2f17 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -14,8 +14,13 @@ use lint::{LintPassObject, LintId, Lint}; use session::Session; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT}; +<<<<<<< HEAD use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT}; use syntax::ext::base::MacroExpanderFn; +======= +use syntax::ext::base::{IdentTT, Decorator, MultiDecorator, Modifier, MultiModifier, MacroRulesTT}; +use syntax::ext::base::{MacroExpanderFn}; +>>>>>>> 143f2db3174103e459218958f567985b1f47944b use syntax::codemap::Span; use syntax::parse::token; use syntax::ptr::P; @@ -84,6 +89,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 +99,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 => { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 50ab430f148..f84d3ed98c7 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -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, @@ -127,6 +138,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. @@ -397,12 +431,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 @@ -473,6 +515,13 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>) syntax_expanders.insert(intern("log_syntax"), builtin_normal_expander( ext::log_syntax::expand_syntax_ext)); +<<<<<<< HEAD +======= + syntax_expanders.insert(intern("derive"), + MultiDecorator(box ext::deriving::expand_meta_derive)); + syntax_expanders.insert(intern("deriving"), + MultiDecorator(box ext::deriving::expand_deprecated_deriving)); +>>>>>>> 143f2db3174103e459218958f567985b1f47944b ext::deriving::register_all(&mut syntax_expanders); @@ -537,6 +586,11 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>) syntax_expanders.insert(intern("cfg"), builtin_normal_expander( ext::cfg::expand_cfg)); +<<<<<<< HEAD +======= + syntax_expanders.insert(intern("cfg_attr"), + MultiModifier(box ext::cfg_attr::expand)); +>>>>>>> 143f2db3174103e459218958f567985b1f47944b syntax_expanders.insert(intern("trace_macros"), builtin_normal_expander( ext::trace_macros::expand_trace_macros)); diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index a3725355840..586e73ad645 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -13,9 +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, MetaWord}; +use ast::{Item, MetaItem, MetaWord, MetaList, MetaNameValue}; use attr::AttrMetaMethods; -use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier}; +use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier, Annotatable}; use ext::build::AstBuilder; use feature_gate; use codemap::Span; @@ -78,9 +78,19 @@ pub mod ord; pub mod generic; fn expand_derive(cx: &mut ExtCtxt, - _: Span, + span: Span, mitem: &MetaItem, - item: P<Item>) -> P<Item> { + annotatable: &Annotatable) + -> P<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; + } + }; + item.map(|mut item| { if mitem.value_str().is_some() { cx.span_err(mitem.span, "unexpected value in `derive`"); @@ -113,7 +123,7 @@ fn expand_derive(cx: &mut ExtCtxt, intern_and_get_ident(&format!("derive_{}", tname))))); } - item + Annotatable::Item(item) }) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d1db956adb3..76a4ef2f4ed 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -477,6 +477,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 @@ -1082,6 +1083,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> { @@ -1120,9 +1122,31 @@ fn expand_annotatable(a: Annotatable, 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())); + 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.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, + &mut |ann| anns.push(ann)); + decorator_items.extend(anns.into_iter() + .flat_map(|ann| expand_annotatable(ann, fld).into_iter())); fld.cx.bt_pop(); } @@ -1184,7 +1208,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 } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5a57e09fcff..b56ecf7ae80 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -814,7 +814,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()); diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index 5b7e52e9164..07a18354c61 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -19,8 +19,7 @@ extern crate rustc; use syntax::ast::{self, TokenTree, Item, MetaItem}; 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; @@ -42,6 +41,9 @@ 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"), + MultiDecorator(box expand_duplicate)); } fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) @@ -104,6 +106,83 @@ 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, + mut push: Box<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.get()) + } 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) => { + match it { + ImplItem::MethodImplItem(m) => { + let mut new_m = (*m).clone(); + new_m.attrs.clear(); + replace_method_name(&mut new_m.node, copy_name); + push(Annotatable::ImplItem(ImplItem::MethodImplItem(P(new_m)))); + } + ImplItem::TypeImplItem(t) => { + let mut new_t = (*t).clone(); + new_t.attrs.clear(); + new_t.ident = copy_name; + push(Annotatable::ImplItem(ImplItem::TypeImplItem(P(new_t)))); + } + } + } + Annotatable::TraitItem(it) => { + match it { + TraitItem::RequiredMethod(rm) => { + let mut new_rm = rm.clone(); + new_rm.attrs.clear(); + new_rm.ident = copy_name; + push(Annotatable::TraitItem(TraitItem::RequiredMethod(new_rm))); + } + TraitItem::ProvidedMethod(pm) => { + let mut new_pm = (*pm).clone(); + new_pm.attrs.clear(); + replace_method_name(&mut new_pm.node, copy_name); + push(Annotatable::TraitItem(TraitItem::ProvidedMethod(P(new_pm)))); + } + TraitItem::TypeTraitItem(t) => { + let mut new_t = (*t).clone(); + new_t.attrs.clear(); + new_t.ty_param.ident = copy_name; + push(Annotatable::TraitItem(TraitItem::TypeTraitItem(P(new_t)))); + } + } + } + } + + fn replace_method_name(m: &mut ast::Method_, i: ast::Ident) { + if let &mut ast::Method_::MethDecl(ref mut ident, _, _, _, _, _, _, _) = m { + *ident = i + } + } +} + fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult+'static> { use syntax::ext::quote::rt::*; diff --git a/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs b/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs new file mode 100644 index 00000000000..45341d12d07 --- /dev/null +++ b/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs @@ -0,0 +1,52 @@ +// 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)] + +#[plugin] #[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 }; +} |
