Skip to content

Commit fca80c9

Browse files
committed
Generalize Invocation to include modifiers/decorators.
1 parent 3cba93f commit fca80c9

File tree

2 files changed

+138
-95
lines changed

2 files changed

+138
-95
lines changed

src/libsyntax/ext/base.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,6 @@ impl Annotatable {
9191
_ => panic!("expected Item")
9292
}
9393
}
94-
95-
pub fn fold_with<F: Folder>(self, folder: &mut F) -> SmallVector<Self> {
96-
match self {
97-
Annotatable::Item(item) => folder.fold_item(item).map(Annotatable::Item),
98-
Annotatable::ImplItem(item) =>
99-
folder.fold_impl_item(item.unwrap()).map(|item| Annotatable::ImplItem(P(item))),
100-
Annotatable::TraitItem(item) =>
101-
folder.fold_trait_item(item.unwrap()).map(|item| Annotatable::TraitItem(P(item))),
102-
}
103-
}
10494
}
10595

10696
// A more flexible ItemDecorator.

src/libsyntax/ext/expand.rs

Lines changed: 138 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -109,29 +109,104 @@ impl ExpansionKind {
109109
fn dummy(self, span: Span) -> Expansion {
110110
self.make_from(DummyResult::any(span)).unwrap()
111111
}
112+
113+
fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I) -> Expansion {
114+
let items = items.into_iter();
115+
match self {
116+
ExpansionKind::Items =>
117+
Expansion::Items(items.map(Annotatable::expect_item).collect()),
118+
ExpansionKind::ImplItems =>
119+
Expansion::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
120+
ExpansionKind::TraitItems =>
121+
Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
122+
_ => unreachable!(),
123+
}
124+
}
112125
}
113126

114127
pub struct Invocation {
115-
span: Span,
116-
attrs: Vec<ast::Attribute>,
117-
mac: ast::Mac,
118-
ident: Option<Ident>,
128+
kind: InvocationKind,
129+
expansion_kind: ExpansionKind,
119130
mark: Mark,
120-
kind: ExpansionKind,
131+
}
132+
133+
enum InvocationKind {
134+
Bang {
135+
attrs: Vec<ast::Attribute>,
136+
mac: ast::Mac,
137+
ident: Option<Ident>,
138+
span: Span,
139+
},
140+
Attr {
141+
attr: ast::Attribute,
142+
item: Annotatable,
143+
},
121144
}
122145

123146
pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> {
124147
if let ast::ExprKind::Mac(mac) = expr.node {
125-
let invoc = fld.new_invoc(mac, expr.attrs.into(), expr.span, ExpansionKind::Expr);
126-
expand_mac_invoc(invoc, fld).make_expr()
148+
let invoc = fld.new_bang_invoc(mac, expr.attrs.into(), expr.span, ExpansionKind::Expr);
149+
expand_invoc(invoc, fld).make_expr()
127150
} else {
128151
P(noop_fold_expr(expr, fld))
129152
}
130153
}
131154

155+
fn expand_invoc(invoc: Invocation, fld: &mut MacroExpander) -> Expansion {
156+
match invoc.kind {
157+
InvocationKind::Bang { .. } => expand_bang_invoc(invoc, fld),
158+
InvocationKind::Attr { .. } => expand_attr_invoc(invoc, fld),
159+
}
160+
}
161+
162+
fn expand_attr_invoc(invoc: Invocation, fld: &mut MacroExpander) -> Expansion {
163+
let Invocation { expansion_kind: kind, .. } = invoc;
164+
let (attr, item) = match invoc.kind {
165+
InvocationKind::Attr { attr, item } => (attr, item),
166+
_ => unreachable!(),
167+
};
168+
169+
let extension = match fld.cx.syntax_env.find(intern(&attr.name())) {
170+
Some(extension) => extension,
171+
None => unreachable!(),
172+
};
173+
174+
attr::mark_used(&attr);
175+
fld.cx.bt_push(ExpnInfo {
176+
call_site: attr.span,
177+
callee: NameAndSpan {
178+
format: MacroAttribute(intern(&attr.name())),
179+
span: Some(attr.span),
180+
allow_internal_unstable: false,
181+
}
182+
});
183+
184+
let modified = match *extension {
185+
MultiModifier(ref mac) => {
186+
kind.expect_from_annotatables(mac.expand(fld.cx, attr.span, &attr.node.value, item))
187+
}
188+
MultiDecorator(ref mac) => {
189+
let mut items = Vec::new();
190+
mac.expand(fld.cx, attr.span, &attr.node.value, &item, &mut |item| items.push(item));
191+
items.push(item);
192+
kind.expect_from_annotatables(items)
193+
}
194+
_ => unreachable!(),
195+
};
196+
197+
fld.cx.bt_pop();
198+
199+
let configured = modified.fold_with(&mut fld.strip_unconfigured());
200+
configured.fold_with(fld)
201+
}
202+
132203
/// Expand a macro invocation. Returns the result of expansion.
133-
fn expand_mac_invoc(invoc: Invocation, fld: &mut MacroExpander) -> Expansion {
134-
let Invocation { span, attrs, mac, ident, mark, kind } = invoc;
204+
fn expand_bang_invoc(invoc: Invocation, fld: &mut MacroExpander) -> Expansion {
205+
let Invocation { mark, expansion_kind: kind, .. } = invoc;
206+
let (attrs, mac, ident, span) = match invoc.kind {
207+
InvocationKind::Bang { attrs, mac, ident, span } => (attrs, mac, ident, span),
208+
_ => unreachable!(),
209+
};
135210
let Mac_ { path, tts, .. } = mac.node;
136211

137212
// Detect use of feature-gated or invalid attributes on macro invoations
@@ -270,11 +345,8 @@ fn expand_mac_invoc(invoc: Invocation, fld: &mut MacroExpander) -> Expansion {
270345
fully_expanded
271346
}
272347

273-
// When we enter a module, record it, for the sake of `module!`
274-
pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
275-
-> SmallVector<P<ast::Item>> {
276-
expand_annotatable(Annotatable::Item(it), fld)
277-
.into_iter().map(|i| i.expect_item()).collect()
348+
pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> {
349+
expand_annotatable(Annotatable::Item(it), fld).make_items()
278350
}
279351

280352
// does this attribute list contain "macro_use" ?
@@ -311,8 +383,8 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
311383
_ => return noop_fold_stmt(stmt, fld)
312384
};
313385

314-
let invoc = fld.new_invoc(mac, attrs.into(), stmt.span, ExpansionKind::Stmts);
315-
let mut fully_expanded = expand_mac_invoc(invoc, fld).make_stmts();
386+
let invoc = fld.new_bang_invoc(mac, attrs.into(), stmt.span, ExpansionKind::Stmts);
387+
let mut fully_expanded = expand_invoc(invoc, fld).make_stmts();
316388

317389
// If this is a macro invocation with a semicolon, then apply that
318390
// semicolon to the final statement produced by expansion.
@@ -332,28 +404,30 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
332404
}
333405
p.and_then(|p| match p.node {
334406
PatKind::Mac(mac) => {
335-
let invoc = fld.new_invoc(mac, Vec::new(), p.span, ExpansionKind::Pat);
336-
expand_mac_invoc(invoc, fld).make_pat()
407+
let invoc = fld.new_bang_invoc(mac, Vec::new(), p.span, ExpansionKind::Pat);
408+
expand_invoc(invoc, fld).make_pat()
337409
}
338410
_ => unreachable!(),
339411
})
340412
}
341413

342-
fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
414+
fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> Expansion {
343415
match a {
344416
Annotatable::Item(it) => match it.node {
345417
ast::ItemKind::Mac(..) => {
346418
if match it.node {
347419
ItemKind::Mac(ref mac) => mac.node.path.segments.is_empty(),
348420
_ => unreachable!(),
349421
} {
350-
return SmallVector::one(Annotatable::Item(it));
422+
return Expansion::Items(SmallVector::one(it));
351423
}
352424
it.and_then(|it| match it.node {
353425
ItemKind::Mac(mac) => {
354-
let mut invoc = fld.new_invoc(mac, it.attrs, it.span, ExpansionKind::Items);
355-
invoc.ident = Some(it.ident);
356-
expand_mac_invoc(invoc, fld).make_items()
426+
let invoc =
427+
fld.new_invoc(ExpansionKind::Items, InvocationKind::Bang {
428+
mac: mac, attrs: it.attrs, ident: Some(it.ident), span: it.span,
429+
});
430+
expand_invoc(invoc, fld)
357431
}
358432
_ => unreachable!(),
359433
})
@@ -370,31 +444,24 @@ fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector
370444
if valid_ident {
371445
fld.cx.mod_pop();
372446
}
373-
result
447+
Expansion::Items(result)
374448
},
375-
_ => noop_fold_item(it, fld),
376-
}.into_iter().map(|i| Annotatable::Item(i)).collect(),
377-
378-
Annotatable::TraitItem(it) => {
379-
expand_trait_item(it.unwrap(), fld).into_iter().
380-
map(|it| Annotatable::TraitItem(P(it))).collect()
381-
}
449+
_ => Expansion::Items(noop_fold_item(it, fld)),
450+
},
382451

383-
Annotatable::ImplItem(ii) => {
384-
expand_impl_item(ii.unwrap(), fld).into_iter().
385-
map(|ii| Annotatable::ImplItem(P(ii))).collect()
386-
}
452+
Annotatable::TraitItem(it) => Expansion::TraitItems(expand_trait_item(it.unwrap(), fld)),
453+
Annotatable::ImplItem(ii) => Expansion::ImplItems(expand_impl_item(ii.unwrap(), fld)),
387454
}
388455
}
389456

390-
fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
391-
let mut multi_modifier = None;
457+
fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> Expansion {
458+
let mut attr = None;
392459
item = item.map_attrs(|mut attrs| {
393460
for i in 0..attrs.len() {
394461
if let Some(extension) = fld.cx.syntax_env.find(intern(&attrs[i].name())) {
395462
match *extension {
396463
MultiModifier(..) | MultiDecorator(..) => {
397-
multi_modifier = Some((attrs.remove(i), extension));
464+
attr = Some(attrs.remove(i));
398465
break;
399466
}
400467
_ => {}
@@ -404,47 +471,25 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe
404471
attrs
405472
});
406473

407-
match multi_modifier {
408-
None => expand_multi_modified(item, fld),
409-
Some((attr, extension)) => {
410-
attr::mark_used(&attr);
411-
fld.cx.bt_push(ExpnInfo {
412-
call_site: attr.span,
413-
callee: NameAndSpan {
414-
format: MacroAttribute(intern(&attr.name())),
415-
span: Some(attr.span),
416-
allow_internal_unstable: false,
417-
}
418-
});
419-
420-
let modified = match *extension {
421-
MultiModifier(ref mac) => mac.expand(fld.cx, attr.span, &attr.node.value, item),
422-
MultiDecorator(ref mac) => {
423-
let mut items = Vec::new();
424-
mac.expand(fld.cx, attr.span, &attr.node.value, &item,
425-
&mut |item| items.push(item));
426-
items.push(item);
427-
items
428-
}
429-
_ => unreachable!(),
430-
};
431-
432-
fld.cx.bt_pop();
433-
let configured = modified.into_iter().flat_map(|it| {
434-
it.fold_with(&mut fld.strip_unconfigured())
435-
}).collect::<SmallVector<_>>();
436-
437-
configured.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect()
438-
}
474+
if let Some(attr) = attr {
475+
let kind = match item {
476+
Annotatable::Item(_) => ExpansionKind::Items,
477+
Annotatable::ImplItem(_) => ExpansionKind::ImplItems,
478+
Annotatable::TraitItem(_) => ExpansionKind::TraitItems,
479+
};
480+
let invoc = fld.new_invoc(kind, InvocationKind::Attr { attr: attr, item: item });
481+
expand_invoc(invoc, fld)
482+
} else {
483+
expand_multi_modified(item, fld)
439484
}
440485
}
441486

442487
fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
443488
-> SmallVector<ast::ImplItem> {
444489
match ii.node {
445490
ast::ImplItemKind::Macro(mac) => {
446-
let invoc = fld.new_invoc(mac, ii.attrs, ii.span, ExpansionKind::ImplItems);
447-
expand_mac_invoc(invoc, fld).make_impl_items()
491+
let invoc = fld.new_bang_invoc(mac, ii.attrs, ii.span, ExpansionKind::ImplItems);
492+
expand_invoc(invoc, fld).make_impl_items()
448493
}
449494
_ => fold::noop_fold_impl_item(ii, fld)
450495
}
@@ -454,8 +499,8 @@ fn expand_trait_item(ti: ast::TraitItem, fld: &mut MacroExpander)
454499
-> SmallVector<ast::TraitItem> {
455500
match ti.node {
456501
ast::TraitItemKind::Macro(mac) => {
457-
let invoc = fld.new_invoc(mac, ti.attrs, ti.span, ExpansionKind::TraitItems);
458-
expand_mac_invoc(invoc, fld).make_trait_items()
502+
let invoc = fld.new_bang_invoc(mac, ti.attrs, ti.span, ExpansionKind::TraitItems);
503+
expand_invoc(invoc, fld).make_trait_items()
459504
}
460505
_ => fold::noop_fold_trait_item(ti, fld)
461506
}
@@ -469,8 +514,8 @@ pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
469514

470515
match t.node {
471516
ast::TyKind::Mac(mac) => {
472-
let invoc = fld.new_invoc(mac, Vec::new(), t.span, ExpansionKind::Ty);
473-
expand_mac_invoc(invoc, fld).make_ty()
517+
let invoc = fld.new_bang_invoc(mac, Vec::new(), t.span, ExpansionKind::Ty);
518+
expand_invoc(invoc, fld).make_ty()
474519
}
475520
_ => unreachable!(),
476521
}
@@ -542,10 +587,20 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
542587
});
543588
}
544589

545-
fn new_invoc(&self, mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span, kind: ExpansionKind)
590+
fn new_invoc(&self, expansion_kind: ExpansionKind, kind: InvocationKind)
546591
-> Invocation {
547-
let mark = Mark::fresh();
548-
Invocation { span: span, attrs: attrs, mac: mac, mark: mark, kind: kind, ident: None }
592+
Invocation { mark: Mark::fresh(), kind: kind, expansion_kind: expansion_kind }
593+
}
594+
595+
fn new_bang_invoc(
596+
&self, mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span, kind: ExpansionKind,
597+
) -> Invocation {
598+
self.new_invoc(kind, InvocationKind::Bang {
599+
attrs: attrs,
600+
mac: mac,
601+
ident: None,
602+
span: span,
603+
})
549604
}
550605

551606
fn with_exts_frame<T, F: FnOnce(&mut Self) -> T>(&mut self, macros_escape: bool, f: F) -> T {
@@ -573,8 +628,8 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
573628
expr.and_then(|expr| match expr.node {
574629
ast::ExprKind::Mac(mac) => {
575630
let invoc =
576-
self.new_invoc(mac, expr.attrs.into(), expr.span, ExpansionKind::OptExpr);
577-
expand_mac_invoc(invoc, self).make_opt_expr()
631+
self.new_bang_invoc(mac, expr.attrs.into(), expr.span, ExpansionKind::OptExpr);
632+
expand_invoc(invoc, self).make_opt_expr()
578633
}
579634
_ => Some(expand_expr(expr, self)),
580635
})
@@ -624,13 +679,11 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
624679
}
625680

626681
fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
627-
expand_annotatable(Annotatable::TraitItem(P(i)), self)
628-
.into_iter().map(|i| i.expect_trait_item()).collect()
682+
expand_annotatable(Annotatable::TraitItem(P(i)), self).make_trait_items()
629683
}
630684

631685
fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
632-
expand_annotatable(Annotatable::ImplItem(P(i)), self)
633-
.into_iter().map(|i| i.expect_impl_item()).collect()
686+
expand_annotatable(Annotatable::ImplItem(P(i)), self).make_impl_items()
634687
}
635688

636689
fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {

0 commit comments

Comments
 (0)