From 53579e6d866eea41f2d3d8d0ddff42c73e75cea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Fri, 16 Jan 2015 22:47:05 +0100 Subject: [PATCH 01/15] Deprecate ItemModifier in favor of MultiItemModifier [breaking-change] --- src/libsyntax/ext/base.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a184cc5c2b296..b5bfd2dce80bb 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -51,6 +51,7 @@ impl ItemDecorator for F } } +#[deprecated="Replaced by MultiItemModifier"] pub trait ItemModifier { fn expand(&self, ecx: &mut ExtCtxt, @@ -60,9 +61,11 @@ pub trait ItemModifier { -> P; } +#[deprecated="Replaced by MultiItemModifier"] impl ItemModifier for F where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P) -> P { + fn expand(&self, ecx: &mut ExtCtxt, span: Span, From 57690399a2ab6dd579ea1f97e9866b213f8b14d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Fri, 16 Jan 2015 22:51:03 +0100 Subject: [PATCH 02/15] Deprecate ItemDecorator in favor of MultiItemDecorator [breaking-change] --- src/libsyntax/ext/base.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b5bfd2dce80bb..666e69c205955 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -29,6 +29,7 @@ use fold::Folder; use std::collections::HashMap; use std::rc::Rc; +#[deprecated="Replaced by MultiItemDecorator"] pub trait ItemDecorator { fn expand(&self, ecx: &mut ExtCtxt, From 77d59217a38e2982fdcf6bff800f1c9acc0d9aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Fri, 16 Jan 2015 22:59:41 +0100 Subject: [PATCH 03/15] Add MultiItemDecorator --- src/libsyntax/ext/base.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 666e69c205955..edd66b5028620 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -150,6 +150,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)>); +} + +impl MultiItemDecorator for F + where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, Box)>) +{ + fn expand(&self, + ecx: &mut ExtCtxt, + sp: Span, + meta_item: &ast::MetaItem, + item: &Annotatable, + push: Box)>) { + (*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. From f97cff9abd4ea7a7a8ac24bb9afb09eb271bcda9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Fri, 16 Jan 2015 23:04:55 +0100 Subject: [PATCH 04/15] Add MultiDecorator variant to SyntaxExtension enum --- src/libsyntax/ext/base.rs | 6 +++++- src/libsyntax/ext/expand.rs | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index edd66b5028620..7d802d953b35e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -418,11 +418,15 @@ impl MacResult for DummyResult { /// An enum representing the different kinds of syntax extensions. pub enum SyntaxExtension { + /// A syntax extension that is attached to an item and creates new items + /// based upon it. + Decorator(Box), + /// A syntax extension that is attached to an item and creates new items /// based upon it. /// /// `#[derive(...)]` is an `ItemDecorator`. - Decorator(Box), + MultiDecorator(Box), /// A syntax extension that is attached to an item and modifies it /// in-place. diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5736400313e95..dbbcee0d9d826 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1096,6 +1096,28 @@ fn expand_annotatable(a: Annotatable, 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_item(item, fld)), + // but that double-mut-borrows fld + let mut items: SmallVector> = SmallVector::zero(); + dec.expand(fld.cx, attr.span, &*attr.node.value, a, + box |&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()), From 6f233aaa0c743cc6ca7e42d7dcd4b7d92ef4ad9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Fri, 16 Jan 2015 23:05:24 +0100 Subject: [PATCH 05/15] Deprecate SyntaxExtension::Decorator It has been replaced by SyntaxExtension::MultiDecorator [breaking-change] --- src/libsyntax/ext/base.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7d802d953b35e..b63678881f6cb 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -420,6 +420,7 @@ impl MacResult for DummyResult { pub enum SyntaxExtension { /// A syntax extension that is attached to an item and creates new items /// based upon it. + #[deprecated="Replaced by MultiDecorator"] Decorator(Box), /// A syntax extension that is attached to an item and creates new items From 2e07b0d6be3d2ffcfb154b5cbbe02bc166014172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Fri, 16 Jan 2015 23:07:49 +0100 Subject: [PATCH 06/15] Deprecate SyntaxExtension::Modifier Replaced by SyntaxExtension::MultiModifier [breaking-change] --- src/libsyntax/ext/base.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b63678881f6cb..d3cedee6d21b9 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -431,6 +431,7 @@ pub enum SyntaxExtension { /// A syntax extension that is attached to an item and modifies it /// in-place. + #[deprecated="Replaced by MultiModifier"] Modifier(Box), /// A syntax extension that is attached to an item and modifies it From 01172eedfab32b24e38aa86ba0cba24453e842fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Tue, 20 Jan 2015 20:10:55 +0100 Subject: [PATCH 07/15] Add tests for MultiItemDecorator --- src/test/auxiliary/macro_crate_test.rs | 85 ++++++++++++++++++- .../macro-crate-multi-decorator.rs | 52 ++++++++++++ 2 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index d545a42ae1927..d3c9659a1f170 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -16,11 +16,10 @@ extern crate syntax; extern crate rustc; -use syntax::ast::{TokenTree, Item, MetaItem, ImplItem, TraitItem, Method}; +use syntax::ast::{self, TokenTree, Item, MetaItem, ImplItem, TraitItem, Method}; 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; @@ -40,6 +39,9 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_syntax_extension( token::intern("into_multi_foo"), MultiModifier(box 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]) @@ -92,6 +94,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) +{ + 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 { 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 0000000000000..45341d12d0743 --- /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 or the MIT license +// , 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 }; +} From aa3fe205223936e37c0accd91473fa3d666451ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Tue, 20 Jan 2015 20:28:36 +0100 Subject: [PATCH 08/15] Replace uses of Decorator and Modifier --- src/librustc/plugin/registry.rs | 4 +- src/libsyntax/ext/base.rs | 15 +++++--- src/libsyntax/ext/cfg_attr.rs | 61 ++++++++++++++++++++++++++----- src/libsyntax/ext/deriving/mod.rs | 25 +++++++++---- src/libsyntax/ext/expand.rs | 19 ++++++---- 5 files changed, 92 insertions(+), 32 deletions(-) diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index f6fb1c2d41928..98f1f73b563bf 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -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; @@ -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 => { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index d3cedee6d21b9..cf0df37ede841 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -39,6 +39,8 @@ pub trait ItemDecorator { push: Box)>); } +#[allow(deprecated)] +#[deprecated="Replaced by MultiItemDecorator"] impl ItemDecorator for F where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, Box)>) { @@ -62,6 +64,7 @@ pub trait ItemModifier { -> P; } +#[allow(deprecated)] #[deprecated="Replaced by MultiItemModifier"] impl ItemModifier for F where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P) -> P @@ -157,18 +160,18 @@ pub trait MultiItemDecorator { sp: Span, meta_item: &ast::MetaItem, item: &Annotatable, - push: Box)>); + push: Box); } impl MultiItemDecorator for F - where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, Box)>) + where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, Box) { fn expand(&self, ecx: &mut ExtCtxt, sp: Span, meta_item: &ast::MetaItem, item: &Annotatable, - push: Box)>) { + push: Box) { (*self)(ecx, sp, meta_item, item, push) } } @@ -426,7 +429,7 @@ pub enum SyntaxExtension { /// A syntax extension that is attached to an item and creates new items /// based upon it. /// - /// `#[derive(...)]` is an `ItemDecorator`. + /// `#[derive(...)]` is a `MultiItemDecorator`. MultiDecorator(Box), /// A syntax extension that is attached to an item and modifies it @@ -499,7 +502,7 @@ 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)); @@ -562,7 +565,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)); diff --git a/src/libsyntax/ext/cfg_attr.rs b/src/libsyntax/ext/cfg_attr.rs index a85f12edb2286..d282c3084deac 100644 --- a/src/libsyntax/ext/cfg_attr.rs +++ b/src/libsyntax/ext/cfg_attr.rs @@ -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) -> P { +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(, )]`"); - 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)) + } else { + ann } - - P(out) } - diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index d3d7fee3a189a..a06ed638fe14d 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -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; @@ -49,10 +48,20 @@ pub fn expand_deprecated_deriving(cx: &mut ExtCtxt, } pub fn expand_meta_derive(cx: &mut ExtCtxt, - _span: Span, + span: Span, mitem: &MetaItem, - item: &Item, - mut push: Box)>) { + annotatable: &Annotatable, + mut push: Box) +{ + // 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`"); @@ -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() { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index dbbcee0d9d826..672acfbff6589 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -488,6 +488,7 @@ pub fn expand_item(it: P, 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, fld: &mut MacroExpander) -> P { // partition the attributes into ItemModifiers and others @@ -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 { @@ -1092,7 +1094,8 @@ 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(); } @@ -1108,13 +1111,13 @@ fn expand_annotatable(a: Annotatable, } }); - // we'd ideally decorator_items.push_all(expand_item(item, fld)), + // we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)), // but that double-mut-borrows fld - let mut items: SmallVector> = SmallVector::zero(); - dec.expand(fld.cx, attr.span, &*attr.node.value, a, - box |&mut: item| items.push(item)); - decorator_items.extend(items.into_iter() - .flat_map(|item| expand_item(item, fld).into_iter())); + let mut anns: SmallVector = 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(); } @@ -1179,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 } From 5af4df4a264ea3409189a3b64c12fcf6b6eee2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Fri, 23 Jan 2015 10:15:56 +0100 Subject: [PATCH 09/15] Fix pretty printer --- src/libsyntax/print/pprust.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5367ccc1357c9..f5ecadffeded6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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)); From 143f2db3174103e459218958f567985b1f47944b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Sat, 31 Jan 2015 11:38:29 +0100 Subject: [PATCH 10/15] Fix rebase issues --- src/libsyntax/ext/base.rs | 20 +++++++++++++------- src/libsyntax/ext/deriving/mod.rs | 4 ++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index cf0df37ede841..22477783692f2 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -29,7 +29,8 @@ use fold::Folder; use std::collections::HashMap; use std::rc::Rc; -#[deprecated="Replaced by MultiItemDecorator"] +#[unstable(feature = "rustc_private")] +#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")] pub trait ItemDecorator { fn expand(&self, ecx: &mut ExtCtxt, @@ -40,7 +41,8 @@ pub trait ItemDecorator { } #[allow(deprecated)] -#[deprecated="Replaced by MultiItemDecorator"] +#[unstable(feature = "rustc_private")] +#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")] impl ItemDecorator for F where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, Box)>) { @@ -54,7 +56,8 @@ impl ItemDecorator for F } } -#[deprecated="Replaced by MultiItemModifier"] +#[unstable(feature = "rustc_private")] +#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")] pub trait ItemModifier { fn expand(&self, ecx: &mut ExtCtxt, @@ -65,7 +68,8 @@ pub trait ItemModifier { } #[allow(deprecated)] -#[deprecated="Replaced by MultiItemModifier"] +#[unstable(feature = "rustc_private")] +#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")] impl ItemModifier for F where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P) -> P { @@ -423,7 +427,8 @@ impl MacResult for DummyResult { pub enum SyntaxExtension { /// A syntax extension that is attached to an item and creates new items /// based upon it. - #[deprecated="Replaced by MultiDecorator"] + #[unstable(feature = "rustc_private")] + #[deprecated(since = "1.0.0", reason = "replaced by MultiDecorator")] Decorator(Box), /// A syntax extension that is attached to an item and creates new items @@ -434,7 +439,8 @@ pub enum SyntaxExtension { /// A syntax extension that is attached to an item and modifies it /// in-place. - #[deprecated="Replaced by MultiModifier"] + #[unstable(feature = "rustc_private")] + #[deprecated(since = "1.0.0", reason = "replaced by MultiModifier")] Modifier(Box), /// A syntax extension that is attached to an item and modifies it @@ -504,7 +510,7 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv { syntax_expanders.insert(intern("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 diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index a06ed638fe14d..12132adb80e3d 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -42,8 +42,8 @@ pub mod generic; pub fn expand_deprecated_deriving(cx: &mut ExtCtxt, span: Span, _: &MetaItem, - _: &Item, - _: Box)>) { + _: &Annotatable, + _: Box) { cx.span_err(span, "`deriving` has been renamed to `derive`"); } From 0a4f9a26962d85d57a0b603ad324bd86fdd474cf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 25 Apr 2015 15:31:11 +1200 Subject: [PATCH 11/15] Rebasing and making MulitDecorators work --- src/librustc/plugin/registry.rs | 9 ++------- src/libsyntax/ext/base.rs | 18 +++--------------- src/libsyntax/ext/deriving/mod.rs | 15 +++------------ src/libsyntax/ext/expand.rs | 7 +++++-- 4 files changed, 13 insertions(+), 36 deletions(-) diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index fccde9a2f1788..04df464129541 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -14,13 +14,8 @@ 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::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; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index f84d3ed98c767..3e54e43c02961 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -145,18 +145,18 @@ pub trait MultiItemDecorator { sp: Span, meta_item: &ast::MetaItem, item: &Annotatable, - push: Box); + push: &mut FnMut(Annotatable)); } impl MultiItemDecorator for F - where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, Box) + 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: Box) { + push: &mut FnMut(Annotatable)) { (*self)(ecx, sp, meta_item, item, push) } } @@ -515,13 +515,6 @@ 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); @@ -586,11 +579,6 @@ 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 586e73ad64554..bc4a7f90911dc 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -80,17 +80,8 @@ pub mod generic; fn expand_derive(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, - annotatable: &Annotatable) - -> P { - // 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: P) + -> P { item.map(|mut item| { if mitem.value_str().is_some() { cx.span_err(mitem.span, "unexpected value in `derive`"); @@ -123,7 +114,7 @@ fn expand_derive(cx: &mut ExtCtxt, intern_and_get_ident(&format!("derive_{}", tname))))); } - Annotatable::Item(item) + item }) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 76a4ef2f4ed72..106d862042a90 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1134,9 +1134,12 @@ fn expand_annotatable(a: Annotatable, fld.cx.bt_push(ExpnInfo { call_site: attr.span, callee: NameAndSpan { - name: mname.get().to_string(), + name: mname.to_string(), format: MacroAttribute, - span: None + span: Some(attr.span), + // attributes can do whatever they like, + // for now. + allow_internal_unstable: true, } }); From c0a42aecbc85298fb6351253c4cd1824567b7a42 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Apr 2015 17:34:39 +1200 Subject: [PATCH 12/15] WIP refactor expansion of decorators and move derive to MultiDecorator --- src/libsyntax/ext/base.rs | 20 +- src/libsyntax/ext/deriving/bounds.rs | 13 +- src/libsyntax/ext/deriving/clone.rs | 8 +- src/libsyntax/ext/deriving/cmp/eq.rs | 8 +- src/libsyntax/ext/deriving/cmp/ord.rs | 8 +- src/libsyntax/ext/deriving/cmp/partial_eq.rs | 8 +- src/libsyntax/ext/deriving/cmp/partial_ord.rs | 8 +- src/libsyntax/ext/deriving/decodable.rs | 16 +- src/libsyntax/ext/deriving/default.rs | 8 +- src/libsyntax/ext/deriving/encodable.rs | 16 +- src/libsyntax/ext/deriving/generic/mod.rs | 71 +++-- src/libsyntax/ext/deriving/hash.rs | 8 +- src/libsyntax/ext/deriving/mod.rs | 80 ++--- src/libsyntax/ext/deriving/primitive.rs | 8 +- src/libsyntax/ext/deriving/show.rs | 8 +- 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 3e54e43c02961..2ecefef51045e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -123,6 +123,16 @@ impl Annotatable { } } + pub fn map_item_or(self, mut f: F, mut or: G) -> Annotatable + where F: FnMut(P) -> P, + G: FnMut(Annotatable) -> Annotatable + { + match self { + Annotatable::Item(i) => Annotatable::Item(f(i)), + _ => or(self) + } + } + pub fn expect_trait_item(self) -> P { 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 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), /// 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), /// 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 eb3debeac9901..1300eb7ff3f45 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)) + _: 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: 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 97fc3f0bf5600..935f0ae8a5ef4 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: 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 ce8f0a7b32b90..d7142d657d408 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: Annotatable, + push: &mut FnMut(Annotatable)) { fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { cs_same_method( diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 94cc0d9c493f2..6e52da2f332a6 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: 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 61eb81c6755e2..c31c91760e0c5 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: 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 dbb779decace2..9097e984dd6af 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: 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 0b31f06f87d06..1ab51865652a7 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: 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: 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: 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 f04eaa08dead1..b7b741290af1b 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: 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 92944d649332f..47acedbcb8a66 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: 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: 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: 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 4c05cd973ff6f..222bbe2df6d21 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)) + 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 b9835eda791f7..b1ec3f564f574 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: 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 bc4a7f90911dc..61848cca059ce 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) - -> P { - 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)) { + 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 a972cfe135511..d218b8df15311 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: 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 3ce1f6f12ceab..5ace1b45b065b 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: 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 106d862042a90..5033f406da047 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -477,59 +477,6 @@ pub fn expand_item(it: P, 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, fld: &mut MacroExpander) - -> P { - // 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 { @@ -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> = 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 = 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 = 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, - fld: &MacroExpander) - -> (Vec, Vec) { - 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, Vec) { + 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, Vec) { - 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, + new_attrs: &mut Vec) +{ + 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 = 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 = 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, + fld: &mut MacroExpander) + -> P { + // 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, fld: &mut MacroExpander) -> SmallVector> { match ii.node { From aa5ca282b20391c6df51fdfa94e0de5672ccfac1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 1 May 2015 16:05:02 +1200 Subject: [PATCH 13/15] Get tests passing --- src/libsyntax/ext/deriving/generic/mod.rs | 5 +- src/test/auxiliary/custom_derive_plugin.rs | 12 ++- src/test/auxiliary/macro_crate_test.rs | 90 ++++--------------- .../macro-crate-multi-decorator.rs | 9 +- 4 files changed, 35 insertions(+), 81 deletions(-) diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 222bbe2df6d21..4a54b36f8c4f3 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -398,7 +398,8 @@ impl<'a> TraitDef<'a> { generics) } _ => { - cx.span_err(mitem.span, "`derive` may only be applied to structs and enums"); + cx.span_err(mitem.span, + "`derive` may only be applied to structs and enums"); return; } }; @@ -417,7 +418,7 @@ impl<'a> TraitDef<'a> { }))) } _ => { - cx.span_err(mitem.span, "`derive` may only be applied to structs and enums"); + cx.span_err(mitem.span, "`derive` may only be applied to structs and enums"); } } } diff --git a/src/test/auxiliary/custom_derive_plugin.rs b/src/test/auxiliary/custom_derive_plugin.rs index 17d3f6a46ef57..433a15795b3c6 100644 --- a/src/test/auxiliary/custom_derive_plugin.rs +++ b/src/test/auxiliary/custom_derive_plugin.rs @@ -19,7 +19,7 @@ extern crate rustc; use syntax::ast; use syntax::codemap::Span; -use syntax::ext::base::{Decorator, ExtCtxt}; +use syntax::ext::base::{Decorator, 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}; @@ -70,5 +70,13 @@ fn expand(cx: &mut ExtCtxt, ], }; - trait_def.expand(cx, mitem, item, push) + trait_def.expand(cx, + mitem, + Annotatable::Item(P(item.clone())), + &mut |i| { + match i { + Annotatable::Item(i) => push(i), + _ => panic!("Not an item") + } + }) } diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index de1edf89162e2..53a6672d4888d 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -10,13 +10,12 @@ // 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, Method, ImplItem, TraitItem}; +use syntax::ast::{self, TokenTree, Item, MetaItem, ImplItem, TraitItem}; use syntax::codemap::Span; use syntax::ext::base::*; use syntax::parse::{self, token}; @@ -25,7 +24,6 @@ use rustc::plugin::Registry; #[macro_export] macro_rules! exported_macro { () => (2) } - macro_rules! unexported_macro { () => (3) } #[plugin_registrar] @@ -42,7 +40,8 @@ pub fn plugin_registrar(reg: &mut Registry) { MultiModifier(Box::new(expand_into_foo_multi))); reg.register_syntax_extension( token::intern("duplicate"), - MultiDecorator(box expand_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]) @@ -109,13 +108,13 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt, fn expand_duplicate(cx: &mut ExtCtxt, sp: Span, mi: &MetaItem, - it: &Annotatable, - mut push: Box) + 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.get()) + token::str_to_ident(&w) } else { cx.span_err(mi.span, "Expected word"); return; @@ -136,75 +135,18 @@ fn expand_duplicate(cx: &mut ExtCtxt, 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)))); - } - } + let mut new_it = (*it).clone(); + new_it.attrs.clear(); + new_it.ident = copy_name; + push(Annotatable::ImplItem(P(new_it))); } - } - - fn replace_method_name(m: &mut ast::Method_, i: ast::Ident) { - if let &mut ast::Method_::MethDecl(ref mut ident, _, _, _, _, _, _, _) = m { - *ident = i + Annotatable::TraitItem(tt) => { + let mut new_it = (*tt).clone(); + new_it.attrs.clear(); + new_it.ident = copy_name; + push(Annotatable::TraitItem(P(new_it))); } } } -fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box { - use syntax::ext::quote::rt::*; - - if !tts.is_empty() { - cx.span_fatal(sp, "forged_ident takes no arguments"); - } - - // Most of this is modelled after the expansion of the `quote_expr!` - // macro ... - let parse_sess = cx.parse_sess(); - let cfg = cx.cfg(); - - // ... except this is where we inject a forged identifier, - // and deliberately do not call `cx.parse_tts_with_hygiene` - // (because we are testing that this will be *rejected* - // by the default parser). - - let expr = { - let tt = cx.parse_tts("\x00name_2,ctxt_0\x00".to_string()); - let mut parser = new_parser_from_tts(parse_sess, cfg, tt); - parser.parse_expr() - }; - MacEager::expr(expr) -} - pub fn foo() {} diff --git a/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs b/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs index 45341d12d0743..3c215b6ca48dd 100644 --- a/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs +++ b/src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs @@ -11,12 +11,15 @@ // aux-build:macro_crate_test.rs // ignore-stage1 -#![feature(plugin)] +#![feature(plugin, custom_attribute)] +#![plugin(macro_crate_test)] -#[plugin] #[no_link] +#[macro_use] +#[no_link] extern crate macro_crate_test; -// The duplicate macro will create a copy of the item with the given identifier +// The duplicate macro will create a copy of the item with the given identifier. + #[duplicate(MyCopy)] struct MyStruct { number: i32 From 5d16772ecb93270ac64b44b429a157f397a3e41d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 12 May 2015 14:15:02 +1200 Subject: [PATCH 14/15] Rebasing --- src/libsyntax/ext/deriving/bounds.rs | 2 +- src/libsyntax/ext/deriving/clone.rs | 2 +- src/libsyntax/ext/deriving/cmp/eq.rs | 2 +- src/libsyntax/ext/deriving/cmp/ord.rs | 2 +- src/libsyntax/ext/deriving/cmp/partial_eq.rs | 2 +- src/libsyntax/ext/deriving/cmp/partial_ord.rs | 2 +- src/libsyntax/ext/deriving/decodable.rs | 2 +- src/libsyntax/ext/deriving/default.rs | 2 +- src/libsyntax/ext/deriving/encodable.rs | 2 +- src/libsyntax/ext/deriving/generic/mod.rs | 10 +++++----- src/libsyntax/ext/deriving/hash.rs | 2 +- src/libsyntax/ext/deriving/primitive.rs | 2 +- src/libsyntax/ext/deriving/show.rs | 2 +- 13 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index 1300eb7ff3f45..0593de6db07a7 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -45,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); } diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 935f0ae8a5ef4..0d8fb47142937 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -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( diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index d7142d657d408..bd7c7d85a375f 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -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) } diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 6e52da2f332a6..b4caf0ec26e27 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -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) } diff --git a/src/libsyntax/ext/deriving/cmp/partial_eq.rs b/src/libsyntax/ext/deriving/cmp/partial_eq.rs index c31c91760e0c5..5d744334745d3 100644 --- a/src/libsyntax/ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax/ext/deriving/cmp/partial_eq.rs @@ -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) } diff --git a/src/libsyntax/ext/deriving/cmp/partial_ord.rs b/src/libsyntax/ext/deriving/cmp/partial_ord.rs index 9097e984dd6af..3ef73f6556e30 100644 --- a/src/libsyntax/ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax/ext/deriving/cmp/partial_ord.rs @@ -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)] diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 1ab51865652a7..75c9bc42ea2bf 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -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, diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index b7b741290af1b..e9984c84e322f 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -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 { diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 47acedbcb8a66..4430c58700af3 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -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, diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 78c2faea9d204..b1ab0438a018b 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -380,22 +380,22 @@ impl<'a> TraitDef<'a> { pub fn expand(&self, cx: &mut ExtCtxt, mitem: &ast::MetaItem, - item: Annotatable, + item: &'a Annotatable, push: &mut FnMut(Annotatable)) { - match item { - Annotatable::Item(item) => { + 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, + &struct_def, item.ident, generics) } ast::ItemEnum(ref enum_def, ref generics) => { self.expand_enum_def(cx, enum_def, - &item.attrs[..], + &item.attrs, item.ident, generics) } diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index b1ec3f564f574..698e788d65f00 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -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 { diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index d218b8df15311..4fe9aefa1a4df 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -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 { diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 5ace1b45b065b..dc634df2073a4 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -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 From c544e838de7a0f0c11c681aa0b29056bdee5cb55 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 13 May 2015 16:24:49 +1200 Subject: [PATCH 15/15] Rebasing --- src/test/auxiliary/custom_derive_plugin.rs | 18 +++++------------- .../auxiliary/custom_derive_plugin_attr.rs | 10 +++++----- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/test/auxiliary/custom_derive_plugin.rs b/src/test/auxiliary/custom_derive_plugin.rs index 253c89233bf5a..0edbeb2d02ca4 100644 --- a/src/test/auxiliary/custom_derive_plugin.rs +++ b/src/test/auxiliary/custom_derive_plugin.rs @@ -19,7 +19,7 @@ extern crate rustc; use syntax::ast; use syntax::codemap::Span; -use syntax::ext::base::{Decorator, ExtCtxt, Annotatable}; +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)) { + item: Annotatable, + push: &mut FnMut(Annotatable)) { let trait_def = TraitDef { span: span, attributes: vec![], @@ -70,13 +70,5 @@ fn expand(cx: &mut ExtCtxt, ], }; - trait_def.expand(cx, - mitem, - Annotatable::Item(P(item.clone())), - &mut |i| { - match i { - Annotatable::Item(i) => push(i), - _ => panic!("Not an item") - } - }) + trait_def.expand(cx, mitem, &item, push) } diff --git a/src/test/auxiliary/custom_derive_plugin_attr.rs b/src/test/auxiliary/custom_derive_plugin_attr.rs index 445aa743a77fe..92963b2812dd8 100644 --- a/src/test/auxiliary/custom_derive_plugin_attr.rs +++ b/src/test/auxiliary/custom_derive_plugin_attr.rs @@ -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)) { + 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