]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/ext/expand.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / libsyntax / ext / expand.rs
CommitLineData
1a4d82fc 1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
223e47cc
LB
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
cc61c64b
XL
11use ast::{self, Block, Ident, NodeId, PatKind, Path};
12use ast::{MacStmtStyle, StmtKind, ItemKind};
5bcae85e 13use attr::{self, HasAttrs};
9e0c209e 14use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
c30ab7b3 15use config::{is_test_or_bench, StripUnconfigured};
cc61c64b 16use errors::FatalError;
223e47cc 17use ext::base::*;
8bb4bdeb 18use ext::derive::{add_derived_markers, collect_derives};
041b39d2 19use ext::hygiene::{Mark, SyntaxContext};
8bb4bdeb
XL
20use ext::placeholders::{placeholder, PlaceholderExpander};
21use feature_gate::{self, Features, is_builtin_attr};
1a4d82fc 22use fold;
223e47cc 23use fold::*;
041b39d2
XL
24use parse::{DirectoryOwnership, PResult};
25use parse::token::{self, Token};
9e0c209e 26use parse::parser::Parser;
1a4d82fc 27use ptr::P;
c30ab7b3 28use std_inject;
8bb4bdeb 29use symbol::Symbol;
476ff2be 30use symbol::keywords;
cc61c64b 31use syntax_pos::{Span, DUMMY_SP};
abe05a73 32use syntax_pos::hygiene::ExpnFormat;
041b39d2 33use tokenstream::{TokenStream, TokenTree};
1a4d82fc 34use util::small_vector::SmallVector;
970d7e83 35use visit::Visitor;
223e47cc 36
8bb4bdeb 37use std::collections::HashMap;
9e0c209e 38use std::mem;
9e0c209e
SL
39use std::rc::Rc;
40
41macro_rules! expansions {
42 ($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
43 $(.$fold:ident)* $(lift .$fold_elt:ident)*,
44 $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
45 #[derive(Copy, Clone, PartialEq, Eq)]
46 pub enum ExpansionKind { OptExpr, $( $kind, )* }
47 pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
48
49 impl ExpansionKind {
50 pub fn name(self) -> &'static str {
51 match self {
52 ExpansionKind::OptExpr => "expression",
53 $( ExpansionKind::$kind => $kind_name, )*
54 }
55 }
92a42be0 56
9e0c209e
SL
57 fn make_from<'a>(self, result: Box<MacResult + 'a>) -> Option<Expansion> {
58 match self {
59 ExpansionKind::OptExpr => result.make_expr().map(Some).map(Expansion::OptExpr),
60 $( ExpansionKind::$kind => result.$make().map(Expansion::$kind), )*
61 }
62 }
63 }
1a4d82fc 64
9e0c209e
SL
65 impl Expansion {
66 pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
67 match self {
68 Expansion::OptExpr(expr) => expr,
69 _ => panic!("Expansion::make_* called on the wrong kind of expansion"),
70 }
71 }
72 $( pub fn $make(self) -> $ty {
73 match self {
74 Expansion::$kind(ast) => ast,
75 _ => panic!("Expansion::make_* called on the wrong kind of expansion"),
76 }
77 } )*
78
79 pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
80 use self::Expansion::*;
81 match self {
82 OptExpr(expr) => OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
83 $($( $kind(ast) => $kind(folder.$fold(ast)), )*)*
84 $($( $kind(ast) => {
85 $kind(ast.into_iter().flat_map(|ast| folder.$fold_elt(ast)).collect())
86 }, )*)*
87 }
88 }
1a4d82fc 89
476ff2be 90 pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
9e0c209e
SL
91 match *self {
92 Expansion::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
93 Expansion::OptExpr(None) => {}
94 $($( Expansion::$kind(ref ast) => visitor.$visit(ast), )*)*
476ff2be 95 $($( Expansion::$kind(ref ast) => for ast in &ast[..] {
9e0c209e
SL
96 visitor.$visit_elt(ast);
97 }, )*)*
98 }
3157f602 99 }
9e0c209e
SL
100 }
101
102 impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
103 fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
104 self.expand(Expansion::OptExpr(Some(expr))).make_opt_expr()
3157f602 105 }
9e0c209e
SL
106 $($(fn $fold(&mut self, node: $ty) -> $ty {
107 self.expand(Expansion::$kind(node)).$make()
108 })*)*
109 $($(fn $fold_elt(&mut self, node: $ty_elt) -> $ty {
110 self.expand(Expansion::$kind(SmallVector::one(node))).$make()
111 })*)*
112 }
113
114 impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
115 $(fn $make(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$ty> {
116 Some(self.make(ExpansionKind::$kind).$make())
117 })*
1a4d82fc 118 }
9e0c209e 119 }
3157f602 120}
1a4d82fc 121
9e0c209e
SL
122expansions! {
123 Expr: P<ast::Expr> [], "expression", .make_expr, .fold_expr, .visit_expr;
124 Pat: P<ast::Pat> [], "pattern", .make_pat, .fold_pat, .visit_pat;
125 Ty: P<ast::Ty> [], "type", .make_ty, .fold_ty, .visit_ty;
126 Stmts: SmallVector<ast::Stmt> [SmallVector, ast::Stmt],
127 "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt;
128 Items: SmallVector<P<ast::Item>> [SmallVector, P<ast::Item>],
129 "item", .make_items, lift .fold_item, lift .visit_item;
130 TraitItems: SmallVector<ast::TraitItem> [SmallVector, ast::TraitItem],
3157f602 131 "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item;
9e0c209e 132 ImplItems: SmallVector<ast::ImplItem> [SmallVector, ast::ImplItem],
3157f602
XL
133 "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item;
134}
c1a9b12d 135
9e0c209e
SL
136impl ExpansionKind {
137 fn dummy(self, span: Span) -> Expansion {
138 self.make_from(DummyResult::any(span)).unwrap()
139 }
140
141 fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I) -> Expansion {
142 let items = items.into_iter();
143 match self {
144 ExpansionKind::Items =>
145 Expansion::Items(items.map(Annotatable::expect_item).collect()),
146 ExpansionKind::ImplItems =>
147 Expansion::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
148 ExpansionKind::TraitItems =>
149 Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
150 _ => unreachable!(),
151 }
3157f602
XL
152 }
153}
154
abe05a73
XL
155fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
156 // We don't want to format a path using pretty-printing,
157 // `format!("{}", path)`, because that tries to insert
158 // line-breaks and is slow.
159 let mut path_str = String::with_capacity(64);
160 for (i, segment) in path.segments.iter().enumerate() {
161 if i != 0 {
162 path_str.push_str("::");
163 }
164
165 if segment.identifier.name != keywords::CrateRoot.name() &&
166 segment.identifier.name != keywords::DollarCrate.name()
167 {
168 path_str.push_str(&segment.identifier.name.as_str())
169 }
170 }
171
172 MacroBang(Symbol::intern(&path_str))
173}
174
9e0c209e
SL
175pub struct Invocation {
176 pub kind: InvocationKind,
177 expansion_kind: ExpansionKind,
8bb4bdeb 178 pub expansion_data: ExpansionData,
9e0c209e
SL
179}
180
181pub enum InvocationKind {
182 Bang {
9e0c209e
SL
183 mac: ast::Mac,
184 ident: Option<Ident>,
185 span: Span,
186 },
187 Attr {
8bb4bdeb 188 attr: Option<ast::Attribute>,
cc61c64b 189 traits: Vec<Path>,
8bb4bdeb
XL
190 item: Annotatable,
191 },
192 Derive {
cc61c64b 193 path: Path,
9e0c209e
SL
194 item: Annotatable,
195 },
196}
197
198impl Invocation {
199 fn span(&self) -> Span {
200 match self.kind {
201 InvocationKind::Bang { span, .. } => span,
8bb4bdeb 202 InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,
cc61c64b
XL
203 InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
204 InvocationKind::Derive { ref path, .. } => path.span,
c1a9b12d 205 }
5bcae85e
SL
206 }
207}
c1a9b12d 208
9e0c209e
SL
209pub struct MacroExpander<'a, 'b:'a> {
210 pub cx: &'a mut ExtCtxt<'b>,
211 monotonic: bool, // c.f. `cx.monotonic_expander()`
212}
213
214impl<'a, 'b> MacroExpander<'a, 'b> {
215 pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
216 MacroExpander { cx: cx, monotonic: monotonic }
217 }
218
c30ab7b3
SL
219 pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
220 self.cx.crate_root = std_inject::injected_crate_name(&krate);
221 let mut module = ModuleData {
476ff2be 222 mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
ea8adc8c 223 directory: self.cx.codemap().span_to_unmapped_path(krate.span),
c30ab7b3
SL
224 };
225 module.directory.pop();
226 self.cx.current_expansion.module = Rc::new(module);
9e0c209e 227
cc61c64b
XL
228 let orig_mod_span = krate.module.inner;
229
9e0c209e
SL
230 let krate_item = Expansion::Items(SmallVector::one(P(ast::Item {
231 attrs: krate.attrs,
232 span: krate.span,
233 node: ast::ItemKind::Mod(krate.module),
5bcae85e 234 ident: keywords::Invalid.ident(),
5bcae85e 235 id: ast::DUMMY_NODE_ID,
9e0c209e 236 vis: ast::Visibility::Public,
3b2f2976 237 tokens: None,
9e0c209e
SL
238 })));
239
cc61c64b
XL
240 match self.expand(krate_item).make_items().pop().map(P::unwrap) {
241 Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
9e0c209e
SL
242 krate.attrs = attrs;
243 krate.module = module;
244 },
cc61c64b
XL
245 None => {
246 // Resolution failed so we return an empty expansion
247 krate.attrs = vec![];
248 krate.module = ast::Mod {
249 inner: orig_mod_span,
250 items: vec![],
251 };
252 },
9e0c209e
SL
253 _ => unreachable!(),
254 };
7cac9316 255 self.cx.trace_macros_diag();
9e0c209e 256 krate
5bcae85e 257 }
1a4d82fc 258
9e0c209e
SL
259 // Fully expand all the invocations in `expansion`.
260 fn expand(&mut self, expansion: Expansion) -> Expansion {
261 let orig_expansion_data = self.cx.current_expansion.clone();
262 self.cx.current_expansion.depth = 0;
263
8bb4bdeb 264 let (expansion, mut invocations) = self.collect_invocations(expansion, &[]);
476ff2be 265 self.resolve_imports();
9e0c209e
SL
266 invocations.reverse();
267
c30ab7b3 268 let mut expansions = Vec::new();
8bb4bdeb 269 let mut derives = HashMap::new();
c30ab7b3
SL
270 let mut undetermined_invocations = Vec::new();
271 let (mut progress, mut force) = (false, !self.monotonic);
272 loop {
8bb4bdeb 273 let mut invoc = if let Some(invoc) = invocations.pop() {
c30ab7b3 274 invoc
c30ab7b3 275 } else {
476ff2be
SL
276 self.resolve_imports();
277 if undetermined_invocations.is_empty() { break }
c30ab7b3
SL
278 invocations = mem::replace(&mut undetermined_invocations, Vec::new());
279 force = !mem::replace(&mut progress, false);
280 continue
281 };
282
283 let scope =
284 if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
8bb4bdeb 285 let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
c30ab7b3
SL
286 Ok(ext) => Some(ext),
287 Err(Determinacy::Determined) => None,
288 Err(Determinacy::Undetermined) => {
289 undetermined_invocations.push(invoc);
290 continue
291 }
292 };
293
294 progress = true;
9e0c209e
SL
295 let ExpansionData { depth, mark, .. } = invoc.expansion_data;
296 self.cx.current_expansion = invoc.expansion_data.clone();
297
9e0c209e 298 self.cx.current_expansion.mark = scope;
8bb4bdeb
XL
299 // FIXME(jseyfried): Refactor out the following logic
300 let (expansion, new_invocations) = if let Some(ext) = ext {
301 if let Some(ext) = ext {
302 let expansion = self.expand_invoc(invoc, ext);
303 self.collect_invocations(expansion, &[])
304 } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
ea8adc8c
XL
305 let derive_allowed = match item {
306 Annotatable::Item(ref item) => match item.node {
307 ast::ItemKind::Struct(..) |
308 ast::ItemKind::Enum(..) |
309 ast::ItemKind::Union(..) => true,
310 _ => false,
311 },
312 _ => false,
313 };
314 if !derive_allowed {
315 let attr = item.attrs().iter()
316 .find(|attr| attr.check_name("derive"))
317 .expect("`derive` attribute should exist");
318 let span = attr.span;
319 let mut err = self.cx.mut_span_err(span,
320 "`derive` may only be applied to \
321 structs, enums and unions");
322 if let ast::AttrStyle::Inner = attr.style {
323 let trait_list = traits.iter()
324 .map(|t| format!("{}", t)).collect::<Vec<_>>();
325 let suggestion = format!("#[derive({})]", trait_list.join(", "));
326 err.span_suggestion(span, "try an outer attribute", suggestion);
327 }
328 err.emit();
329 }
330
331 let item = self.fully_configure(item)
cc61c64b 332 .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
8bb4bdeb 333 let item_with_markers =
cc61c64b 334 add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
8bb4bdeb
XL
335 let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new);
336
cc61c64b 337 for path in &traits {
7cac9316 338 let mark = Mark::fresh(self.cx.current_expansion.mark);
8bb4bdeb 339 derives.push(mark);
8bb4bdeb 340 let item = match self.cx.resolver.resolve_macro(
cc61c64b 341 Mark::root(), path, MacroKind::Derive, false) {
8bb4bdeb 342 Ok(ext) => match *ext {
3b2f2976 343 BuiltinDerive(..) => item_with_markers.clone(),
8bb4bdeb
XL
344 _ => item.clone(),
345 },
346 _ => item.clone(),
347 };
348 invocations.push(Invocation {
cc61c64b 349 kind: InvocationKind::Derive { path: path.clone(), item: item },
8bb4bdeb
XL
350 expansion_kind: invoc.expansion_kind,
351 expansion_data: ExpansionData {
3b2f2976 352 mark,
8bb4bdeb
XL
353 ..invoc.expansion_data.clone()
354 },
355 });
356 }
357 let expansion = invoc.expansion_kind
358 .expect_from_annotatables(::std::iter::once(item_with_markers));
359 self.collect_invocations(expansion, derives)
360 } else {
361 unreachable!()
362 }
363 } else {
364 self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()), &[])
9e0c209e
SL
365 };
366
c30ab7b3 367 if expansions.len() < depth {
9e0c209e
SL
368 expansions.push(Vec::new());
369 }
32a655c1 370 expansions[depth - 1].push((mark, expansion));
9e0c209e
SL
371 if !self.cx.ecfg.single_step {
372 invocations.extend(new_invocations.into_iter().rev());
373 }
374 }
375
376 self.cx.current_expansion = orig_expansion_data;
377
378 let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
379 while let Some(expansions) = expansions.pop() {
380 for (mark, expansion) in expansions.into_iter().rev() {
8bb4bdeb 381 let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
cc61c64b 382 placeholder_expander.add(NodeId::placeholder_from_mark(mark), expansion, derives);
9e0c209e
SL
383 }
384 }
385
c30ab7b3 386 expansion.fold_with(&mut placeholder_expander)
9e0c209e
SL
387 }
388
476ff2be
SL
389 fn resolve_imports(&mut self) {
390 if self.monotonic {
391 let err_count = self.cx.parse_sess.span_diagnostic.err_count();
392 self.cx.resolver.resolve_imports();
393 self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
394 }
395 }
396
8bb4bdeb
XL
397 fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark])
398 -> (Expansion, Vec<Invocation>) {
9e0c209e
SL
399 let result = {
400 let mut collector = InvocationCollector {
401 cfg: StripUnconfigured {
9e0c209e
SL
402 should_test: self.cx.ecfg.should_test,
403 sess: self.cx.parse_sess,
404 features: self.cx.ecfg.features,
405 },
406 cx: self.cx,
407 invocations: Vec::new(),
408 monotonic: self.monotonic,
409 };
410 (expansion.fold_with(&mut collector), collector.invocations)
411 };
9e0c209e
SL
412
413 if self.monotonic {
c30ab7b3 414 let err_count = self.cx.parse_sess.span_diagnostic.err_count();
9e0c209e 415 let mark = self.cx.current_expansion.mark;
8bb4bdeb 416 self.cx.resolver.visit_expansion(mark, &result.0, derives);
c30ab7b3 417 self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
9e0c209e
SL
418 }
419
420 result
421 }
422
ea8adc8c
XL
423 fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
424 let mut cfg = StripUnconfigured {
425 should_test: self.cx.ecfg.should_test,
426 sess: self.cx.parse_sess,
427 features: self.cx.ecfg.features,
428 };
429 // Since the item itself has already been configured by the InvocationCollector,
430 // we know that fold result vector will contain exactly one element
431 match item {
432 Annotatable::Item(item) => {
433 Annotatable::Item(cfg.fold_item(item).pop().unwrap())
434 }
435 Annotatable::TraitItem(item) => {
436 Annotatable::TraitItem(item.map(|item| cfg.fold_trait_item(item).pop().unwrap()))
437 }
438 Annotatable::ImplItem(item) => {
439 Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap()))
440 }
441 }
442 }
443
9e0c209e 444 fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
cc61c64b 445 let result = match invoc.kind {
9e0c209e
SL
446 InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
447 InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext),
8bb4bdeb 448 InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext),
cc61c64b
XL
449 };
450
451 if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
452 let info = self.cx.current_expansion.mark.expn_info().unwrap();
453 let suggested_limit = self.cx.ecfg.recursion_limit * 2;
ea8adc8c 454 let mut err = self.cx.struct_span_err(info.call_site,
cc61c64b
XL
455 &format!("recursion limit reached while expanding the macro `{}`",
456 info.callee.name()));
457 err.help(&format!(
458 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
459 suggested_limit));
460 err.emit();
ea8adc8c 461 self.cx.trace_macros_diag();
cc61c64b 462 panic!(FatalError);
9e0c209e 463 }
cc61c64b
XL
464
465 result
9e0c209e
SL
466 }
467
468 fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
469 let Invocation { expansion_kind: kind, .. } = invoc;
470 let (attr, item) = match invoc.kind {
8bb4bdeb 471 InvocationKind::Attr { attr, item, .. } => (attr.unwrap(), item),
9e0c209e
SL
472 _ => unreachable!(),
473 };
474
475 attr::mark_used(&attr);
cc61c64b 476 invoc.expansion_data.mark.set_expn_info(ExpnInfo {
9e0c209e
SL
477 call_site: attr.span,
478 callee: NameAndSpan {
cc61c64b
XL
479 format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
480 span: None,
9e0c209e 481 allow_internal_unstable: false,
3b2f2976 482 allow_internal_unsafe: false,
9e0c209e
SL
483 }
484 });
485
486 match *ext {
487 MultiModifier(ref mac) => {
7cac9316 488 let meta = panictry!(attr.parse_meta(self.cx.parse_sess));
cc61c64b 489 let item = mac.expand(self.cx, attr.span, &meta, item);
9e0c209e
SL
490 kind.expect_from_annotatables(item)
491 }
492 MultiDecorator(ref mac) => {
493 let mut items = Vec::new();
7cac9316 494 let meta = panictry!(attr.parse_meta(self.cx.parse_sess));
cc61c64b 495 mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
9e0c209e
SL
496 items.push(item);
497 kind.expect_from_annotatables(items)
498 }
3b2f2976 499 AttrProcMacro(ref mac) => {
041b39d2
XL
500 let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
501 Annotatable::Item(item) => token::NtItem(item),
502 Annotatable::TraitItem(item) => token::NtTraitItem(item.unwrap()),
503 Annotatable::ImplItem(item) => token::NtImplItem(item.unwrap()),
504 })).into();
505 let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok);
506 self.parse_expansion(tok_result, kind, &attr.path, attr.span)
9e0c209e 507 }
3b2f2976 508 ProcMacroDerive(..) | BuiltinDerive(..) => {
cc61c64b 509 self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
ea8adc8c 510 self.cx.trace_macros_diag();
c30ab7b3
SL
511 kind.dummy(attr.span)
512 }
513 _ => {
cc61c64b 514 let msg = &format!("macro `{}` may not be used in attributes", attr.path);
7cac9316 515 self.cx.span_err(attr.span, msg);
ea8adc8c 516 self.cx.trace_macros_diag();
c30ab7b3
SL
517 kind.dummy(attr.span)
518 }
9e0c209e
SL
519 }
520 }
521
522 /// Expand a macro invocation. Returns the result of expansion.
523 fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
524 let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
32a655c1
SL
525 let (mac, ident, span) = match invoc.kind {
526 InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
9e0c209e
SL
527 _ => unreachable!(),
528 };
8bb4bdeb 529 let path = &mac.node.path;
9e0c209e 530
7cac9316 531 let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
3b2f2976
XL
532 let validate_and_set_expn_info = |def_site_span,
533 allow_internal_unstable,
534 allow_internal_unsafe| {
7cac9316
XL
535 if ident.name != keywords::Invalid.name() {
536 return Err(format!("macro {}! expects no ident argument, given '{}'", path, ident));
537 }
538 mark.set_expn_info(ExpnInfo {
539 call_site: span,
540 callee: NameAndSpan {
abe05a73 541 format: macro_bang_format(path),
7cac9316 542 span: def_site_span,
3b2f2976
XL
543 allow_internal_unstable,
544 allow_internal_unsafe,
7cac9316
XL
545 },
546 });
547 Ok(())
548 };
549
9e0c209e 550 let opt_expanded = match *ext {
3b2f2976 551 DeclMacro(ref expand, def_span) => {
7cac9316 552 if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s),
3b2f2976 553 false, false) {
9e0c209e 554 self.cx.span_err(path.span, &msg);
ea8adc8c 555 self.cx.trace_macros_diag();
9e0c209e 556 return kind.dummy(span);
3157f602 557 }
041b39d2 558 kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
7cac9316 559 }
3157f602 560
3b2f2976
XL
561 NormalTT {
562 ref expander,
563 def_info,
564 allow_internal_unstable,
565 allow_internal_unsafe
566 } => {
7cac9316 567 if let Err(msg) = validate_and_set_expn_info(def_info.map(|(_, s)| s),
3b2f2976
XL
568 allow_internal_unstable,
569 allow_internal_unsafe) {
7cac9316 570 self.cx.span_err(path.span, &msg);
ea8adc8c 571 self.cx.trace_macros_diag();
7cac9316
XL
572 return kind.dummy(span);
573 }
3b2f2976 574 kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
3157f602
XL
575 }
576
577 IdentTT(ref expander, tt_span, allow_internal_unstable) => {
578 if ident.name == keywords::Invalid.name() {
9e0c209e 579 self.cx.span_err(path.span,
cc61c64b 580 &format!("macro {}! expects an ident argument", path));
ea8adc8c 581 self.cx.trace_macros_diag();
9e0c209e 582 return kind.dummy(span);
b039eaaf 583 };
3157f602 584
cc61c64b 585 invoc.expansion_data.mark.set_expn_info(ExpnInfo {
9e0c209e 586 call_site: span,
3157f602 587 callee: NameAndSpan {
abe05a73 588 format: macro_bang_format(path),
3157f602 589 span: tt_span,
3b2f2976
XL
590 allow_internal_unstable,
591 allow_internal_unsafe: false,
223e47cc 592 }
3157f602
XL
593 });
594
041b39d2 595 let input: Vec<_> = mac.node.stream().into_trees().collect();
8bb4bdeb 596 kind.make_from(expander.expand(self.cx, span, ident, input))
3157f602
XL
597 }
598
3b2f2976 599 MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
9e0c209e 600 self.cx.span_err(path.span,
cc61c64b 601 &format!("`{}` can only be used in attributes", path));
ea8adc8c 602 self.cx.trace_macros_diag();
9e0c209e
SL
603 return kind.dummy(span);
604 }
3157f602 605
3b2f2976 606 ProcMacroDerive(..) | BuiltinDerive(..) => {
cc61c64b 607 self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
ea8adc8c 608 self.cx.trace_macros_diag();
c30ab7b3
SL
609 return kind.dummy(span);
610 }
611
3b2f2976 612 ProcMacro(ref expandfun) => {
9e0c209e
SL
613 if ident.name != keywords::Invalid.name() {
614 let msg =
cc61c64b 615 format!("macro {}! expects no ident argument, given '{}'", path, ident);
9e0c209e 616 self.cx.span_err(path.span, &msg);
ea8adc8c 617 self.cx.trace_macros_diag();
9e0c209e
SL
618 return kind.dummy(span);
619 }
620
cc61c64b 621 invoc.expansion_data.mark.set_expn_info(ExpnInfo {
9e0c209e 622 call_site: span,
3157f602 623 callee: NameAndSpan {
abe05a73 624 format: macro_bang_format(path),
9e0c209e
SL
625 // FIXME procedural macros do not have proper span info
626 // yet, when they do, we should use it here.
3157f602 627 span: None,
9e0c209e 628 // FIXME probably want to follow macro_rules macros here.
3157f602 629 allow_internal_unstable: false,
3b2f2976 630 allow_internal_unsafe: false,
9e0c209e 631 },
3157f602
XL
632 });
633
041b39d2 634 let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
cc61c64b 635 Some(self.parse_expansion(tok_result, kind, path, span))
b039eaaf 636 }
9e0c209e 637 };
3157f602 638
041b39d2 639 unwrap_or!(opt_expanded, {
9e0c209e
SL
640 let msg = format!("non-{kind} macro in {kind} position: {name}",
641 name = path.segments[0].identifier.name, kind = kind.name());
642 self.cx.span_err(path.span, &msg);
ea8adc8c 643 self.cx.trace_macros_diag();
041b39d2
XL
644 kind.dummy(span)
645 })
9e0c209e 646 }
1a4d82fc 647
8bb4bdeb
XL
648 /// Expand a derive invocation. Returns the result of expansion.
649 fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
650 let Invocation { expansion_kind: kind, .. } = invoc;
cc61c64b
XL
651 let (path, item) = match invoc.kind {
652 InvocationKind::Derive { path, item } => (path, item),
8bb4bdeb
XL
653 _ => unreachable!(),
654 };
655
cc61c64b
XL
656 let pretty_name = Symbol::intern(&format!("derive({})", path));
657 let span = path.span;
658 let attr = ast::Attribute {
3b2f2976
XL
659 path, span,
660 tokens: TokenStream::empty(),
cc61c64b
XL
661 // irrelevant:
662 id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
663 };
8bb4bdeb 664
cc61c64b 665 let mut expn_info = ExpnInfo {
8bb4bdeb
XL
666 call_site: span,
667 callee: NameAndSpan {
668 format: MacroAttribute(pretty_name),
cc61c64b 669 span: None,
8bb4bdeb 670 allow_internal_unstable: false,
3b2f2976 671 allow_internal_unsafe: false,
8bb4bdeb 672 }
cc61c64b 673 };
8bb4bdeb
XL
674
675 match *ext {
3b2f2976 676 ProcMacroDerive(ref ext, _) => {
cc61c64b 677 invoc.expansion_data.mark.set_expn_info(expn_info);
ea8adc8c 678 let span = span.with_ctxt(self.cx.backtrace());
cc61c64b
XL
679 let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
680 name: keywords::Invalid.name(),
681 span: DUMMY_SP,
682 node: ast::MetaItemKind::Word,
8bb4bdeb 683 };
cc61c64b 684 kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item))
8bb4bdeb 685 }
3b2f2976 686 BuiltinDerive(func) => {
cc61c64b
XL
687 expn_info.callee.allow_internal_unstable = true;
688 invoc.expansion_data.mark.set_expn_info(expn_info);
ea8adc8c 689 let span = span.with_ctxt(self.cx.backtrace());
8bb4bdeb 690 let mut items = Vec::new();
cc61c64b
XL
691 func(self.cx, span, &attr.meta().unwrap(), &item, &mut |a| items.push(a));
692 kind.expect_from_annotatables(items)
8bb4bdeb
XL
693 }
694 _ => {
cc61c64b 695 let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
7cac9316 696 self.cx.span_err(span, msg);
ea8adc8c 697 self.cx.trace_macros_diag();
8bb4bdeb
XL
698 kind.dummy(span)
699 }
700 }
701 }
702
cc61c64b 703 fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, path: &Path, span: Span)
9e0c209e 704 -> Expansion {
8bb4bdeb 705 let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
9e0c209e
SL
706 let expansion = match parser.parse_expansion(kind, false) {
707 Ok(expansion) => expansion,
708 Err(mut err) => {
9cc50fc6 709 err.emit();
ea8adc8c 710 self.cx.trace_macros_diag();
9e0c209e 711 return kind.dummy(span);
1a4d82fc
JJ
712 }
713 };
cc61c64b 714 parser.ensure_complete_parse(path, kind.name(), span);
041b39d2 715 expansion
9e0c209e
SL
716 }
717}
970d7e83 718
9e0c209e
SL
719impl<'a> Parser<'a> {
720 pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bool)
721 -> PResult<'a, Expansion> {
722 Ok(match kind {
723 ExpansionKind::Items => {
476ff2be 724 let mut items = SmallVector::new();
9e0c209e
SL
725 while let Some(item) = self.parse_item()? {
726 items.push(item);
727 }
728 Expansion::Items(items)
729 }
730 ExpansionKind::TraitItems => {
476ff2be 731 let mut items = SmallVector::new();
9e0c209e 732 while self.token != token::Eof {
cc61c64b 733 items.push(self.parse_trait_item(&mut false)?);
9e0c209e
SL
734 }
735 Expansion::TraitItems(items)
736 }
737 ExpansionKind::ImplItems => {
476ff2be 738 let mut items = SmallVector::new();
9e0c209e 739 while self.token != token::Eof {
cc61c64b 740 items.push(self.parse_impl_item(&mut false)?);
9e0c209e
SL
741 }
742 Expansion::ImplItems(items)
743 }
744 ExpansionKind::Stmts => {
476ff2be
SL
745 let mut stmts = SmallVector::new();
746 while self.token != token::Eof &&
747 // won't make progress on a `}`
748 self.token != token::CloseDelim(token::Brace) {
9e0c209e
SL
749 if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? {
750 stmts.push(stmt);
751 }
752 }
753 Expansion::Stmts(stmts)
223e47cc 754 }
9e0c209e
SL
755 ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
756 ExpansionKind::OptExpr => Expansion::OptExpr(Some(self.parse_expr()?)),
cc61c64b 757 ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
9e0c209e
SL
758 ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
759 })
760 }
761
cc61c64b 762 pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) {
9e0c209e
SL
763 if self.token != token::Eof {
764 let msg = format!("macro expansion ignores token `{}` and any following",
765 self.this_token_to_string());
ea8adc8c
XL
766 // Avoid emitting backtrace info twice.
767 let def_site_span = self.span.with_ctxt(SyntaxContext::empty());
041b39d2 768 let mut err = self.diagnostic().struct_span_err(def_site_span, &msg);
9e0c209e
SL
769 let msg = format!("caused by the macro expansion here; the usage \
770 of `{}!` is likely invalid in {} context",
cc61c64b 771 macro_path, kind_name);
9e0c209e 772 err.span_note(span, &msg).emit();
1a4d82fc
JJ
773 }
774 }
1a4d82fc
JJ
775}
776
9e0c209e
SL
777struct InvocationCollector<'a, 'b: 'a> {
778 cx: &'a mut ExtCtxt<'b>,
779 cfg: StripUnconfigured<'a>,
780 invocations: Vec<Invocation>,
781 monotonic: bool,
782}
223e47cc 783
9e0c209e
SL
784impl<'a, 'b> InvocationCollector<'a, 'b> {
785 fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
7cac9316 786 let mark = Mark::fresh(self.cx.current_expansion.mark);
9e0c209e 787 self.invocations.push(Invocation {
3b2f2976
XL
788 kind,
789 expansion_kind,
c30ab7b3 790 expansion_data: ExpansionData {
3b2f2976 791 mark,
c30ab7b3
SL
792 depth: self.cx.current_expansion.depth + 1,
793 ..self.cx.current_expansion.clone()
794 },
9e0c209e 795 });
cc61c64b 796 placeholder(expansion_kind, NodeId::placeholder_from_mark(mark))
1a4d82fc 797 }
223e47cc 798
32a655c1
SL
799 fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion {
800 self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
9e0c209e 801 }
85aaf69f 802
8bb4bdeb
XL
803 fn collect_attr(&mut self,
804 attr: Option<ast::Attribute>,
cc61c64b 805 traits: Vec<Path>,
8bb4bdeb
XL
806 item: Annotatable,
807 kind: ExpansionKind)
9e0c209e 808 -> Expansion {
3b2f2976 809 self.collect(kind, InvocationKind::Attr { attr, traits, item })
9e0c209e 810 }
3157f602 811
9e0c209e 812 // If `item` is an attr invocation, remove and return the macro attribute.
cc61c64b 813 fn classify_item<T>(&mut self, mut item: T) -> (Option<ast::Attribute>, Vec<Path>, T)
8bb4bdeb
XL
814 where T: HasAttrs,
815 {
816 let (mut attr, mut traits) = (None, Vec::new());
817
9e0c209e 818 item = item.map_attrs(|mut attrs| {
8bb4bdeb
XL
819 if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs) {
820 attr = Some(legacy_attr_invoc);
821 return attrs;
822 }
823
824 if self.cx.ecfg.proc_macro_enabled() {
825 attr = find_attr_invoc(&mut attrs);
826 }
827 traits = collect_derives(&mut self.cx, &mut attrs);
9e0c209e
SL
828 attrs
829 });
8bb4bdeb
XL
830
831 (attr, traits, item)
9e0c209e 832 }
c34b1796 833
9e0c209e
SL
834 fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
835 self.cfg.configure(node)
d9579d0f 836 }
32a655c1
SL
837
838 // Detect use of feature-gated or invalid attributes on macro invocations
839 // since they will not be detected after macro expansion.
840 fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
32a655c1
SL
841 let features = self.cx.ecfg.features.unwrap();
842 for attr in attrs.iter() {
7cac9316 843 feature_gate::check_attribute(attr, self.cx.parse_sess, features);
32a655c1
SL
844 }
845 }
85aaf69f
SL
846}
847
8bb4bdeb 848pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
7cac9316
XL
849 attrs.iter()
850 .position(|a| !attr::is_known(a) && !is_builtin_attr(a))
851 .map(|i| attrs.remove(i))
8bb4bdeb
XL
852}
853
9e0c209e
SL
854impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
855 fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
856 let mut expr = self.cfg.configure_expr(expr).unwrap();
857 expr.node = self.cfg.configure_expr_kind(expr.node);
858
859 if let ast::ExprKind::Mac(mac) = expr.node {
32a655c1
SL
860 self.check_attributes(&expr.attrs);
861 self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr()
9e0c209e
SL
862 } else {
863 P(noop_fold_expr(expr, self))
223e47cc 864 }
c34b1796 865 }
223e47cc 866
9e0c209e
SL
867 fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
868 let mut expr = configure!(self, expr).unwrap();
869 expr.node = self.cfg.configure_expr_kind(expr.node);
870
871 if let ast::ExprKind::Mac(mac) = expr.node {
32a655c1
SL
872 self.check_attributes(&expr.attrs);
873 self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr()
9e0c209e
SL
874 } else {
875 Some(P(noop_fold_expr(expr, self)))
3157f602 876 }
3157f602 877 }
3157f602 878
9e0c209e 879 fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
32a655c1 880 let pat = self.cfg.configure_pat(pat);
9e0c209e
SL
881 match pat.node {
882 PatKind::Mac(_) => {}
883 _ => return noop_fold_pat(pat, self),
e9174d1e 884 }
e9174d1e 885
9e0c209e 886 pat.and_then(|pat| match pat.node {
32a655c1 887 PatKind::Mac(mac) => self.collect_bang(mac, pat.span, ExpansionKind::Pat).make_pat(),
9e0c209e
SL
888 _ => unreachable!(),
889 })
890 }
e9174d1e 891
9e0c209e
SL
892 fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
893 let stmt = match self.cfg.configure_stmt(stmt) {
894 Some(stmt) => stmt,
476ff2be 895 None => return SmallVector::new(),
9e0c209e 896 };
1a4d82fc 897
9e0c209e
SL
898 let (mac, style, attrs) = if let StmtKind::Mac(mac) = stmt.node {
899 mac.unwrap()
900 } else {
901 // The placeholder expander gives ids to statements, so we avoid folding the id here.
902 let ast::Stmt { id, node, span } = stmt;
903 return noop_fold_stmt_kind(node, self).into_iter().map(|node| {
904 ast::Stmt { id: id, node: node, span: span }
905 }).collect()
906 };
907
32a655c1
SL
908 self.check_attributes(&attrs);
909 let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts).make_stmts();
9e0c209e
SL
910
911 // If this is a macro invocation with a semicolon, then apply that
912 // semicolon to the final statement produced by expansion.
913 if style == MacStmtStyle::Semicolon {
914 if let Some(stmt) = placeholder.pop() {
915 placeholder.push(stmt.add_trailing_semicolon());
916 }
5bcae85e 917 }
9e0c209e
SL
918
919 placeholder
1a4d82fc 920 }
3157f602 921
9e0c209e 922 fn fold_block(&mut self, block: P<Block>) -> P<Block> {
476ff2be
SL
923 let old_directory_ownership = self.cx.current_expansion.directory_ownership;
924 self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
9e0c209e 925 let result = noop_fold_block(block, self);
476ff2be 926 self.cx.current_expansion.directory_ownership = old_directory_ownership;
9e0c209e 927 result
3157f602
XL
928 }
929
9e0c209e
SL
930 fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
931 let item = configure!(self, item);
932
8bb4bdeb
XL
933 let (attr, traits, mut item) = self.classify_item(item);
934 if attr.is_some() || !traits.is_empty() {
ea8adc8c 935 let item = Annotatable::Item(item);
8bb4bdeb 936 return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items();
3157f602
XL
937 }
938
9e0c209e
SL
939 match item.node {
940 ast::ItemKind::Mac(..) => {
32a655c1 941 self.check_attributes(&item.attrs);
8bb4bdeb 942 item.and_then(|item| match item.node {
9e0c209e
SL
943 ItemKind::Mac(mac) => {
944 self.collect(ExpansionKind::Items, InvocationKind::Bang {
3b2f2976 945 mac,
9e0c209e
SL
946 ident: Some(item.ident),
947 span: item.span,
948 }).make_items()
949 }
950 _ => unreachable!(),
951 })
3157f602 952 }
9e0c209e
SL
953 ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
954 if item.ident == keywords::Invalid.ident() {
955 return noop_fold_item(item, self);
956 }
3157f602 957
476ff2be 958 let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
9e0c209e
SL
959 let mut module = (*self.cx.current_expansion.module).clone();
960 module.mod_path.push(item.ident);
1a4d82fc 961
9e0c209e
SL
962 // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`).
963 // In the non-inline case, `inner` is never the dummy span (c.f. `parse_item_mod`).
964 // Thus, if `inner` is the dummy span, we know the module is inline.
cc61c64b 965 let inline_module = item.span.contains(inner) || inner == DUMMY_SP;
54a0048b 966
9e0c209e 967 if inline_module {
c30ab7b3 968 if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
476ff2be
SL
969 self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned;
970 module.directory.push(&*path.as_str());
c30ab7b3
SL
971 } else {
972 module.directory.push(&*item.ident.name.as_str());
973 }
9e0c209e 974 } else {
ea8adc8c 975 let mut path = self.cx.parse_sess.codemap().span_to_unmapped_path(inner);
476ff2be
SL
976 let directory_ownership = match path.file_name().unwrap().to_str() {
977 Some("mod.rs") => DirectoryOwnership::Owned,
978 _ => DirectoryOwnership::UnownedViaMod(false),
979 };
980 path.pop();
981 module.directory = path;
982 self.cx.current_expansion.directory_ownership = directory_ownership;
9e0c209e 983 }
3157f602 984
9e0c209e
SL
985 let orig_module =
986 mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
987 let result = noop_fold_item(item, self);
988 self.cx.current_expansion.module = orig_module;
476ff2be 989 self.cx.current_expansion.directory_ownership = orig_directory_ownership;
7cac9316 990 result
9e0c209e 991 }
c30ab7b3
SL
992 // Ensure that test functions are accessible from the test harness.
993 ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
994 if item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
995 item = item.map(|mut item| { item.vis = ast::Visibility::Public; item });
996 }
997 noop_fold_item(item, self)
998 }
9e0c209e
SL
999 _ => noop_fold_item(item, self),
1000 }
1a4d82fc
JJ
1001 }
1002
9e0c209e
SL
1003 fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
1004 let item = configure!(self, item);
1a4d82fc 1005
8bb4bdeb
XL
1006 let (attr, traits, item) = self.classify_item(item);
1007 if attr.is_some() || !traits.is_empty() {
ea8adc8c 1008 let item = Annotatable::TraitItem(P(item));
8bb4bdeb
XL
1009 return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
1010 .make_trait_items()
9e0c209e
SL
1011 }
1012
1013 match item.node {
1014 ast::TraitItemKind::Macro(mac) => {
1015 let ast::TraitItem { attrs, span, .. } = item;
32a655c1
SL
1016 self.check_attributes(&attrs);
1017 self.collect_bang(mac, span, ExpansionKind::TraitItems).make_trait_items()
54a0048b 1018 }
9e0c209e 1019 _ => fold::noop_fold_trait_item(item, self),
54a0048b 1020 }
1a4d82fc
JJ
1021 }
1022
9e0c209e
SL
1023 fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem> {
1024 let item = configure!(self, item);
1a4d82fc 1025
8bb4bdeb
XL
1026 let (attr, traits, item) = self.classify_item(item);
1027 if attr.is_some() || !traits.is_empty() {
ea8adc8c 1028 let item = Annotatable::ImplItem(P(item));
8bb4bdeb
XL
1029 return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems)
1030 .make_impl_items();
9e0c209e 1031 }
1a4d82fc 1032
9e0c209e
SL
1033 match item.node {
1034 ast::ImplItemKind::Macro(mac) => {
1035 let ast::ImplItem { attrs, span, .. } = item;
32a655c1
SL
1036 self.check_attributes(&attrs);
1037 self.collect_bang(mac, span, ExpansionKind::ImplItems).make_impl_items()
9e0c209e
SL
1038 }
1039 _ => fold::noop_fold_impl_item(item, self),
1040 }
85aaf69f
SL
1041 }
1042
9e0c209e
SL
1043 fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
1044 let ty = match ty.node {
1045 ast::TyKind::Mac(_) => ty.unwrap(),
1046 _ => return fold::noop_fold_ty(ty, self),
1047 };
1048
1049 match ty.node {
32a655c1 1050 ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, ExpansionKind::Ty).make_ty(),
9e0c209e
SL
1051 _ => unreachable!(),
1052 }
1a4d82fc
JJ
1053 }
1054
9e0c209e
SL
1055 fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod {
1056 noop_fold_foreign_mod(self.cfg.configure_foreign_mod(foreign_mod), self)
e9174d1e 1057 }
970d7e83 1058
9e0c209e 1059 fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
8bb4bdeb
XL
1060 match item {
1061 ast::ItemKind::MacroDef(..) => item,
1062 _ => noop_fold_item_kind(self.cfg.configure_item_kind(item), self),
1063 }
54a0048b
SL
1064 }
1065
9e0c209e
SL
1066 fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
1067 if self.monotonic {
1068 assert_eq!(id, ast::DUMMY_NODE_ID);
1069 self.cx.resolver.next_node_id()
1070 } else {
1071 id
1072 }
54a0048b
SL
1073 }
1074}
1075
85aaf69f 1076pub struct ExpansionConfig<'feat> {
1a4d82fc 1077 pub crate_name: String,
85aaf69f
SL
1078 pub features: Option<&'feat Features>,
1079 pub recursion_limit: usize,
d9579d0f 1080 pub trace_mac: bool,
3157f602 1081 pub should_test: bool, // If false, strip `#[test]` nodes
9e0c209e
SL
1082 pub single_step: bool,
1083 pub keep_macs: bool,
1a4d82fc
JJ
1084}
1085
c34b1796
AL
1086macro_rules! feature_tests {
1087 ($( fn $getter:ident = $field:ident, )*) => {
1088 $(
1089 pub fn $getter(&self) -> bool {
1090 match self.features {
1091 Some(&Features { $field: true, .. }) => true,
1092 _ => false,
1093 }
1094 }
1095 )*
1096 }
1097}
1098
85aaf69f
SL
1099impl<'feat> ExpansionConfig<'feat> {
1100 pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1a4d82fc 1101 ExpansionConfig {
3b2f2976 1102 crate_name,
85aaf69f 1103 features: None,
7cac9316 1104 recursion_limit: 1024,
d9579d0f 1105 trace_mac: false,
3157f602 1106 should_test: false,
9e0c209e
SL
1107 single_step: false,
1108 keep_macs: false,
1a4d82fc 1109 }
970d7e83 1110 }
85aaf69f 1111
c34b1796 1112 feature_tests! {
a7813a04
XL
1113 fn enable_quotes = quote,
1114 fn enable_asm = asm,
cc61c64b 1115 fn enable_global_asm = global_asm,
a7813a04
XL
1116 fn enable_log_syntax = log_syntax,
1117 fn enable_concat_idents = concat_idents,
1118 fn enable_trace_macros = trace_macros,
c34b1796 1119 fn enable_allow_internal_unstable = allow_internal_unstable,
a7813a04 1120 fn enable_custom_derive = custom_derive,
8bb4bdeb 1121 fn proc_macro_enabled = proc_macro,
85aaf69f 1122 }
970d7e83
LB
1123}
1124
cc61c64b 1125// A Marker adds the given mark to the syntax context.
3b2f2976 1126#[derive(Debug)]
041b39d2 1127pub struct Marker(pub Mark);
1a4d82fc
JJ
1128
1129impl Folder for Marker {
5bcae85e 1130 fn fold_ident(&mut self, mut ident: Ident) -> Ident {
cc61c64b 1131 ident.ctxt = ident.ctxt.apply_mark(self.0);
5bcae85e 1132 ident
1a4d82fc 1133 }
1a4d82fc 1134
ea8adc8c
XL
1135 fn new_span(&mut self, span: Span) -> Span {
1136 span.with_ctxt(span.ctxt().apply_mark(self.0))
3157f602 1137 }
cc61c64b
XL
1138
1139 fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
1140 noop_fold_mac(mac, self)
1141 }
1a4d82fc 1142}