Skip to content

Commit 0a62a05

Browse files
committed
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
2 parents f9e53c7 + 143f2db commit 0a62a05

File tree

7 files changed

+239
-14
lines changed

7 files changed

+239
-14
lines changed

src/librustc/plugin/registry.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ use lint::{LintPassObject, LintId, Lint};
1414
use session::Session;
1515

1616
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
17+
<<<<<<< HEAD
1718
use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
1819
use syntax::ext::base::MacroExpanderFn;
20+
=======
21+
use syntax::ext::base::{IdentTT, Decorator, MultiDecorator, Modifier, MultiModifier, MacroRulesTT};
22+
use syntax::ext::base::{MacroExpanderFn};
23+
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
1924
use syntax::codemap::Span;
2025
use syntax::parse::token;
2126
use syntax::ptr::P;
@@ -84,6 +89,7 @@ impl<'a> Registry<'a> {
8489
/// Register a syntax extension of any kind.
8590
///
8691
/// This is the most general hook into `libsyntax`'s expansion behavior.
92+
#[allow(deprecated)]
8793
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
8894
self.syntax_exts.push((name, match extension {
8995
NormalTT(ext, _, allow_internal_unstable) => {
@@ -93,6 +99,7 @@ impl<'a> Registry<'a> {
9399
IdentTT(ext, Some(self.krate_span), allow_internal_unstable)
94100
}
95101
Decorator(ext) => Decorator(ext),
102+
MultiDecorator(ext) => MultiDecorator(ext),
96103
Modifier(ext) => Modifier(ext),
97104
MultiModifier(ext) => MultiModifier(ext),
98105
MacroRulesTT => {

src/libsyntax/ext/base.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ use std::collections::HashMap;
3030
use std::rc::Rc;
3131
use std::default::Default;
3232

33+
#[unstable(feature = "rustc_private")]
34+
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
3335
pub trait ItemDecorator {
3436
fn expand(&self,
3537
ecx: &mut ExtCtxt,
@@ -39,6 +41,9 @@ pub trait ItemDecorator {
3941
push: &mut FnMut(P<ast::Item>));
4042
}
4143

44+
#[allow(deprecated)]
45+
#[unstable(feature = "rustc_private")]
46+
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
4247
impl<F> ItemDecorator for F
4348
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, &mut FnMut(P<ast::Item>))
4449
{
@@ -52,6 +57,8 @@ impl<F> ItemDecorator for F
5257
}
5358
}
5459

60+
#[unstable(feature = "rustc_private")]
61+
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
5562
pub trait ItemModifier {
5663
fn expand(&self,
5764
ecx: &mut ExtCtxt,
@@ -61,9 +68,13 @@ pub trait ItemModifier {
6168
-> P<ast::Item>;
6269
}
6370

71+
#[allow(deprecated)]
72+
#[unstable(feature = "rustc_private")]
73+
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
6474
impl<F> ItemModifier for F
6575
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P<ast::Item>) -> P<ast::Item>
6676
{
77+
6778
fn expand(&self,
6879
ecx: &mut ExtCtxt,
6980
span: Span,
@@ -127,6 +138,29 @@ impl Annotatable {
127138
}
128139
}
129140

141+
// A more flexible ItemDecorator.
142+
pub trait MultiItemDecorator {
143+
fn expand(&self,
144+
ecx: &mut ExtCtxt,
145+
sp: Span,
146+
meta_item: &ast::MetaItem,
147+
item: &Annotatable,
148+
push: Box<FnMut(Annotatable)>);
149+
}
150+
151+
impl<F> MultiItemDecorator for F
152+
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, Box<FnMut(Annotatable)>)
153+
{
154+
fn expand(&self,
155+
ecx: &mut ExtCtxt,
156+
sp: Span,
157+
meta_item: &ast::MetaItem,
158+
item: &Annotatable,
159+
push: Box<FnMut(Annotatable)>) {
160+
(*self)(ecx, sp, meta_item, item, push)
161+
}
162+
}
163+
130164
// A more flexible ItemModifier (ItemModifier should go away, eventually, FIXME).
131165
// meta_item is the annotation, item is the item being modified, parent_item
132166
// 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 {
397431
pub enum SyntaxExtension {
398432
/// A syntax extension that is attached to an item and creates new items
399433
/// based upon it.
400-
///
401-
/// `#[derive(...)]` is an `ItemDecorator`.
434+
#[unstable(feature = "rustc_private")]
435+
#[deprecated(since = "1.0.0", reason = "replaced by MultiDecorator")]
402436
Decorator(Box<ItemDecorator + 'static>),
403437

438+
/// A syntax extension that is attached to an item and creates new items
439+
/// based upon it.
440+
///
441+
/// `#[derive(...)]` is a `MultiItemDecorator`.
442+
MultiDecorator(Box<MultiItemDecorator + 'static>),
443+
404444
/// A syntax extension that is attached to an item and modifies it
405445
/// in-place.
446+
#[unstable(feature = "rustc_private")]
447+
#[deprecated(since = "1.0.0", reason = "replaced by MultiModifier")]
406448
Modifier(Box<ItemModifier + 'static>),
407449

408450
/// 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>)
473515
syntax_expanders.insert(intern("log_syntax"),
474516
builtin_normal_expander(
475517
ext::log_syntax::expand_syntax_ext));
518+
<<<<<<< HEAD
519+
=======
520+
syntax_expanders.insert(intern("derive"),
521+
MultiDecorator(box ext::deriving::expand_meta_derive));
522+
syntax_expanders.insert(intern("deriving"),
523+
MultiDecorator(box ext::deriving::expand_deprecated_deriving));
524+
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
476525

477526
ext::deriving::register_all(&mut syntax_expanders);
478527

@@ -537,6 +586,11 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
537586
syntax_expanders.insert(intern("cfg"),
538587
builtin_normal_expander(
539588
ext::cfg::expand_cfg));
589+
<<<<<<< HEAD
590+
=======
591+
syntax_expanders.insert(intern("cfg_attr"),
592+
MultiModifier(box ext::cfg_attr::expand));
593+
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
540594
syntax_expanders.insert(intern("trace_macros"),
541595
builtin_normal_expander(
542596
ext::trace_macros::expand_trace_macros));

src/libsyntax/ext/deriving/mod.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is
1414
//! the standard library, and "std" is the core library.
1515
16-
use ast::{Item, MetaItem, MetaWord};
16+
use ast::{Item, MetaItem, MetaWord, MetaList, MetaNameValue};
1717
use attr::AttrMetaMethods;
18-
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier};
18+
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier, Annotatable};
1919
use ext::build::AstBuilder;
2020
use feature_gate;
2121
use codemap::Span;
@@ -78,9 +78,19 @@ pub mod ord;
7878
pub mod generic;
7979

8080
fn expand_derive(cx: &mut ExtCtxt,
81-
_: Span,
81+
span: Span,
8282
mitem: &MetaItem,
83-
item: P<Item>) -> P<Item> {
83+
annotatable: &Annotatable)
84+
-> P<Annotatable> {
85+
// Derive can only be applied to items
86+
let item = match annotatable {
87+
&Annotatable::Item(ref it) => it.clone(),
88+
_ => {
89+
cx.span_err(span, "`derive` can only be applied to items");
90+
return;
91+
}
92+
};
93+
8494
item.map(|mut item| {
8595
if mitem.value_str().is_some() {
8696
cx.span_err(mitem.span, "unexpected value in `derive`");
@@ -113,7 +123,7 @@ fn expand_derive(cx: &mut ExtCtxt,
113123
intern_and_get_ident(&format!("derive_{}", tname)))));
114124
}
115125

116-
item
126+
Annotatable::Item(item)
117127
})
118128
}
119129

src/libsyntax/ext/expand.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
477477
.into_iter().map(|i| i.expect_item()).collect()
478478
}
479479

480+
#[allow(deprecated)] // This is needed because the `ItemModifier` trait is used
480481
fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
481482
-> P<ast::Item> {
482483
// partition the attributes into ItemModifiers and others
@@ -1082,6 +1083,7 @@ impl<'a> Folder for PatIdentRenamer<'a> {
10821083
}
10831084
}
10841085

1086+
#[allow(deprecated)] // This is needed because the `Decorator` variant is used
10851087
fn expand_annotatable(a: Annotatable,
10861088
fld: &mut MacroExpander)
10871089
-> SmallVector<Annotatable> {
@@ -1120,9 +1122,31 @@ fn expand_annotatable(a: Annotatable,
11201122
let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
11211123
dec.expand(fld.cx, attr.span, &*attr.node.value, &**it,
11221124
&mut |item| items.push(item));
1123-
decorator_items.extend(
1124-
items.into_iter()
1125-
.flat_map(|item| expand_item(item, fld).into_iter()));
1125+
decorator_items.extend(items.into_iter()
1126+
.flat_map(|item| expand_item(item, fld).into_iter()
1127+
.map(|i| Annotatable::Item(i))));
1128+
1129+
fld.cx.bt_pop();
1130+
}
1131+
MultiDecorator(ref dec) => {
1132+
attr::mark_used(attr);
1133+
1134+
fld.cx.bt_push(ExpnInfo {
1135+
call_site: attr.span,
1136+
callee: NameAndSpan {
1137+
name: mname.get().to_string(),
1138+
format: MacroAttribute,
1139+
span: None
1140+
}
1141+
});
1142+
1143+
// we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)),
1144+
// but that double-mut-borrows fld
1145+
let mut anns: SmallVector<Annotatable> = SmallVector::zero();
1146+
dec.expand(fld.cx, attr.span, &*attr.node.value, &a,
1147+
&mut |ann| anns.push(ann));
1148+
decorator_items.extend(anns.into_iter()
1149+
.flat_map(|ann| expand_annotatable(ann, fld).into_iter()));
11261150

11271151
fld.cx.bt_pop();
11281152
}
@@ -1184,7 +1208,7 @@ fn expand_annotatable(a: Annotatable,
11841208
}
11851209
};
11861210

1187-
new_items.push_all(decorator_items.into_iter().map(|i| Annotatable::Item(i)).collect());
1211+
new_items.push_all(decorator_items);
11881212
new_items
11891213
}
11901214

src/libsyntax/print/pprust.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,6 @@ impl<'a> State<'a> {
814814
word(&mut self.s, ";")
815815
}
816816

817-
818817
/// Pretty-print an item
819818
pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
820819
try!(self.hardbreak_if_not_bol());

src/test/auxiliary/macro_crate_test.rs

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ extern crate rustc;
1919
use syntax::ast::{self, TokenTree, Item, MetaItem};
2020
use syntax::codemap::Span;
2121
use syntax::ext::base::*;
22-
use syntax::parse::token;
23-
use syntax::parse;
22+
use syntax::parse::{self, token};
2423
use syntax::ptr::P;
2524
use rustc::plugin::Registry;
2625

@@ -42,6 +41,9 @@ pub fn plugin_registrar(reg: &mut Registry) {
4241
token::intern("into_multi_foo"),
4342
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
4443
MultiModifier(Box::new(expand_into_foo_multi)));
44+
reg.register_syntax_extension(
45+
token::intern("duplicate"),
46+
MultiDecorator(box expand_duplicate));
4547
}
4648

4749
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
@@ -104,6 +106,83 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
104106
}
105107
}
106108

109+
// Create a duplicate of the annotatable, based on the MetaItem
110+
fn expand_duplicate(cx: &mut ExtCtxt,
111+
sp: Span,
112+
mi: &MetaItem,
113+
it: &Annotatable,
114+
mut push: Box<FnMut(Annotatable)>)
115+
{
116+
let copy_name = match mi.node {
117+
ast::MetaItem_::MetaList(_, ref xs) => {
118+
if let ast::MetaItem_::MetaWord(ref w) = xs[0].node {
119+
token::str_to_ident(w.get())
120+
} else {
121+
cx.span_err(mi.span, "Expected word");
122+
return;
123+
}
124+
}
125+
_ => {
126+
cx.span_err(mi.span, "Expected list");
127+
return;
128+
}
129+
};
130+
131+
// Duplicate the item but replace its ident by the MetaItem
132+
match it.clone() {
133+
Annotatable::Item(it) => {
134+
let mut new_it = (*it).clone();
135+
new_it.attrs.clear();
136+
new_it.ident = copy_name;
137+
push(Annotatable::Item(P(new_it)));
138+
}
139+
Annotatable::ImplItem(it) => {
140+
match it {
141+
ImplItem::MethodImplItem(m) => {
142+
let mut new_m = (*m).clone();
143+
new_m.attrs.clear();
144+
replace_method_name(&mut new_m.node, copy_name);
145+
push(Annotatable::ImplItem(ImplItem::MethodImplItem(P(new_m))));
146+
}
147+
ImplItem::TypeImplItem(t) => {
148+
let mut new_t = (*t).clone();
149+
new_t.attrs.clear();
150+
new_t.ident = copy_name;
151+
push(Annotatable::ImplItem(ImplItem::TypeImplItem(P(new_t))));
152+
}
153+
}
154+
}
155+
Annotatable::TraitItem(it) => {
156+
match it {
157+
TraitItem::RequiredMethod(rm) => {
158+
let mut new_rm = rm.clone();
159+
new_rm.attrs.clear();
160+
new_rm.ident = copy_name;
161+
push(Annotatable::TraitItem(TraitItem::RequiredMethod(new_rm)));
162+
}
163+
TraitItem::ProvidedMethod(pm) => {
164+
let mut new_pm = (*pm).clone();
165+
new_pm.attrs.clear();
166+
replace_method_name(&mut new_pm.node, copy_name);
167+
push(Annotatable::TraitItem(TraitItem::ProvidedMethod(P(new_pm))));
168+
}
169+
TraitItem::TypeTraitItem(t) => {
170+
let mut new_t = (*t).clone();
171+
new_t.attrs.clear();
172+
new_t.ty_param.ident = copy_name;
173+
push(Annotatable::TraitItem(TraitItem::TypeTraitItem(P(new_t))));
174+
}
175+
}
176+
}
177+
}
178+
179+
fn replace_method_name(m: &mut ast::Method_, i: ast::Ident) {
180+
if let &mut ast::Method_::MethDecl(ref mut ident, _, _, _, _, _, _, _) = m {
181+
*ident = i
182+
}
183+
}
184+
}
185+
107186
fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult+'static> {
108187
use syntax::ext::quote::rt::*;
109188

0 commit comments

Comments
 (0)