expand.rs 68.5 KB
Newer Older
S
Steven Fackler 已提交
1
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9 10
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use ast::{self, Block, Ident, NodeId, PatKind, Path};
J
Jeffrey Seyfried 已提交
12
use ast::{MacStmtStyle, StmtKind, ItemKind};
13
use attr::{self, HasAttrs};
D
Donato Sciarra 已提交
14
use source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
15
use config::{is_test_or_bench, StripUnconfigured};
16
use errors::{Applicability, FatalError};
P
Patrick Walton 已提交
17
use ext::base::*;
18
use ext::build::AstBuilder;
19
use ext::derive::{add_derived_markers, collect_derives};
20
use ext::hygiene::{self, Mark, SyntaxContext};
21
use ext::placeholders::{placeholder, PlaceholderExpander};
22
use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
J
John Clements 已提交
23
use fold;
24
use fold::*;
25
use parse::{DirectoryOwnership, PResult, ParseSess};
J
Jeffrey Seyfried 已提交
26
use parse::token::{self, Token};
N
Nick Cameron 已提交
27
use parse::parser::Parser;
28
use ptr::P;
29
use OneVector;
30
use symbol::Symbol;
31
use symbol::keywords;
32
use syntax_pos::{Span, DUMMY_SP, FileName};
33
use syntax_pos::hygiene::ExpnFormat;
J
Jeffrey Seyfried 已提交
34
use tokenstream::{TokenStream, TokenTree};
35
use visit::{self, Visitor};
36

37
use std::collections::HashMap;
38 39
use std::fs::File;
use std::io::Read;
40
use std::iter::FromIterator;
41
use std::{iter, mem};
J
Jeffrey Seyfried 已提交
42
use std::rc::Rc;
43
use std::path::PathBuf;
44

45
macro_rules! ast_fragments {
46 47 48
    (
        $($Kind:ident($AstTy:ty) {
            $kind_name:expr;
49 50 51 52
            // FIXME: HACK: this should be `$(one ...)?` and `$(many ...)?` but `?` macro
            // repetition was removed from 2015 edition in #51587 because of ambiguities.
            $(one fn $fold_ast:ident; fn $visit_ast:ident;)*
            $(many fn $fold_ast_elt:ident; fn $visit_ast_elt:ident;)*
53 54 55
            fn $make_ast:ident;
        })*
    ) => {
56 57
        /// A fragment of AST that can be produced by a single macro expansion.
        /// Can also serve as an input and intermediate result for macro expansion operations.
58 59 60 61
        pub enum AstFragment {
            OptExpr(Option<P<ast::Expr>>),
            $($Kind($AstTy),)*
        }
62 63

        /// "Discriminant" of an AST fragment.
64
        #[derive(Copy, Clone, PartialEq, Eq)]
65 66 67 68
        pub enum AstFragmentKind {
            OptExpr,
            $($Kind,)*
        }
69

70
        impl AstFragmentKind {
71
            pub fn name(self) -> &'static str {
72
                match self {
73
                    AstFragmentKind::OptExpr => "expression",
74
                    $(AstFragmentKind::$Kind => $kind_name,)*
75 76
                }
            }
J
Jeffrey Seyfried 已提交
77

78
            fn make_from<'a>(self, result: Box<dyn MacResult + 'a>) -> Option<AstFragment> {
79
                match self {
80 81
                    AstFragmentKind::OptExpr =>
                        result.make_expr().map(Some).map(AstFragment::OptExpr),
82
                    $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
83 84 85
                }
            }
        }
86

87
        impl AstFragment {
88
            pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
89
                match self {
90 91
                    AstFragment::OptExpr(expr) => expr,
                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
92 93
                }
            }
94 95

            $(pub fn $make_ast(self) -> $AstTy {
96
                match self {
97
                    AstFragment::$Kind(ast) => ast,
98
                    _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
99
                }
100
            })*
101

102
            pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
103
                match self {
104 105 106
                    AstFragment::OptExpr(expr) =>
                        AstFragment::OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
                    $($(AstFragment::$Kind(ast) =>
107
                        AstFragment::$Kind(folder.$fold_ast(ast)),)*)*
108 109 110
                    $($(AstFragment::$Kind(ast) =>
                        AstFragment::$Kind(ast.into_iter()
                                              .flat_map(|ast| folder.$fold_ast_elt(ast))
111
                                              .collect()),)*)*
112
                }
113
            }
114

115
            pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
116
                match *self {
117 118
                    AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
                    AstFragment::OptExpr(None) => {}
119
                    $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)*)*
120 121
                    $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
                        visitor.$visit_ast_elt(ast_elt);
122
                    })*)*
123 124
                }
            }
125
        }
126 127 128

        impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
            fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
129
                self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr()
130
            }
131 132
            $($(fn $fold_ast(&mut self, ast: $AstTy) -> $AstTy {
                self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()
133
            })*)*
134
            $($(fn $fold_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
135
                self.expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast()
136
            })*)*
137
        }
138 139

        impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
140 141 142
            $(fn $make_ast(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>)
                           -> Option<$AstTy> {
                Some(self.make(AstFragmentKind::$Kind).$make_ast())
143 144
            })*
        }
145
    }
146 147
}

148
ast_fragments! {
149 150 151
    Expr(P<ast::Expr>) { "expression"; one fn fold_expr; fn visit_expr; fn make_expr; }
    Pat(P<ast::Pat>) { "pattern"; one fn fold_pat; fn visit_pat; fn make_pat; }
    Ty(P<ast::Ty>) { "type"; one fn fold_ty; fn visit_ty; fn make_ty; }
152 153 154
    Stmts(OneVector<ast::Stmt>) { "statement"; many fn fold_stmt; fn visit_stmt; fn make_stmts; }
    Items(OneVector<P<ast::Item>>) { "item"; many fn fold_item; fn visit_item; fn make_items; }
    TraitItems(OneVector<ast::TraitItem>) {
155 156
        "trait item"; many fn fold_trait_item; fn visit_trait_item; fn make_trait_items;
    }
157
    ImplItems(OneVector<ast::ImplItem>) {
158 159
        "impl item"; many fn fold_impl_item; fn visit_impl_item; fn make_impl_items;
    }
160
    ForeignItems(OneVector<ast::ForeignItem>) {
161 162
        "foreign item"; many fn fold_foreign_item; fn visit_foreign_item; fn make_foreign_items;
    }
163 164
}

165 166
impl AstFragmentKind {
    fn dummy(self, span: Span) -> Option<AstFragment> {
167
        self.make_from(DummyResult::any(span))
168
    }
169

170 171
    fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
                                                                     -> AstFragment {
172
        let mut items = items.into_iter();
173
        match self {
174 175 176 177 178 179 180 181 182 183 184
            AstFragmentKind::Items =>
                AstFragment::Items(items.map(Annotatable::expect_item).collect()),
            AstFragmentKind::ImplItems =>
                AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
            AstFragmentKind::TraitItems =>
                AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
            AstFragmentKind::ForeignItems =>
                AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
            AstFragmentKind::Stmts =>
                AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect()),
            AstFragmentKind::Expr => AstFragment::Expr(
185 186
                items.next().expect("expected exactly one expression").expect_expr()
            ),
187 188 189
            AstFragmentKind::OptExpr =>
                AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)),
            AstFragmentKind::Pat | AstFragmentKind::Ty =>
190
                panic!("patterns and types aren't annotatable"),
191 192
        }
    }
193
}
194

195 196 197 198 199 200 201 202 203 204
fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
    // We don't want to format a path using pretty-printing,
    // `format!("{}", path)`, because that tries to insert
    // line-breaks and is slow.
    let mut path_str = String::with_capacity(64);
    for (i, segment) in path.segments.iter().enumerate() {
        if i != 0 {
            path_str.push_str("::");
        }

205 206
        if segment.ident.name != keywords::CrateRoot.name() &&
            segment.ident.name != keywords::DollarCrate.name()
207
        {
V
Vadim Petrochenkov 已提交
208
            path_str.push_str(&segment.ident.as_str())
209 210 211 212 213 214
        }
    }

    MacroBang(Symbol::intern(&path_str))
}

215
pub struct Invocation {
216
    pub kind: InvocationKind,
217
    fragment_kind: AstFragmentKind,
218
    pub expansion_data: ExpansionData,
219 220
}

221
pub enum InvocationKind {
222 223 224 225 226 227
    Bang {
        mac: ast::Mac,
        ident: Option<Ident>,
        span: Span,
    },
    Attr {
228
        attr: Option<ast::Attribute>,
J
Jeffrey Seyfried 已提交
229
        traits: Vec<Path>,
230 231
        item: Annotatable,
    },
232
    Derive {
J
Jeffrey Seyfried 已提交
233
        path: Path,
234 235
        item: Annotatable,
    },
236
}
237

238
impl Invocation {
239
    pub fn span(&self) -> Span {
240 241
        match self.kind {
            InvocationKind::Bang { span, .. } => span,
242
            InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,
J
Jeffrey Seyfried 已提交
243 244
            InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
            InvocationKind::Derive { ref path, .. } => path.span,
245 246 247 248
        }
    }
}

249
pub struct MacroExpander<'a, 'b:'a> {
250
    pub cx: &'a mut ExtCtxt<'b>,
251
    monotonic: bool, // c.f. `cx.monotonic_expander()`
N
Nick Cameron 已提交
252 253 254
}

impl<'a, 'b> MacroExpander<'a, 'b> {
255
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
256
        MacroExpander { cx: cx, monotonic: monotonic }
N
Nick Cameron 已提交
257
    }
258

259 260
    pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
        let mut module = ModuleData {
261
            mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
D
Donato Sciarra 已提交
262
            directory: match self.cx.source_map().span_to_unmapped_path(krate.span) {
263 264 265
                FileName::Real(path) => path,
                other => PathBuf::from(other.to_string()),
            },
266 267
        };
        module.directory.pop();
268
        self.cx.root_path = module.directory.clone();
269
        self.cx.current_expansion.module = Rc::new(module);
270
        self.cx.current_expansion.crate_span = Some(krate.span);
271

272 273
        let orig_mod_span = krate.module.inner;

274
        let krate_item = AstFragment::Items(smallvec![P(ast::Item {
275 276 277 278 279
            attrs: krate.attrs,
            span: krate.span,
            node: ast::ItemKind::Mod(krate.module),
            ident: keywords::Invalid.ident(),
            id: ast::DUMMY_NODE_ID,
280
            vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
281
            tokens: None,
282
        })]);
283

284
        match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
285
            Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
286 287 288
                krate.attrs = attrs;
                krate.module = module;
            },
289 290 291 292 293 294 295 296
            None => {
                // Resolution failed so we return an empty expansion
                krate.attrs = vec![];
                krate.module = ast::Mod {
                    inner: orig_mod_span,
                    items: vec![],
                };
            },
297 298
            _ => unreachable!(),
        };
299
        self.cx.trace_macros_diag();
300 301 302
        krate
    }

303
    // Fully expand all macro invocations in this AST fragment.
304
    fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
305 306 307
        let orig_expansion_data = self.cx.current_expansion.clone();
        self.cx.current_expansion.depth = 0;

308
        // Collect all macro invocations and replace them with placeholders.
309 310
        let (fragment_with_placeholders, mut invocations)
            = self.collect_invocations(input_fragment, &[]);
311 312 313

        // Optimization: if we resolve all imports now,
        // we'll be able to immediately resolve most of imported macros.
314
        self.resolve_imports();
315

M
Matthias Krüger 已提交
316
        // Resolve paths in all invocations and produce output expanded fragments for them, but
317 318 319 320
        // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
        // The output fragments also go through expansion recursively until no invocations are left.
        // Unresolved macros produce dummy outputs as a recovery measure.
        invocations.reverse();
321
        let mut expanded_fragments = Vec::new();
322
        let mut derives: HashMap<Mark, Vec<_>> = HashMap::new();
323 324 325
        let mut undetermined_invocations = Vec::new();
        let (mut progress, mut force) = (false, !self.monotonic);
        loop {
326
            let invoc = if let Some(invoc) = invocations.pop() {
327 328
                invoc
            } else {
329 330
                self.resolve_imports();
                if undetermined_invocations.is_empty() { break }
331 332 333 334 335 336 337
                invocations = mem::replace(&mut undetermined_invocations, Vec::new());
                force = !mem::replace(&mut progress, false);
                continue
            };

            let scope =
                if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
338
            let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) {
339 340 341 342 343 344 345 346 347
                Ok(ext) => Some(ext),
                Err(Determinacy::Determined) => None,
                Err(Determinacy::Undetermined) => {
                    undetermined_invocations.push(invoc);
                    continue
                }
            };

            progress = true;
348 349
            let ExpansionData { depth, mark, .. } = invoc.expansion_data;
            self.cx.current_expansion = invoc.expansion_data.clone();
350

351
            self.cx.current_expansion.mark = scope;
352
            // FIXME(jseyfried): Refactor out the following logic
353
            let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
354
                if let Some(ext) = ext {
355 356 357
                    let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
                    let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
                    self.collect_invocations(fragment, &[])
358
                } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
359 360
                    if !item.derive_allowed() {
                        let attr = attr::find_by_name(item.attrs(), "derive")
361 362 363 364 365 366 367
                            .expect("`derive` attribute should exist");
                        let span = attr.span;
                        let mut err = self.cx.mut_span_err(span,
                                                           "`derive` may only be applied to \
                                                            structs, enums and unions");
                        if let ast::AttrStyle::Inner = attr.style {
                            let trait_list = traits.iter()
L
ljedrz 已提交
368
                                .map(|t| t.to_string()).collect::<Vec<_>>();
369
                            let suggestion = format!("#[derive({})]", trait_list.join(", "));
370 371 372 373 374
                            err.span_suggestion_with_applicability(
                                span, "try an outer attribute", suggestion,
                                // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
                                Applicability::MaybeIncorrect
                            );
375 376
                        }
                        err.emit();
377 378
                    }

379
                    let item = self.fully_configure(item)
380
                        .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
381
                    let item_with_markers =
382
                        add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
383
                    let derives = derives.entry(invoc.expansion_data.mark).or_default();
384

J
Jeffrey Seyfried 已提交
385
                    for path in &traits {
J
Jeffrey Seyfried 已提交
386
                        let mark = Mark::fresh(self.cx.current_expansion.mark);
387
                        derives.push(mark);
388 389
                        let item = match self.cx.resolver.resolve_macro_path(
                                path, MacroKind::Derive, Mark::root(), &[], false) {
390
                            Ok(ext) => match *ext {
391
                                BuiltinDerive(..) => item_with_markers.clone(),
392 393 394 395 396
                                _ => item.clone(),
                            },
                            _ => item.clone(),
                        };
                        invocations.push(Invocation {
J
Jeffrey Seyfried 已提交
397
                            kind: InvocationKind::Derive { path: path.clone(), item: item },
398
                            fragment_kind: invoc.fragment_kind,
399
                            expansion_data: ExpansionData {
400
                                mark,
401 402 403 404
                                ..invoc.expansion_data.clone()
                            },
                        });
                    }
405
                    let fragment = invoc.fragment_kind
406
                        .expect_from_annotatables(::std::iter::once(item_with_markers));
407
                    self.collect_invocations(fragment, derives)
408 409 410 411
                } else {
                    unreachable!()
                }
            } else {
412
                self.collect_invocations(invoc.fragment_kind.dummy(invoc.span()).unwrap(), &[])
413
            };
414

415 416
            if expanded_fragments.len() < depth {
                expanded_fragments.push(Vec::new());
417
            }
418
            expanded_fragments[depth - 1].push((mark, expanded_fragment));
419
            if !self.cx.ecfg.single_step {
420 421 422 423
                invocations.extend(new_invocations.into_iter().rev());
            }
        }

424 425
        self.cx.current_expansion = orig_expansion_data;

426
        // Finally incorporate all the expanded macros into the input AST fragment.
427
        let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
428 429
        while let Some(expanded_fragments) = expanded_fragments.pop() {
            for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() {
430
                let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
431 432
                placeholder_expander.add(NodeId::placeholder_from_mark(mark),
                                         expanded_fragment, derives);
433 434
            }
        }
435
        fragment_with_placeholders.fold_with(&mut placeholder_expander)
436 437
    }

438 439 440 441 442 443 444 445
    fn resolve_imports(&mut self) {
        if self.monotonic {
            let err_count = self.cx.parse_sess.span_diagnostic.err_count();
            self.cx.resolver.resolve_imports();
            self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
        }
    }

446 447 448 449
    /// Collect all macro invocations reachable at this time in this AST fragment, and replace
    /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
    /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
    /// prepares data for resolving paths of macro invocations.
450 451 452
    fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
                           -> (AstFragment, Vec<Invocation>) {
        let (fragment_with_placeholders, invocations) = {
453 454 455 456 457 458 459 460
            let mut collector = InvocationCollector {
                cfg: StripUnconfigured {
                    should_test: self.cx.ecfg.should_test,
                    sess: self.cx.parse_sess,
                    features: self.cx.ecfg.features,
                },
                cx: self.cx,
                invocations: Vec::new(),
461
                monotonic: self.monotonic,
J
John Renner 已提交
462
                tests_nameable: true,
463
            };
464
            (fragment.fold_with(&mut collector), collector.invocations)
465
        };
466

467
        if self.monotonic {
468
            let err_count = self.cx.parse_sess.span_diagnostic.err_count();
469
            let mark = self.cx.current_expansion.mark;
470 471
            self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
                                                                  derives);
472
            self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
473 474
        }

475
        (fragment_with_placeholders, invocations)
476
    }
477

478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
    fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
        let mut cfg = StripUnconfigured {
            should_test: self.cx.ecfg.should_test,
            sess: self.cx.parse_sess,
            features: self.cx.ecfg.features,
        };
        // Since the item itself has already been configured by the InvocationCollector,
        // we know that fold result vector will contain exactly one element
        match item {
            Annotatable::Item(item) => {
                Annotatable::Item(cfg.fold_item(item).pop().unwrap())
            }
            Annotatable::TraitItem(item) => {
                Annotatable::TraitItem(item.map(|item| cfg.fold_trait_item(item).pop().unwrap()))
            }
            Annotatable::ImplItem(item) => {
                Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap()))
            }
496 497 498 499 500
            Annotatable::ForeignItem(item) => {
                Annotatable::ForeignItem(
                    item.map(|item| cfg.fold_foreign_item(item).pop().unwrap())
                )
            }
501 502 503 504 505 506
            Annotatable::Stmt(stmt) => {
                Annotatable::Stmt(stmt.map(|stmt| cfg.fold_stmt(stmt).pop().unwrap()))
            }
            Annotatable::Expr(expr) => {
                Annotatable::Expr(cfg.fold_expr(expr))
            }
507 508 509
        }
    }

510
    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
V
Vadim Petrochenkov 已提交
511 512 513 514 515 516 517 518 519
        if invoc.fragment_kind == AstFragmentKind::ForeignItems &&
           !self.cx.ecfg.macros_in_extern_enabled() {
            if let SyntaxExtension::NonMacroAttr { .. } = *ext {} else {
                emit_feature_err(&self.cx.parse_sess, "macros_in_extern",
                                 invoc.span(), GateIssue::Language,
                                 "macro invocations in `extern {}` blocks are experimental");
            }
        }

520
        let result = match invoc.kind {
521 522 523
            InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
            InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?,
524 525 526 527 528
        };

        if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
            let info = self.cx.current_expansion.mark.expn_info().unwrap();
            let suggested_limit = self.cx.ecfg.recursion_limit * 2;
529
            let mut err = self.cx.struct_span_err(info.call_site,
530
                &format!("recursion limit reached while expanding the macro `{}`",
531
                         info.format.name()));
532 533 534 535
            err.help(&format!(
                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                suggested_limit));
            err.emit();
536
            self.cx.trace_macros_diag();
537
            FatalError.raise();
538
        }
539

540
        Some(result)
541 542
    }

543 544
    fn expand_attr_invoc(&mut self,
                         invoc: Invocation,
545
                         ext: &SyntaxExtension)
546
                         -> Option<AstFragment> {
547
        let (attr, item) = match invoc.kind {
548
            InvocationKind::Attr { attr, item, .. } => (attr?, item),
549 550 551
            _ => unreachable!(),
        };

552
        if let NonMacroAttr { mark_used: false } = *ext {} else {
V
Vadim Petrochenkov 已提交
553 554
            // Macro attrs are always used when expanded,
            // non-macro attrs are considered used when the field says so.
555 556
            attr::mark_used(&attr);
        }
557
        invoc.expansion_data.mark.set_expn_info(ExpnInfo {
558
            call_site: attr.span,
559
            def_site: None,
L
ljedrz 已提交
560
            format: MacroAttribute(Symbol::intern(&attr.path.to_string())),
561 562
            allow_internal_unstable: false,
            allow_internal_unsafe: false,
563
            local_inner_macros: false,
564
            edition: ext.edition(),
565 566
        });

567
        match *ext {
568
            NonMacroAttr { .. } => {
569 570 571 572
                attr::mark_known(&attr);
                let item = item.map_attrs(|mut attrs| { attrs.push(attr); attrs });
                Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
            }
573
            MultiModifier(ref mac) => {
574 575
                let meta = attr.parse_meta(self.cx.parse_sess)
                               .map_err(|mut e| { e.emit(); }).ok()?;
576
                let item = mac.expand(self.cx, attr.span, &meta, item);
577
                Some(invoc.fragment_kind.expect_from_annotatables(item))
578 579 580
            }
            MultiDecorator(ref mac) => {
                let mut items = Vec::new();
581 582
                let meta = attr.parse_meta(self.cx.parse_sess)
                               .expect("derive meta should already have been parsed");
583
                mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
584
                items.push(item);
585
                Some(invoc.fragment_kind.expect_from_annotatables(items))
586
            }
587
            AttrProcMacro(ref mac, ..) => {
588
                self.gate_proc_macro_attr_item(attr.span, &item);
J
Jeffrey Seyfried 已提交
589 590
                let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
                    Annotatable::Item(item) => token::NtItem(item),
591 592
                    Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
                    Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
593
                    Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
594 595
                    Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                    Annotatable::Expr(expr) => token::NtExpr(expr),
J
Jeffrey Seyfried 已提交
596
                })).into();
597 598
                let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
                let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
599 600
                let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
                                                  &attr.path, attr.span);
601 602
                self.gate_proc_macro_expansion(attr.span, &res);
                res
603
            }
604
            ProcMacroDerive(..) | BuiltinDerive(..) => {
J
Jeffrey Seyfried 已提交
605
                self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
606
                self.cx.trace_macros_diag();
607
                invoc.fragment_kind.dummy(attr.span)
608 609
            }
            _ => {
J
Jeffrey Seyfried 已提交
610
                let msg = &format!("macro `{}` may not be used in attributes", attr.path);
611
                self.cx.span_err(attr.span, msg);
612
                self.cx.trace_macros_diag();
613
                invoc.fragment_kind.dummy(attr.span)
614
            }
615
        }
616 617
    }

618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
    fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream {
        let mut trees = tokens.trees();
        match trees.next() {
            Some(TokenTree::Delimited(_, delim)) => {
                if trees.next().is_none() {
                    return delim.tts.into()
                }
            }
            Some(TokenTree::Token(..)) => {}
            None => return TokenStream::empty(),
        }
        self.cx.span_err(span, "custom attribute invocations must be \
            of the form #[foo] or #[foo(..)], the macro name must only be \
            followed by a delimiter token");
        TokenStream::empty()
    }

    fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
        let (kind, gate) = match *item {
            Annotatable::Item(ref item) => {
                match item.node {
                    ItemKind::Mod(_) if self.cx.ecfg.proc_macro_mod() => return,
                    ItemKind::Mod(_) => ("modules", "proc_macro_mod"),
                    _ => return,
                }
            }
            Annotatable::TraitItem(_) => return,
            Annotatable::ImplItem(_) => return,
            Annotatable::ForeignItem(_) => return,
            Annotatable::Stmt(_) |
            Annotatable::Expr(_) if self.cx.ecfg.proc_macro_expr() => return,
            Annotatable::Stmt(_) => ("statements", "proc_macro_expr"),
            Annotatable::Expr(_) => ("expressions", "proc_macro_expr"),
        };
        emit_feature_err(
            self.cx.parse_sess,
            gate,
            span,
            GateIssue::Language,
            &format!("custom attributes cannot be applied to {}", kind),
        );
    }

661
    fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
662 663 664
        if self.cx.ecfg.proc_macro_gen() {
            return
        }
665 666
        let fragment = match fragment {
            Some(fragment) => fragment,
667 668 669
            None => return,
        };

670
        fragment.visit_with(&mut DisallowMacros {
671 672 673 674
            span,
            parse_sess: self.cx.parse_sess,
        });

675
        struct DisallowMacros<'a> {
676 677 678 679
            span: Span,
            parse_sess: &'a ParseSess,
        }

680
        impl<'ast, 'a> Visitor<'ast> for DisallowMacros<'a> {
681
            fn visit_item(&mut self, i: &'ast ast::Item) {
682
                if let ast::ItemKind::MacroDef(_) = i.node {
683 684 685 686 687
                    emit_feature_err(
                        self.parse_sess,
                        "proc_macro_gen",
                        self.span,
                        GateIssue::Language,
688
                        &format!("procedural macros cannot expand to macro definitions"),
689 690 691 692 693 694 695 696 697 698 699
                    );
                }
                visit::walk_item(self, i);
            }

            fn visit_mac(&mut self, _mac: &'ast ast::Mac) {
                // ...
            }
        }
    }

700
    /// Expand a macro invocation. Returns the resulting expanded AST fragment.
701 702
    fn expand_bang_invoc(&mut self,
                         invoc: Invocation,
703
                         ext: &SyntaxExtension)
704 705
                         -> Option<AstFragment> {
        let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind);
706 707
        let (mac, ident, span) = match invoc.kind {
            InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
708 709
            _ => unreachable!(),
        };
J
Jeffrey Seyfried 已提交
710
        let path = &mac.node.path;
711

712
        let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
713 714
        let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
                                          def_site_span: Option<Span>,
715
                                          allow_internal_unstable,
716
                                          allow_internal_unsafe,
717
                                          local_inner_macros,
718
                                          // can't infer this type
719 720
                                          unstable_feature: Option<(Symbol, u32)>,
                                          edition| {
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739

            // feature-gate the macro invocation
            if let Some((feature, issue)) = unstable_feature {
                let crate_span = this.cx.current_expansion.crate_span.unwrap();
                // don't stability-check macros in the same crate
                // (the only time this is null is for syntax extensions registered as macros)
                if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span))
                    && !span.allows_unstable() && this.cx.ecfg.features.map_or(true, |feats| {
                    // macro features will count as lib features
                    !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature)
                }) {
                    let explain = format!("macro {}! is unstable", path);
                    emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span,
                                     GateIssue::Library(Some(issue)), &explain);
                    this.cx.trace_macros_diag();
                    return Err(kind.dummy(span));
                }
            }

J
Jeffrey Seyfried 已提交
740
            if ident.name != keywords::Invalid.name() {
741 742 743 744
                let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident);
                this.cx.span_err(path.span, &msg);
                this.cx.trace_macros_diag();
                return Err(kind.dummy(span));
J
Jeffrey Seyfried 已提交
745 746 747
            }
            mark.set_expn_info(ExpnInfo {
                call_site: span,
748 749 750 751
                def_site: def_site_span,
                format: macro_bang_format(path),
                allow_internal_unstable,
                allow_internal_unsafe,
752
                local_inner_macros,
753
                edition,
J
Jeffrey Seyfried 已提交
754 755 756 757
            });
            Ok(())
        };

758
        let opt_expanded = match *ext {
759
            DeclMacro { ref expander, def_info, edition, .. } => {
760
                if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
761
                                                                    false, false, false, None,
762
                                                                    edition) {
763
                    dummy_span
764
                } else {
765
                    kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
766
                }
J
Jeffrey Seyfried 已提交
767
            }
768

769 770 771 772
            NormalTT {
                ref expander,
                def_info,
                allow_internal_unstable,
773
                allow_internal_unsafe,
774
                local_inner_macros,
775
                unstable_feature,
776
                edition,
777
            } => {
778 779 780
                if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
                                                                    allow_internal_unstable,
                                                                    allow_internal_unsafe,
781
                                                                    local_inner_macros,
782 783
                                                                    unstable_feature,
                                                                    edition) {
784
                    dummy_span
785 786
                } else {
                    kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
J
Jeffrey Seyfried 已提交
787
                }
788 789 790 791 792
            }

            IdentTT(ref expander, tt_span, allow_internal_unstable) => {
                if ident.name == keywords::Invalid.name() {
                    self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
793
                                    &format!("macro {}! expects an ident argument", path));
794
                    self.cx.trace_macros_diag();
795 796 797 798
                    kind.dummy(span)
                } else {
                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                        call_site: span,
799 800 801 802
                        def_site: tt_span,
                        format: macro_bang_format(path),
                        allow_internal_unstable,
                        allow_internal_unsafe: false,
803
                        local_inner_macros: false,
804
                        edition: hygiene::default_edition(),
805
                    });
806

807 808 809
                    let input: Vec<_> = mac.node.stream().into_trees().collect();
                    kind.make_from(expander.expand(self.cx, span, ident, input))
                }
810 811
            }

812
            MultiDecorator(..) | MultiModifier(..) |
813
            AttrProcMacro(..) | SyntaxExtension::NonMacroAttr { .. } => {
814
                self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
815
                                 &format!("`{}` can only be used in attributes", path));
816
                self.cx.trace_macros_diag();
817
                kind.dummy(span)
818
            }
819

820
            ProcMacroDerive(..) | BuiltinDerive(..) => {
J
Jeffrey Seyfried 已提交
821
                self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
822
                self.cx.trace_macros_diag();
823
                kind.dummy(span)
824 825
            }

826
            SyntaxExtension::ProcMacro { ref expander, allow_internal_unstable, edition } => {
827 828
                if ident.name != keywords::Invalid.name() {
                    let msg =
J
Jeffrey Seyfried 已提交
829
                        format!("macro {}! expects no ident argument, given '{}'", path, ident);
N
Nick Cameron 已提交
830
                    self.cx.span_err(path.span, &msg);
831
                    self.cx.trace_macros_diag();
832 833
                    kind.dummy(span)
                } else {
834
                    self.gate_proc_macro_expansion_kind(span, kind);
835 836
                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                        call_site: span,
837 838 839 840 841 842 843
                        // FIXME procedural macros do not have proper span info
                        // yet, when they do, we should use it here.
                        def_site: None,
                        format: macro_bang_format(path),
                        // FIXME probably want to follow macro_rules macros here.
                        allow_internal_unstable,
                        allow_internal_unsafe: false,
844
                        local_inner_macros: false,
845
                        edition,
846
                    });
847

848
                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
849
                    let result = self.parse_ast_fragment(tok_result, kind, path, span);
850 851
                    self.gate_proc_macro_expansion(span, &result);
                    result
852
                }
853
            }
854 855
        };

856 857 858
        if opt_expanded.is_some() {
            opt_expanded
        } else {
859
            let msg = format!("non-{kind} macro in {kind} position: {name}",
860
                              name = path.segments[0].ident.name, kind = kind.name());
861
            self.cx.span_err(path.span, &msg);
862
            self.cx.trace_macros_diag();
863
            kind.dummy(span)
864
        }
865
    }
J
Jeffrey Seyfried 已提交
866

867
    fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
868
        let kind = match kind {
869 870 871 872 873 874 875 876 877
            AstFragmentKind::Expr => "expressions",
            AstFragmentKind::OptExpr => "expressions",
            AstFragmentKind::Pat => "patterns",
            AstFragmentKind::Ty => "types",
            AstFragmentKind::Stmts => "statements",
            AstFragmentKind::Items => return,
            AstFragmentKind::TraitItems => return,
            AstFragmentKind::ImplItems => return,
            AstFragmentKind::ForeignItems => return,
878 879 880 881 882 883 884 885 886 887 888 889 890
        };
        if self.cx.ecfg.proc_macro_non_items() {
            return
        }
        emit_feature_err(
            self.cx.parse_sess,
            "proc_macro_non_items",
            span,
            GateIssue::Language,
            &format!("procedural macros cannot be expanded to {}", kind),
        );
    }

891
    /// Expand a derive invocation. Returns the resulting expanded AST fragment.
892 893
    fn expand_derive_invoc(&mut self,
                           invoc: Invocation,
894
                           ext: &SyntaxExtension)
895
                           -> Option<AstFragment> {
J
Jeffrey Seyfried 已提交
896 897
        let (path, item) = match invoc.kind {
            InvocationKind::Derive { path, item } => (path, item),
898 899
            _ => unreachable!(),
        };
900 901 902
        if !item.derive_allowed() {
            return None;
        }
903

J
Jeffrey Seyfried 已提交
904 905 906
        let pretty_name = Symbol::intern(&format!("derive({})", path));
        let span = path.span;
        let attr = ast::Attribute {
907 908
            path, span,
            tokens: TokenStream::empty(),
J
Jeffrey Seyfried 已提交
909 910 911
            // irrelevant:
            id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
        };
912

913
        let mut expn_info = ExpnInfo {
914
            call_site: span,
915 916 917 918
            def_site: None,
            format: MacroAttribute(pretty_name),
            allow_internal_unstable: false,
            allow_internal_unsafe: false,
919
            local_inner_macros: false,
920
            edition: ext.edition(),
921
        };
922 923

        match *ext {
924
            ProcMacroDerive(ref ext, ..) => {
925
                invoc.expansion_data.mark.set_expn_info(expn_info);
926
                let span = span.with_ctxt(self.cx.backtrace());
J
Jeffrey Seyfried 已提交
927
                let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
F
flip1995 已提交
928
                    ident: Path::from_ident(keywords::Invalid.ident()),
J
Jeffrey Seyfried 已提交
929 930 931
                    span: DUMMY_SP,
                    node: ast::MetaItemKind::Word,
                };
932
                let items = ext.expand(self.cx, span, &dummy, item);
933
                Some(invoc.fragment_kind.expect_from_annotatables(items))
934
            }
935
            BuiltinDerive(func) => {
936
                expn_info.allow_internal_unstable = true;
937
                invoc.expansion_data.mark.set_expn_info(expn_info);
938
                let span = span.with_ctxt(self.cx.backtrace());
939
                let mut items = Vec::new();
940
                func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
941
                Some(invoc.fragment_kind.expect_from_annotatables(items))
942 943
            }
            _ => {
J
Jeffrey Seyfried 已提交
944
                let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
945
                self.cx.span_err(span, msg);
946
                self.cx.trace_macros_diag();
947
                invoc.fragment_kind.dummy(span)
948 949 950 951
            }
        }
    }

952 953 954 955 956 957
    fn parse_ast_fragment(&mut self,
                          toks: TokenStream,
                          kind: AstFragmentKind,
                          path: &Path,
                          span: Span)
                          -> Option<AstFragment> {
958
        let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
959 960
        match parser.parse_ast_fragment(kind, false) {
            Ok(fragment) => {
961
                parser.ensure_complete_parse(path, kind.name(), span);
962
                Some(fragment)
963
            }
J
Jeffrey Seyfried 已提交
964
            Err(mut err) => {
965
                err.set_span(span);
J
Jeffrey Seyfried 已提交
966
                err.emit();
967
                self.cx.trace_macros_diag();
968
                kind.dummy(span)
J
Jeffrey Seyfried 已提交
969
            }
970
        }
J
Jeffrey Seyfried 已提交
971
    }
972 973
}

974
impl<'a> Parser<'a> {
975 976
    pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warnings: bool)
                              -> PResult<'a, AstFragment> {
977
        Ok(match kind {
978
            AstFragmentKind::Items => {
979
                let mut items = OneVector::new();
980 981 982
                while let Some(item) = self.parse_item()? {
                    items.push(item);
                }
983
                AstFragment::Items(items)
984
            }
985
            AstFragmentKind::TraitItems => {
986
                let mut items = OneVector::new();
987
                while self.token != token::Eof {
988
                    items.push(self.parse_trait_item(&mut false)?);
989
                }
990
                AstFragment::TraitItems(items)
991
            }
992
            AstFragmentKind::ImplItems => {
993
                let mut items = OneVector::new();
994
                while self.token != token::Eof {
995
                    items.push(self.parse_impl_item(&mut false)?);
996
                }
997
                AstFragment::ImplItems(items)
998
            }
999
            AstFragmentKind::ForeignItems => {
1000
                let mut items = OneVector::new();
1001 1002 1003 1004 1005
                while self.token != token::Eof {
                    if let Some(item) = self.parse_foreign_item()? {
                        items.push(item);
                    }
                }
1006
                AstFragment::ForeignItems(items)
1007
            }
1008
            AstFragmentKind::Stmts => {
1009
                let mut stmts = OneVector::new();
G
Geoffry Song 已提交
1010 1011 1012
                while self.token != token::Eof &&
                      // won't make progress on a `}`
                      self.token != token::CloseDelim(token::Brace) {
J
Jeffrey Seyfried 已提交
1013
                    if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? {
1014 1015 1016
                        stmts.push(stmt);
                    }
                }
1017
                AstFragment::Stmts(stmts)
1018
            }
1019 1020
            AstFragmentKind::Expr => AstFragment::Expr(self.parse_expr()?),
            AstFragmentKind::OptExpr => {
1021
                if self.token != token::Eof {
1022
                    AstFragment::OptExpr(Some(self.parse_expr()?))
1023
                } else {
1024
                    AstFragment::OptExpr(None)
1025 1026
                }
            },
1027 1028
            AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?),
            AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat()?),
1029 1030
        })
    }
1031

J
Jeffrey Seyfried 已提交
1032
    pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) {
1033 1034 1035
        if self.token != token::Eof {
            let msg = format!("macro expansion ignores token `{}` and any following",
                              self.this_token_to_string());
1036 1037
            // Avoid emitting backtrace info twice.
            let def_site_span = self.span.with_ctxt(SyntaxContext::empty());
1038
            let mut err = self.diagnostic().struct_span_err(def_site_span, &msg);
1039 1040
            let msg = format!("caused by the macro expansion here; the usage \
                               of `{}!` is likely invalid in {} context",
J
Jeffrey Seyfried 已提交
1041
                               macro_path, kind_name);
1042 1043 1044
            err.span_note(span, &msg).emit();
        }
    }
1045 1046 1047 1048
}

struct InvocationCollector<'a, 'b: 'a> {
    cx: &'a mut ExtCtxt<'b>,
1049
    cfg: StripUnconfigured<'a>,
1050
    invocations: Vec<Invocation>,
1051
    monotonic: bool,
J
John Renner 已提交
1052 1053 1054 1055 1056

    /// Test functions need to be nameable. Tests inside functions or in other
    /// unnameable locations need to be ignored. `tests_nameable` tracks whether
    /// any test functions found in the current context would be nameable.
    tests_nameable: bool,
1057 1058 1059
}

impl<'a, 'b> InvocationCollector<'a, 'b> {
1060
    fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
J
Jeffrey Seyfried 已提交
1061
        let mark = Mark::fresh(self.cx.current_expansion.mark);
1062
        self.invocations.push(Invocation {
1063
            kind,
1064
            fragment_kind,
J
Jeffrey Seyfried 已提交
1065
            expansion_data: ExpansionData {
1066
                mark,
J
Jeffrey Seyfried 已提交
1067 1068 1069
                depth: self.cx.current_expansion.depth + 1,
                ..self.cx.current_expansion.clone()
            },
1070
        });
1071
        placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
1072
    }
1073

J
John Renner 已提交
1074 1075
    /// Folds the item allowing tests to be expanded because they are still nameable.
    /// This should probably only be called with module items
1076
    fn fold_nameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
J
John Renner 已提交
1077 1078 1079 1080
        fold::noop_fold_item(item, self)
    }

    /// Folds the item but doesn't allow tests to occur within it
1081
    fn fold_unnameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
J
John Renner 已提交
1082 1083 1084 1085 1086 1087
        let was_nameable = mem::replace(&mut self.tests_nameable, false);
        let items = fold::noop_fold_item(item, self);
        self.tests_nameable = was_nameable;
        items
    }

1088
    fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
1089
        self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
1090
    }
1091

1092 1093
    fn collect_attr(&mut self,
                    attr: Option<ast::Attribute>,
J
Jeffrey Seyfried 已提交
1094
                    traits: Vec<Path>,
1095
                    item: Annotatable,
1096 1097
                    kind: AstFragmentKind)
                    -> AstFragment {
1098
        self.collect(kind, InvocationKind::Attr { attr, traits, item })
1099 1100
    }

1101
    /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
J
Jeffrey Seyfried 已提交
1102
    fn classify_item<T>(&mut self, mut item: T) -> (Option<ast::Attribute>, Vec<Path>, T)
1103 1104 1105
        where T: HasAttrs,
    {
        let (mut attr, mut traits) = (None, Vec::new());
1106

1107
        item = item.map_attrs(|mut attrs| {
1108 1109
            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
                                                                                     true) {
1110 1111 1112
                attr = Some(legacy_attr_invoc);
                return attrs;
            }
1113

1114
            attr = find_attr_invoc(&mut attrs);
1115
            traits = collect_derives(&mut self.cx, &mut attrs);
1116 1117
            attrs
        });
1118

1119
        (attr, traits, item)
1120 1121
    }

1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
    /// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough
    /// to the unused-attributes lint (making it an error on statements and expressions
    /// is a breaking change)
    fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T) -> (Option<ast::Attribute>, T) {
        let mut attr = None;

        item = item.map_attrs(|mut attrs| {
            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
                                                                                     false) {
                attr = Some(legacy_attr_invoc);
                return attrs;
            }

1135
            attr = find_attr_invoc(&mut attrs);
1136 1137 1138 1139 1140 1141
            attrs
        });

        (attr, item)
    }

1142 1143 1144
    fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
        self.cfg.configure(node)
    }
1145 1146 1147 1148 1149 1150

    // Detect use of feature-gated or invalid attributes on macro invocations
    // since they will not be detected after macro expansion.
    fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
        let features = self.cx.ecfg.features.unwrap();
        for attr in attrs.iter() {
S
Seiichi Uchida 已提交
1151
            self.check_attribute_inner(attr, features);
1152 1153 1154 1155 1156 1157 1158

            // macros are expanded before any lint passes so this warning has to be hardcoded
            if attr.path == "derive" {
                self.cx.struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations")
                    .note("this may become a hard error in a future release")
                    .emit();
            }
1159 1160
        }
    }
1161 1162 1163

    fn check_attribute(&mut self, at: &ast::Attribute) {
        let features = self.cx.ecfg.features.unwrap();
S
Seiichi Uchida 已提交
1164 1165 1166 1167
        self.check_attribute_inner(at, features);
    }

    fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) {
1168 1169
        feature_gate::check_attribute(at, self.cx.parse_sess, features);
    }
1170 1171
}

1172
pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
1173 1174 1175
    attrs.iter()
         .position(|a| !attr::is_known(a) && !is_builtin_attr(a))
         .map(|i| attrs.remove(i))
1176 1177
}

1178
impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
1179
    fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
1180
        let mut expr = self.cfg.configure_expr(expr).into_inner();
1181 1182
        expr.node = self.cfg.configure_expr_kind(expr.node);

1183 1184
        // ignore derives so they remain unused
        let (attr, expr) = self.classify_nonitem(expr);
1185

1186
        if attr.is_some() {
1187 1188 1189 1190
            // collect the invoc regardless of whether or not attributes are permitted here
            // expansion will eat the attribute so it won't error later
            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));

1191 1192 1193
            // AstFragmentKind::Expr requires the macro to emit an expression
            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
                                     AstFragmentKind::Expr).make_expr();
1194 1195
        }

1196
        if let ast::ExprKind::Mac(mac) = expr.node {
1197
            self.check_attributes(&expr.attrs);
1198
            self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr()
1199 1200 1201
        } else {
            P(noop_fold_expr(expr, self))
        }
1202 1203
    }

1204
    fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
1205
        let mut expr = configure!(self, expr).into_inner();
1206 1207
        expr.node = self.cfg.configure_expr_kind(expr.node);

1208 1209
        // ignore derives so they remain unused
        let (attr, expr) = self.classify_nonitem(expr);
1210

1211
        if attr.is_some() {
1212 1213
            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));

1214
            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
1215
                                     AstFragmentKind::OptExpr)
1216 1217 1218
                .make_opt_expr();
        }

1219
        if let ast::ExprKind::Mac(mac) = expr.node {
1220
            self.check_attributes(&expr.attrs);
1221
            self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr()
1222 1223 1224
        } else {
            Some(P(noop_fold_expr(expr, self)))
        }
1225 1226
    }

1227
    fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
1228
        let pat = self.cfg.configure_pat(pat);
1229 1230
        match pat.node {
            PatKind::Mac(_) => {}
1231
            _ => return noop_fold_pat(pat, self),
1232
        }
K
Keegan McAllister 已提交
1233

1234
        pat.and_then(|pat| match pat.node {
1235
            PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
1236 1237
            _ => unreachable!(),
        })
1238 1239
    }

1240
    fn fold_stmt(&mut self, stmt: ast::Stmt) -> OneVector<ast::Stmt> {
1241
        let mut stmt = match self.cfg.configure_stmt(stmt) {
1242
            Some(stmt) => stmt,
1243
            None => return OneVector::new(),
1244 1245
        };

1246 1247
        // we'll expand attributes on expressions separately
        if !stmt.is_expr() {
1248 1249 1250 1251 1252 1253 1254 1255
            let (attr, derives, stmt_) = if stmt.is_item() {
                self.classify_item(stmt)
            } else {
                // ignore derives on non-item statements so it falls through
                // to the unused-attributes lint
                let (attr, stmt) = self.classify_nonitem(stmt);
                (attr, vec![], stmt)
            };
1256 1257 1258

            if attr.is_some() || !derives.is_empty() {
                return self.collect_attr(attr, derives,
1259
                                         Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts)
1260 1261
                    .make_stmts();
            }
1262

1263 1264
            stmt = stmt_;
        }
1265

1266 1267 1268
        if let StmtKind::Mac(mac) = stmt.node {
            let (mac, style, attrs) = mac.into_inner();
            self.check_attributes(&attrs);
1269
            let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts)
1270 1271 1272 1273 1274 1275 1276 1277
                                        .make_stmts();

            // If this is a macro invocation with a semicolon, then apply that
            // semicolon to the final statement produced by expansion.
            if style == MacStmtStyle::Semicolon {
                if let Some(stmt) = placeholder.pop() {
                    placeholder.push(stmt.add_trailing_semicolon());
                }
1278
            }
1279 1280

            return placeholder;
1281 1282
        }

1283 1284 1285 1286 1287 1288
        // The placeholder expander gives ids to statements, so we avoid folding the id here.
        let ast::Stmt { id, node, span } = stmt;
        noop_fold_stmt_kind(node, self).into_iter().map(|node| {
            ast::Stmt { id, node, span }
        }).collect()

1289 1290
    }

S
Steven Fackler 已提交
1291
    fn fold_block(&mut self, block: P<Block>) -> P<Block> {
1292 1293
        let old_directory_ownership = self.cx.current_expansion.directory_ownership;
        self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
J
Jeffrey Seyfried 已提交
1294
        let result = noop_fold_block(block, self);
1295
        self.cx.current_expansion.directory_ownership = old_directory_ownership;
1296
        result
1297 1298
    }

1299
    fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
1300 1301
        let item = configure!(self, item);

1302 1303
        let (attr, traits, mut item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1304
            let item = Annotatable::Item(item);
1305
            return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
1306 1307 1308 1309
        }

        match item.node {
            ast::ItemKind::Mac(..) => {
1310
                self.check_attributes(&item.attrs);
1311
                item.and_then(|item| match item.node {
1312
                    ItemKind::Mac(mac) => {
1313
                        self.collect(AstFragmentKind::Items, InvocationKind::Bang {
1314
                            mac,
1315 1316
                            ident: Some(item.ident),
                            span: item.span,
1317
                        }).make_items()
1318 1319 1320 1321 1322
                    }
                    _ => unreachable!(),
                })
            }
            ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
1323
                if item.ident == keywords::Invalid.ident() {
J
John Renner 已提交
1324
                    return self.fold_nameable(item);
1325 1326
                }

1327
                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1328 1329
                let mut module = (*self.cx.current_expansion.module).clone();
                module.mod_path.push(item.ident);
1330 1331 1332 1333

                // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`).
                // In the non-inline case, `inner` is never the dummy span (c.f. `parse_item_mod`).
                // Thus, if `inner` is the dummy span, we know the module is inline.
V
Vadim Petrochenkov 已提交
1334
                let inline_module = item.span.contains(inner) || inner.is_dummy();
1335 1336

                if inline_module {
1337
                    if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
1338 1339
                        self.cx.current_expansion.directory_ownership =
                            DirectoryOwnership::Owned { relative: None };
1340
                        module.directory.push(&*path.as_str());
1341
                    } else {
V
Vadim Petrochenkov 已提交
1342
                        module.directory.push(&*item.ident.as_str());
1343
                    }
1344
                } else {
D
Donato Sciarra 已提交
1345
                    let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner);
1346 1347 1348 1349
                    let mut path = match path {
                        FileName::Real(path) => path,
                        other => PathBuf::from(other.to_string()),
                    };
1350
                    let directory_ownership = match path.file_name().unwrap().to_str() {
1351 1352 1353 1354 1355
                        Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
                        Some(_) => DirectoryOwnership::Owned {
                            relative: Some(item.ident),
                        },
                        None => DirectoryOwnership::UnownedViaMod(false),
1356 1357 1358 1359
                    };
                    path.pop();
                    module.directory = path;
                    self.cx.current_expansion.directory_ownership = directory_ownership;
1360 1361
                }

1362 1363
                let orig_module =
                    mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
J
John Renner 已提交
1364
                let result = self.fold_nameable(item);
1365
                self.cx.current_expansion.module = orig_module;
1366
                self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1367
                result
1368
            }
1369
            // Ensure that test functions are accessible from the test harness.
J
John Renner 已提交
1370 1371 1372
            // #[test] fn foo() {}
            // becomes:
            // #[test] pub fn foo_gensym(){}
J
John Renner 已提交
1373
            // #[allow(unused)]
J
John Renner 已提交
1374
            // use foo_gensym as foo;
1375
            ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
J
John Renner 已提交
1376
                if self.tests_nameable && item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
J
John Renner 已提交
1377 1378
                    let orig_ident = item.ident;
                    let orig_vis   = item.vis.clone();
1379 1380

                    // Publicize the item under gensymed name to avoid pollution
1381 1382
                    item = item.map(|mut item| {
                        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
J
John Renner 已提交
1383
                        item.ident = item.ident.gensym();
1384 1385
                        item
                    });
1386 1387

                    // Use the gensymed name under the item's original visibility
J
John Renner 已提交
1388
                    let mut use_item = self.cx.item_use_simple_(
1389 1390
                        item.ident.span,
                        orig_vis,
J
John Renner 已提交
1391 1392 1393
                        Some(orig_ident),
                        self.cx.path(item.ident.span,
                            vec![keywords::SelfValue.ident(), item.ident]));
1394

J
John Renner 已提交
1395
                    // #[allow(unused)] because the test function probably isn't being referenced
J
John Renner 已提交
1396 1397 1398 1399
                    use_item = use_item.map(|mut ui| {
                        ui.attrs.push(
                            self.cx.attribute(DUMMY_SP, attr::mk_list_item(DUMMY_SP,
                                Ident::from_str("allow"), vec![
J
John Renner 已提交
1400
                                    attr::mk_nested_word_item(Ident::from_str("unused"))
J
John Renner 已提交
1401 1402 1403 1404 1405 1406 1407
                                ]
                            ))
                        );

                        ui
                    });

1408
                    OneVector::from_iter(
J
John Renner 已提交
1409 1410
                        self.fold_unnameable(item).into_iter()
                            .chain(self.fold_unnameable(use_item)))
1411
                } else {
J
John Renner 已提交
1412
                    self.fold_unnameable(item)
1413 1414
                }
            }
J
John Renner 已提交
1415
            _ => self.fold_unnameable(item),
1416
        }
1417 1418
    }

1419
    fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector<ast::TraitItem> {
1420 1421
        let item = configure!(self, item);

1422 1423
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1424
            let item = Annotatable::TraitItem(P(item));
1425
            return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems)
1426
                .make_trait_items()
1427 1428 1429 1430 1431
        }

        match item.node {
            ast::TraitItemKind::Macro(mac) => {
                let ast::TraitItem { attrs, span, .. } = item;
1432
                self.check_attributes(&attrs);
1433
                self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
1434 1435 1436 1437 1438
            }
            _ => fold::noop_fold_trait_item(item, self),
        }
    }

1439
    fn fold_impl_item(&mut self, item: ast::ImplItem) -> OneVector<ast::ImplItem> {
1440 1441
        let item = configure!(self, item);

1442 1443
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1444
            let item = Annotatable::ImplItem(P(item));
1445
            return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems)
1446
                .make_impl_items();
1447 1448 1449 1450 1451
        }

        match item.node {
            ast::ImplItemKind::Macro(mac) => {
                let ast::ImplItem { attrs, span, .. } = item;
1452
                self.check_attributes(&attrs);
1453
                self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
1454
            }
1455
            _ => fold::noop_fold_impl_item(item, self),
1456
        }
1457 1458
    }

1459
    fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
1460
        let ty = match ty.node {
1461
            ast::TyKind::Mac(_) => ty.into_inner(),
1462 1463 1464 1465
            _ => return fold::noop_fold_ty(ty, self),
        };

        match ty.node {
1466
            ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
1467 1468
            _ => unreachable!(),
        }
1469
    }
1470 1471 1472 1473 1474

    fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod {
        noop_fold_foreign_mod(self.cfg.configure_foreign_mod(foreign_mod), self)
    }

1475
    fn fold_foreign_item(&mut self,
1476
                         foreign_item: ast::ForeignItem) -> OneVector<ast::ForeignItem> {
1477 1478
        let (attr, traits, foreign_item) = self.classify_item(foreign_item);

V
Vadim Petrochenkov 已提交
1479
        if attr.is_some() || !traits.is_empty() {
1480
            let item = Annotatable::ForeignItem(P(foreign_item));
1481
            return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
1482 1483 1484 1485 1486
                .make_foreign_items();
        }

        if let ast::ForeignItemKind::Macro(mac) = foreign_item.node {
            self.check_attributes(&foreign_item.attrs);
1487
            return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
1488 1489 1490 1491 1492 1493
                .make_foreign_items();
        }

        noop_fold_foreign_item(foreign_item, self)
    }

1494
    fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
1495 1496 1497 1498
        match item {
            ast::ItemKind::MacroDef(..) => item,
            _ => noop_fold_item_kind(self.cfg.configure_item_kind(item), self),
        }
1499
    }
1500

1501 1502 1503 1504 1505
    fn fold_generic_param(&mut self, param: ast::GenericParam) -> ast::GenericParam {
        self.cfg.disallow_cfg_on_generic_param(&param);
        noop_fold_generic_param(param, self)
    }

1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
    fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
        // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
        // contents="file contents")]` attributes
        if !at.check_name("doc") {
            return noop_fold_attribute(at, self);
        }

        if let Some(list) = at.meta_item_list() {
            if !list.iter().any(|it| it.check_name("include")) {
                return noop_fold_attribute(at, self);
            }

            let mut items = vec![];

            for it in list {
                if !it.check_name("include") {
                    items.push(noop_fold_meta_list_item(it, self));
                    continue;
                }

                if let Some(file) = it.value_str() {
                    let err_count = self.cx.parse_sess.span_diagnostic.err_count();
                    self.check_attribute(&at);
                    if self.cx.parse_sess.span_diagnostic.err_count() > err_count {
                        // avoid loading the file if they haven't enabled the feature
                        return noop_fold_attribute(at, self);
                    }

                    let mut buf = vec![];
                    let filename = self.cx.root_path.join(file.to_string());

                    match File::open(&filename).and_then(|mut f| f.read_to_end(&mut buf)) {
                        Ok(..) => {}
                        Err(e) => {
1540 1541 1542 1543
                            self.cx.span_err(at.span,
                                             &format!("couldn't read {}: {}",
                                                      filename.display(),
                                                      e));
1544 1545 1546 1547 1548
                        }
                    }

                    match String::from_utf8(buf) {
                        Ok(src) => {
1549 1550
                            let src_interned = Symbol::intern(&src);

1551 1552
                            // Add this input file to the code map to make it available as
                            // dependency information
D
Donato Sciarra 已提交
1553
                            self.cx.source_map().new_source_file(filename.into(), src);
1554

1555 1556
                            let include_info = vec![
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
1557 1558
                                        attr::mk_name_value_item_str(Ident::from_str("file"),
                                                                     dummy_spanned(file)))),
1559
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
1560
                                        attr::mk_name_value_item_str(Ident::from_str("contents"),
1561
                                                            dummy_spanned(src_interned)))),
1562 1563
                            ];

1564 1565 1566
                            let include_ident = Ident::from_str("include");
                            let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info);
                            items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item)));
1567 1568
                        }
                        Err(_) => {
1569 1570 1571
                            self.cx.span_err(at.span,
                                             &format!("{} wasn't a utf-8 file",
                                                      filename.display()));
1572 1573 1574 1575 1576 1577 1578
                        }
                    }
                } else {
                    items.push(noop_fold_meta_list_item(it, self));
                }
            }

1579
            let meta = attr::mk_list_item(DUMMY_SP, Ident::from_str("doc"), items);
1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590
            match at.style {
                ast::AttrStyle::Inner =>
                    Some(attr::mk_spanned_attr_inner(at.span, at.id, meta)),
                ast::AttrStyle::Outer =>
                    Some(attr::mk_spanned_attr_outer(at.span, at.id, meta)),
            }
        } else {
            noop_fold_attribute(at, self)
        }
    }

1591
    fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
1592 1593 1594 1595 1596 1597
        if self.monotonic {
            assert_eq!(id, ast::DUMMY_NODE_ID);
            self.cx.resolver.next_node_id()
        } else {
            id
        }
1598
    }
1599 1600
}

1601
pub struct ExpansionConfig<'feat> {
1602
    pub crate_name: String,
1603
    pub features: Option<&'feat Features>,
P
Paul Collier 已提交
1604
    pub recursion_limit: usize,
1605
    pub trace_mac: bool,
1606
    pub should_test: bool, // If false, strip `#[test]` nodes
1607 1608
    pub single_step: bool,
    pub keep_macs: bool,
1609 1610
}

1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623
macro_rules! feature_tests {
    ($( fn $getter:ident = $field:ident, )*) => {
        $(
            pub fn $getter(&self) -> bool {
                match self.features {
                    Some(&Features { $field: true, .. }) => true,
                    _ => false,
                }
            }
        )*
    }
}

1624 1625
impl<'feat> ExpansionConfig<'feat> {
    pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1626
        ExpansionConfig {
1627
            crate_name,
1628
            features: None,
1629
            recursion_limit: 1024,
1630
            trace_mac: false,
1631
            should_test: false,
1632 1633
            single_step: false,
            keep_macs: false,
1634 1635
        }
    }
1636

1637
    feature_tests! {
1638 1639
        fn enable_quotes = quote,
        fn enable_asm = asm,
1640
        fn enable_global_asm = global_asm,
1641 1642 1643
        fn enable_log_syntax = log_syntax,
        fn enable_concat_idents = concat_idents,
        fn enable_trace_macros = trace_macros,
1644
        fn enable_allow_internal_unstable = allow_internal_unstable,
1645
        fn enable_custom_derive = custom_derive,
1646
        fn enable_format_args_nl = format_args_nl,
1647
        fn macros_in_extern_enabled = macros_in_extern,
1648
        fn proc_macro_mod = proc_macro_mod,
1649
        fn proc_macro_gen = proc_macro_gen,
1650 1651
        fn proc_macro_expr = proc_macro_expr,
        fn proc_macro_non_items = proc_macro_non_items,
1652
    }
1653 1654
}

1655
// A Marker adds the given mark to the syntax context.
1656
#[derive(Debug)]
1657
pub struct Marker(pub Mark);
1658

E
Eduard Burtescu 已提交
1659
impl Folder for Marker {
1660
    fn new_span(&mut self, span: Span) -> Span {
1661
        span.apply_mark(self.0)
1662
    }
1663 1664 1665 1666

    fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
        noop_fold_mac(mac, self)
    }
1667
}