expand.rs 69.0 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, mem};
J
Jeffrey Seyfried 已提交
41
use std::rc::Rc;
42
use std::path::PathBuf;
43

44
macro_rules! ast_fragments {
45 46 47
    (
        $($Kind:ident($AstTy:ty) {
            $kind_name:expr;
48 49 50 51
            // 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;)*
52 53 54
            fn $make_ast:ident;
        })*
    ) => {
55 56
        /// 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.
57 58 59 60
        pub enum AstFragment {
            OptExpr(Option<P<ast::Expr>>),
            $($Kind($AstTy),)*
        }
61 62

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

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

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

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

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

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

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

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

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

147
ast_fragments! {
148 149 150
    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; }
151 152 153
    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>) {
154 155
        "trait item"; many fn fold_trait_item; fn visit_trait_item; fn make_trait_items;
    }
156
    ImplItems(OneVector<ast::ImplItem>) {
157 158
        "impl item"; many fn fold_impl_item; fn visit_impl_item; fn make_impl_items;
    }
159
    ForeignItems(OneVector<ast::ForeignItem>) {
160 161
        "foreign item"; many fn fold_foreign_item; fn visit_foreign_item; fn make_foreign_items;
    }
162 163
}

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

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

194 195 196 197 198 199 200 201 202 203
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("::");
        }

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

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

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

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

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

247
    pub fn path(&self) -> Option<&Path> {
248
        match self.kind {
249 250 251 252
            InvocationKind::Bang { ref mac, .. } => Some(&mac.node.path),
            InvocationKind::Attr { attr: Some(ref attr), .. } => Some(&attr.path),
            InvocationKind::Attr { attr: None, .. } => None,
            InvocationKind::Derive { ref path, .. } => Some(path),
253 254
        }
    }
255 256
}

257
pub struct MacroExpander<'a, 'b:'a> {
258
    pub cx: &'a mut ExtCtxt<'b>,
259
    monotonic: bool, // c.f. `cx.monotonic_expander()`
N
Nick Cameron 已提交
260 261 262
}

impl<'a, 'b> MacroExpander<'a, 'b> {
263
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
264
        MacroExpander { cx: cx, monotonic: monotonic }
N
Nick Cameron 已提交
265
    }
266

267 268
    pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
        let mut module = ModuleData {
269
            mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
270 271 272 273
            directory: match self.cx.codemap().span_to_unmapped_path(krate.span) {
                FileName::Real(path) => path,
                other => PathBuf::from(other.to_string()),
            },
274 275
        };
        module.directory.pop();
276
        self.cx.root_path = module.directory.clone();
277
        self.cx.current_expansion.module = Rc::new(module);
278
        self.cx.current_expansion.crate_span = Some(krate.span);
279

280 281
        let orig_mod_span = krate.module.inner;

282
        let krate_item = AstFragment::Items(OneVector::one(P(ast::Item {
283 284 285 286 287
            attrs: krate.attrs,
            span: krate.span,
            node: ast::ItemKind::Mod(krate.module),
            ident: keywords::Invalid.ident(),
            id: ast::DUMMY_NODE_ID,
288
            vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
289
            tokens: None,
290 291
        })));

292
        match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
293
            Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
294 295 296
                krate.attrs = attrs;
                krate.module = module;
            },
297 298 299 300 301 302 303 304
            None => {
                // Resolution failed so we return an empty expansion
                krate.attrs = vec![];
                krate.module = ast::Mod {
                    inner: orig_mod_span,
                    items: vec![],
                };
            },
305 306
            _ => unreachable!(),
        };
307
        self.cx.trace_macros_diag();
308 309 310
        krate
    }

311
    // Fully expand all macro invocations in this AST fragment.
312
    fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
313 314 315
        let orig_expansion_data = self.cx.current_expansion.clone();
        self.cx.current_expansion.depth = 0;

316
        // Collect all macro invocations and replace them with placeholders.
317 318
        let (fragment_with_placeholders, mut invocations)
            = self.collect_invocations(input_fragment, &[]);
319 320 321

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

324 325 326 327 328
        // Resolve paths in all invocations and produce ouput expanded fragments for them, but
        // 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();
329
        let mut expanded_fragments = Vec::new();
330
        let mut derives: HashMap<Mark, Vec<_>> = HashMap::new();
331 332 333
        let mut undetermined_invocations = Vec::new();
        let (mut progress, mut force) = (false, !self.monotonic);
        loop {
334
            let invoc = if let Some(invoc) = invocations.pop() {
335 336
                invoc
            } else {
337 338
                self.resolve_imports();
                if undetermined_invocations.is_empty() { break }
339 340 341 342 343 344 345
                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 };
346
            let ext = match self.cx.resolver.resolve_invoc(&invoc, scope, force) {
347 348 349 350 351 352 353 354 355
                Ok(ext) => Some(ext),
                Err(Determinacy::Determined) => None,
                Err(Determinacy::Undetermined) => {
                    undetermined_invocations.push(invoc);
                    continue
                }
            };

            progress = true;
356 357
            let ExpansionData { depth, mark, .. } = invoc.expansion_data;
            self.cx.current_expansion = invoc.expansion_data.clone();
358

359
            self.cx.current_expansion.mark = scope;
360
            // FIXME(jseyfried): Refactor out the following logic
361
            let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
362
                if let Some(ext) = ext {
363 364 365
                    let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
                    let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
                    self.collect_invocations(fragment, &[])
366
                } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
367 368
                    if !item.derive_allowed() {
                        let attr = attr::find_by_name(item.attrs(), "derive")
369 370 371 372 373 374 375
                            .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 已提交
376
                                .map(|t| t.to_string()).collect::<Vec<_>>();
377
                            let suggestion = format!("#[derive({})]", trait_list.join(", "));
378 379 380 381 382
                            err.span_suggestion_with_applicability(
                                span, "try an outer attribute", suggestion,
                                // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
                                Applicability::MaybeIncorrect
                            );
383 384
                        }
                        err.emit();
385 386
                    }

387
                    let item = self.fully_configure(item)
388
                        .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
389
                    let item_with_markers =
390
                        add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
391
                    let derives = derives.entry(invoc.expansion_data.mark).or_default();
392

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

423 424
            if expanded_fragments.len() < depth {
                expanded_fragments.push(Vec::new());
425
            }
426
            expanded_fragments[depth - 1].push((mark, expanded_fragment));
427
            if !self.cx.ecfg.single_step {
428 429 430 431
                invocations.extend(new_invocations.into_iter().rev());
            }
        }

432 433
        self.cx.current_expansion = orig_expansion_data;

434
        // Finally incorporate all the expanded macros into the input AST fragment.
435
        let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
436 437
        while let Some(expanded_fragments) = expanded_fragments.pop() {
            for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() {
438
                let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
439 440
                placeholder_expander.add(NodeId::placeholder_from_mark(mark),
                                         expanded_fragment, derives);
441 442
            }
        }
443
        fragment_with_placeholders.fold_with(&mut placeholder_expander)
444 445
    }

446 447 448 449 450 451 452 453
    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;
        }
    }

454 455 456 457
    /// 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.
458 459 460
    fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
                           -> (AstFragment, Vec<Invocation>) {
        let (fragment_with_placeholders, invocations) = {
461 462 463 464 465 466 467 468
            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(),
469
                monotonic: self.monotonic,
J
John Renner 已提交
470
                tests_nameable: true,
471
            };
472
            (fragment.fold_with(&mut collector), collector.invocations)
473
        };
474

475
        if self.monotonic {
476
            let err_count = self.cx.parse_sess.span_diagnostic.err_count();
477
            let mark = self.cx.current_expansion.mark;
478 479
            self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
                                                                  derives);
480
            self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
481 482
        }

483
        (fragment_with_placeholders, invocations)
484
    }
485

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
    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()))
            }
504 505 506 507 508
            Annotatable::ForeignItem(item) => {
                Annotatable::ForeignItem(
                    item.map(|item| cfg.fold_foreign_item(item).pop().unwrap())
                )
            }
509 510 511 512 513 514
            Annotatable::Stmt(stmt) => {
                Annotatable::Stmt(stmt.map(|stmt| cfg.fold_stmt(stmt).pop().unwrap()))
            }
            Annotatable::Expr(expr) => {
                Annotatable::Expr(cfg.fold_expr(expr))
            }
515 516 517
        }
    }

518
    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
V
Vadim Petrochenkov 已提交
519 520 521 522 523 524 525 526 527
        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");
            }
        }

528
        let result = match invoc.kind {
529 530 531
            InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
            InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?,
532 533 534 535 536
        };

        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;
537
            let mut err = self.cx.struct_span_err(info.call_site,
538
                &format!("recursion limit reached while expanding the macro `{}`",
539
                         info.format.name()));
540 541 542 543
            err.help(&format!(
                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                suggested_limit));
            err.emit();
544
            self.cx.trace_macros_diag();
545
            FatalError.raise();
546
        }
547

548
        Some(result)
549 550
    }

551 552
    fn expand_attr_invoc(&mut self,
                         invoc: Invocation,
553
                         ext: &SyntaxExtension)
554
                         -> Option<AstFragment> {
555
        let (attr, item) = match invoc.kind {
556
            InvocationKind::Attr { attr, item, .. } => (attr?, item),
557 558 559
            _ => unreachable!(),
        };

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

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

669
    fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
670 671 672
        if self.cx.ecfg.proc_macro_gen() {
            return
        }
673 674
        let fragment = match fragment {
            Some(fragment) => fragment,
675 676 677
            None => return,
        };

678
        fragment.visit_with(&mut DisallowModules {
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
            span,
            parse_sess: self.cx.parse_sess,
        });

        struct DisallowModules<'a> {
            span: Span,
            parse_sess: &'a ParseSess,
        }

        impl<'ast, 'a> Visitor<'ast> for DisallowModules<'a> {
            fn visit_item(&mut self, i: &'ast ast::Item) {
                let name = match i.node {
                    ast::ItemKind::Mod(_) => Some("modules"),
                    ast::ItemKind::MacroDef(_) => Some("macro definitions"),
                    _ => None,
                };
                if let Some(name) = name {
                    emit_feature_err(
                        self.parse_sess,
                        "proc_macro_gen",
                        self.span,
                        GateIssue::Language,
                        &format!("procedural macros cannot expand to {}", name),
                    );
                }
                visit::walk_item(self, i);
            }

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

713
    /// Expand a macro invocation. Returns the resulting expanded AST fragment.
714 715
    fn expand_bang_invoc(&mut self,
                         invoc: Invocation,
716
                         ext: &SyntaxExtension)
717 718
                         -> Option<AstFragment> {
        let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind);
719 720
        let (mac, ident, span) = match invoc.kind {
            InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
721 722
            _ => unreachable!(),
        };
J
Jeffrey Seyfried 已提交
723
        let path = &mac.node.path;
724

725
        let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
726 727
        let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
                                          def_site_span: Option<Span>,
728
                                          allow_internal_unstable,
729
                                          allow_internal_unsafe,
730
                                          local_inner_macros,
731
                                          // can't infer this type
732 733
                                          unstable_feature: Option<(Symbol, u32)>,
                                          edition| {
734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752

            // 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 已提交
753
            if ident.name != keywords::Invalid.name() {
754 755 756 757
                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 已提交
758 759 760
            }
            mark.set_expn_info(ExpnInfo {
                call_site: span,
761 762 763 764
                def_site: def_site_span,
                format: macro_bang_format(path),
                allow_internal_unstable,
                allow_internal_unsafe,
765
                local_inner_macros,
766
                edition,
J
Jeffrey Seyfried 已提交
767 768 769 770
            });
            Ok(())
        };

771
        let opt_expanded = match *ext {
772
            DeclMacro { ref expander, def_info, edition, .. } => {
773
                if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
774
                                                                    false, false, false, None,
775
                                                                    edition) {
776
                    dummy_span
777
                } else {
778
                    kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
779
                }
J
Jeffrey Seyfried 已提交
780
            }
781

782 783 784 785
            NormalTT {
                ref expander,
                def_info,
                allow_internal_unstable,
786
                allow_internal_unsafe,
787
                local_inner_macros,
788
                unstable_feature,
789
                edition,
790
            } => {
791 792 793
                if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
                                                                    allow_internal_unstable,
                                                                    allow_internal_unsafe,
794
                                                                    local_inner_macros,
795 796
                                                                    unstable_feature,
                                                                    edition) {
797
                    dummy_span
798 799
                } else {
                    kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
J
Jeffrey Seyfried 已提交
800
                }
801 802 803 804 805
            }

            IdentTT(ref expander, tt_span, allow_internal_unstable) => {
                if ident.name == keywords::Invalid.name() {
                    self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
806
                                    &format!("macro {}! expects an ident argument", path));
807
                    self.cx.trace_macros_diag();
808 809 810 811
                    kind.dummy(span)
                } else {
                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                        call_site: span,
812 813 814 815
                        def_site: tt_span,
                        format: macro_bang_format(path),
                        allow_internal_unstable,
                        allow_internal_unsafe: false,
816
                        local_inner_macros: false,
817
                        edition: hygiene::default_edition(),
818
                    });
819

820 821 822
                    let input: Vec<_> = mac.node.stream().into_trees().collect();
                    kind.make_from(expander.expand(self.cx, span, ident, input))
                }
823 824
            }

825
            MultiDecorator(..) | MultiModifier(..) |
826
            AttrProcMacro(..) | SyntaxExtension::NonMacroAttr { .. } => {
827
                self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
828
                                 &format!("`{}` can only be used in attributes", path));
829
                self.cx.trace_macros_diag();
830
                kind.dummy(span)
831
            }
832

833
            ProcMacroDerive(..) | BuiltinDerive(..) => {
J
Jeffrey Seyfried 已提交
834
                self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
835
                self.cx.trace_macros_diag();
836
                kind.dummy(span)
837 838
            }

839
            SyntaxExtension::ProcMacro { ref expander, allow_internal_unstable, edition } => {
840 841
                if ident.name != keywords::Invalid.name() {
                    let msg =
J
Jeffrey Seyfried 已提交
842
                        format!("macro {}! expects no ident argument, given '{}'", path, ident);
N
Nick Cameron 已提交
843
                    self.cx.span_err(path.span, &msg);
844
                    self.cx.trace_macros_diag();
845 846
                    kind.dummy(span)
                } else {
847
                    self.gate_proc_macro_expansion_kind(span, kind);
848 849
                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                        call_site: span,
850 851 852 853 854 855 856
                        // 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,
857
                        local_inner_macros: false,
858
                        edition,
859
                    });
860

861
                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
862
                    let result = self.parse_ast_fragment(tok_result, kind, path, span);
863 864
                    self.gate_proc_macro_expansion(span, &result);
                    result
865
                }
866
            }
867 868
        };

869 870 871
        if opt_expanded.is_some() {
            opt_expanded
        } else {
872
            let msg = format!("non-{kind} macro in {kind} position: {name}",
873
                              name = path.segments[0].ident.name, kind = kind.name());
874
            self.cx.span_err(path.span, &msg);
875
            self.cx.trace_macros_diag();
876
            kind.dummy(span)
877
        }
878
    }
J
Jeffrey Seyfried 已提交
879

880
    fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
881
        let kind = match kind {
882 883 884 885 886 887 888 889 890
            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,
891 892 893 894 895 896 897 898 899 900 901 902 903
        };
        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),
        );
    }

904
    /// Expand a derive invocation. Returns the resulting expanded AST fragment.
905 906
    fn expand_derive_invoc(&mut self,
                           invoc: Invocation,
907
                           ext: &SyntaxExtension)
908
                           -> Option<AstFragment> {
J
Jeffrey Seyfried 已提交
909 910
        let (path, item) = match invoc.kind {
            InvocationKind::Derive { path, item } => (path, item),
911 912
            _ => unreachable!(),
        };
913 914 915
        if !item.derive_allowed() {
            return None;
        }
916

J
Jeffrey Seyfried 已提交
917 918 919
        let pretty_name = Symbol::intern(&format!("derive({})", path));
        let span = path.span;
        let attr = ast::Attribute {
920 921
            path, span,
            tokens: TokenStream::empty(),
J
Jeffrey Seyfried 已提交
922 923 924
            // irrelevant:
            id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
        };
925

926
        let mut expn_info = ExpnInfo {
927
            call_site: span,
928 929 930 931
            def_site: None,
            format: MacroAttribute(pretty_name),
            allow_internal_unstable: false,
            allow_internal_unsafe: false,
932
            local_inner_macros: false,
933
            edition: ext.edition(),
934
        };
935 936

        match *ext {
937
            ProcMacroDerive(ref ext, ..) => {
938
                invoc.expansion_data.mark.set_expn_info(expn_info);
939
                let span = span.with_ctxt(self.cx.backtrace());
J
Jeffrey Seyfried 已提交
940
                let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
F
flip1995 已提交
941
                    ident: Path::from_ident(keywords::Invalid.ident()),
J
Jeffrey Seyfried 已提交
942 943 944
                    span: DUMMY_SP,
                    node: ast::MetaItemKind::Word,
                };
945
                let items = ext.expand(self.cx, span, &dummy, item);
946
                Some(invoc.fragment_kind.expect_from_annotatables(items))
947
            }
948
            BuiltinDerive(func) => {
949
                expn_info.allow_internal_unstable = true;
950
                invoc.expansion_data.mark.set_expn_info(expn_info);
951
                let span = span.with_ctxt(self.cx.backtrace());
952
                let mut items = Vec::new();
953
                func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
954
                Some(invoc.fragment_kind.expect_from_annotatables(items))
955 956
            }
            _ => {
J
Jeffrey Seyfried 已提交
957
                let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
958
                self.cx.span_err(span, msg);
959
                self.cx.trace_macros_diag();
960
                invoc.fragment_kind.dummy(span)
961 962 963 964
            }
        }
    }

965 966 967 968 969 970
    fn parse_ast_fragment(&mut self,
                          toks: TokenStream,
                          kind: AstFragmentKind,
                          path: &Path,
                          span: Span)
                          -> Option<AstFragment> {
971
        let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
972 973
        match parser.parse_ast_fragment(kind, false) {
            Ok(fragment) => {
974
                parser.ensure_complete_parse(path, kind.name(), span);
975
                Some(fragment)
976
            }
J
Jeffrey Seyfried 已提交
977
            Err(mut err) => {
978
                err.set_span(span);
J
Jeffrey Seyfried 已提交
979
                err.emit();
980
                self.cx.trace_macros_diag();
981
                kind.dummy(span)
J
Jeffrey Seyfried 已提交
982
            }
983
        }
J
Jeffrey Seyfried 已提交
984
    }
985 986
}

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

J
Jeffrey Seyfried 已提交
1045
    pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) {
1046 1047 1048
        if self.token != token::Eof {
            let msg = format!("macro expansion ignores token `{}` and any following",
                              self.this_token_to_string());
1049 1050
            // Avoid emitting backtrace info twice.
            let def_site_span = self.span.with_ctxt(SyntaxContext::empty());
1051
            let mut err = self.diagnostic().struct_span_err(def_site_span, &msg);
1052 1053
            let msg = format!("caused by the macro expansion here; the usage \
                               of `{}!` is likely invalid in {} context",
J
Jeffrey Seyfried 已提交
1054
                               macro_path, kind_name);
1055 1056 1057
            err.span_note(span, &msg).emit();
        }
    }
1058 1059 1060 1061
}

struct InvocationCollector<'a, 'b: 'a> {
    cx: &'a mut ExtCtxt<'b>,
1062
    cfg: StripUnconfigured<'a>,
1063
    invocations: Vec<Invocation>,
1064
    monotonic: bool,
J
John Renner 已提交
1065 1066 1067 1068 1069

    /// 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,
1070 1071 1072
}

impl<'a, 'b> InvocationCollector<'a, 'b> {
1073
    fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
J
Jeffrey Seyfried 已提交
1074
        let mark = Mark::fresh(self.cx.current_expansion.mark);
1075
        self.invocations.push(Invocation {
1076
            kind,
1077
            fragment_kind,
J
Jeffrey Seyfried 已提交
1078
            expansion_data: ExpansionData {
1079
                mark,
J
Jeffrey Seyfried 已提交
1080 1081 1082
                depth: self.cx.current_expansion.depth + 1,
                ..self.cx.current_expansion.clone()
            },
1083
        });
1084
        placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
1085
    }
1086

J
John Renner 已提交
1087 1088
    /// Folds the item allowing tests to be expanded because they are still nameable.
    /// This should probably only be called with module items
1089
    fn fold_nameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
J
John Renner 已提交
1090 1091 1092 1093
        fold::noop_fold_item(item, self)
    }

    /// Folds the item but doesn't allow tests to occur within it
1094
    fn fold_unnameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
J
John Renner 已提交
1095 1096 1097 1098 1099 1100
        let was_nameable = mem::replace(&mut self.tests_nameable, false);
        let items = fold::noop_fold_item(item, self);
        self.tests_nameable = was_nameable;
        items
    }

1101
    fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
1102
        self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
1103
    }
1104

1105 1106
    fn collect_attr(&mut self,
                    attr: Option<ast::Attribute>,
J
Jeffrey Seyfried 已提交
1107
                    traits: Vec<Path>,
1108
                    item: Annotatable,
1109 1110
                    kind: AstFragmentKind)
                    -> AstFragment {
1111
        self.collect(kind, InvocationKind::Attr { attr, traits, item })
1112 1113
    }

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

1120
        item = item.map_attrs(|mut attrs| {
1121 1122
            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
                                                                                     true) {
1123 1124 1125
                attr = Some(legacy_attr_invoc);
                return attrs;
            }
1126

1127
            attr = find_attr_invoc(&mut attrs);
1128
            traits = collect_derives(&mut self.cx, &mut attrs);
1129 1130
            attrs
        });
1131

1132
        (attr, traits, item)
1133 1134
    }

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
    /// 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;
            }

1148
            attr = find_attr_invoc(&mut attrs);
1149 1150 1151 1152 1153 1154
            attrs
        });

        (attr, item)
    }

1155 1156 1157
    fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
        self.cfg.configure(node)
    }
1158 1159 1160 1161 1162 1163

    // 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 已提交
1164
            self.check_attribute_inner(attr, features);
1165 1166 1167 1168 1169 1170 1171

            // 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();
            }
1172 1173
        }
    }
1174 1175 1176

    fn check_attribute(&mut self, at: &ast::Attribute) {
        let features = self.cx.ecfg.features.unwrap();
S
Seiichi Uchida 已提交
1177 1178 1179 1180
        self.check_attribute_inner(at, features);
    }

    fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) {
1181 1182
        feature_gate::check_attribute(at, self.cx.parse_sess, features);
    }
1183 1184
}

1185
pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
1186 1187 1188
    attrs.iter()
         .position(|a| !attr::is_known(a) && !is_builtin_attr(a))
         .map(|i| attrs.remove(i))
1189 1190
}

1191
impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
1192
    fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
1193
        let mut expr = self.cfg.configure_expr(expr).into_inner();
1194 1195
        expr.node = self.cfg.configure_expr_kind(expr.node);

1196 1197
        // ignore derives so they remain unused
        let (attr, expr) = self.classify_nonitem(expr);
1198

1199
        if attr.is_some() {
1200 1201 1202 1203
            // 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));

1204 1205 1206
            // AstFragmentKind::Expr requires the macro to emit an expression
            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
                                     AstFragmentKind::Expr).make_expr();
1207 1208
        }

1209
        if let ast::ExprKind::Mac(mac) = expr.node {
1210
            self.check_attributes(&expr.attrs);
1211
            self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr()
1212 1213 1214
        } else {
            P(noop_fold_expr(expr, self))
        }
1215 1216
    }

1217
    fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
1218
        let mut expr = configure!(self, expr).into_inner();
1219 1220
        expr.node = self.cfg.configure_expr_kind(expr.node);

1221 1222
        // ignore derives so they remain unused
        let (attr, expr) = self.classify_nonitem(expr);
1223

1224
        if attr.is_some() {
1225 1226
            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));

1227
            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
1228
                                     AstFragmentKind::OptExpr)
1229 1230 1231
                .make_opt_expr();
        }

1232
        if let ast::ExprKind::Mac(mac) = expr.node {
1233
            self.check_attributes(&expr.attrs);
1234
            self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr()
1235 1236 1237
        } else {
            Some(P(noop_fold_expr(expr, self)))
        }
1238 1239
    }

1240
    fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
1241
        let pat = self.cfg.configure_pat(pat);
1242 1243
        match pat.node {
            PatKind::Mac(_) => {}
1244
            _ => return noop_fold_pat(pat, self),
1245
        }
K
Keegan McAllister 已提交
1246

1247
        pat.and_then(|pat| match pat.node {
1248
            PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
1249 1250
            _ => unreachable!(),
        })
1251 1252
    }

1253
    fn fold_stmt(&mut self, stmt: ast::Stmt) -> OneVector<ast::Stmt> {
1254
        let mut stmt = match self.cfg.configure_stmt(stmt) {
1255
            Some(stmt) => stmt,
1256
            None => return OneVector::new(),
1257 1258
        };

1259 1260
        // we'll expand attributes on expressions separately
        if !stmt.is_expr() {
1261 1262 1263 1264 1265 1266 1267 1268
            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)
            };
1269 1270 1271

            if attr.is_some() || !derives.is_empty() {
                return self.collect_attr(attr, derives,
1272
                                         Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts)
1273 1274
                    .make_stmts();
            }
1275

1276 1277
            stmt = stmt_;
        }
1278

1279 1280 1281
        if let StmtKind::Mac(mac) = stmt.node {
            let (mac, style, attrs) = mac.into_inner();
            self.check_attributes(&attrs);
1282
            let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts)
1283 1284 1285 1286 1287 1288 1289 1290
                                        .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());
                }
1291
            }
1292 1293

            return placeholder;
1294 1295
        }

1296 1297 1298 1299 1300 1301
        // 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()

1302 1303
    }

S
Steven Fackler 已提交
1304
    fn fold_block(&mut self, block: P<Block>) -> P<Block> {
1305 1306
        let old_directory_ownership = self.cx.current_expansion.directory_ownership;
        self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
J
Jeffrey Seyfried 已提交
1307
        let result = noop_fold_block(block, self);
1308
        self.cx.current_expansion.directory_ownership = old_directory_ownership;
1309
        result
1310 1311
    }

1312
    fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
1313 1314
        let item = configure!(self, item);

1315 1316
        let (attr, traits, mut item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1317
            let item = Annotatable::Item(item);
1318
            return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
1319 1320 1321 1322
        }

        match item.node {
            ast::ItemKind::Mac(..) => {
1323
                self.check_attributes(&item.attrs);
1324
                item.and_then(|item| match item.node {
1325
                    ItemKind::Mac(mac) => {
1326
                        self.collect(AstFragmentKind::Items, InvocationKind::Bang {
1327
                            mac,
1328 1329
                            ident: Some(item.ident),
                            span: item.span,
1330
                        }).make_items()
1331 1332 1333 1334 1335
                    }
                    _ => unreachable!(),
                })
            }
            ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
1336
                if item.ident == keywords::Invalid.ident() {
J
John Renner 已提交
1337
                    return self.fold_nameable(item);
1338 1339
                }

1340
                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1341 1342
                let mut module = (*self.cx.current_expansion.module).clone();
                module.mod_path.push(item.ident);
1343 1344 1345 1346

                // 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 已提交
1347
                let inline_module = item.span.contains(inner) || inner.is_dummy();
1348 1349

                if inline_module {
1350
                    if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
1351 1352
                        self.cx.current_expansion.directory_ownership =
                            DirectoryOwnership::Owned { relative: None };
1353
                        module.directory.push(&*path.as_str());
1354
                    } else {
V
Vadim Petrochenkov 已提交
1355
                        module.directory.push(&*item.ident.as_str());
1356
                    }
1357
                } else {
1358 1359 1360 1361 1362
                    let path = self.cx.parse_sess.codemap().span_to_unmapped_path(inner);
                    let mut path = match path {
                        FileName::Real(path) => path,
                        other => PathBuf::from(other.to_string()),
                    };
1363
                    let directory_ownership = match path.file_name().unwrap().to_str() {
1364 1365 1366 1367 1368
                        Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
                        Some(_) => DirectoryOwnership::Owned {
                            relative: Some(item.ident),
                        },
                        None => DirectoryOwnership::UnownedViaMod(false),
1369 1370 1371 1372
                    };
                    path.pop();
                    module.directory = path;
                    self.cx.current_expansion.directory_ownership = directory_ownership;
1373 1374
                }

1375 1376
                let orig_module =
                    mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
J
John Renner 已提交
1377
                let result = self.fold_nameable(item);
1378
                self.cx.current_expansion.module = orig_module;
1379
                self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1380
                result
1381
            }
1382
            // Ensure that test functions are accessible from the test harness.
J
John Renner 已提交
1383 1384 1385
            // #[test] fn foo() {}
            // becomes:
            // #[test] pub fn foo_gensym(){}
J
John Renner 已提交
1386
            // #[allow(unused)]
J
John Renner 已提交
1387
            // use foo_gensym as foo;
1388
            ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
J
John Renner 已提交
1389
                if self.tests_nameable && item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
J
John Renner 已提交
1390 1391
                    let orig_ident = item.ident;
                    let orig_vis   = item.vis.clone();
1392 1393

                    // Publicize the item under gensymed name to avoid pollution
1394 1395
                    item = item.map(|mut item| {
                        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
J
John Renner 已提交
1396
                        item.ident = item.ident.gensym();
1397 1398
                        item
                    });
1399 1400

                    // Use the gensymed name under the item's original visibility
J
John Renner 已提交
1401
                    let mut use_item = self.cx.item_use_simple_(
1402 1403
                        item.ident.span,
                        orig_vis,
J
John Renner 已提交
1404 1405 1406
                        Some(orig_ident),
                        self.cx.path(item.ident.span,
                            vec![keywords::SelfValue.ident(), item.ident]));
1407

J
John Renner 已提交
1408
                    // #[allow(unused)] because the test function probably isn't being referenced
J
John Renner 已提交
1409 1410 1411 1412
                    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 已提交
1413
                                    attr::mk_nested_word_item(Ident::from_str("unused"))
J
John Renner 已提交
1414 1415 1416 1417 1418 1419 1420
                                ]
                            ))
                        );

                        ui
                    });

1421
                    OneVector::many(
J
John Renner 已提交
1422 1423
                        self.fold_unnameable(item).into_iter()
                            .chain(self.fold_unnameable(use_item)))
1424
                } else {
J
John Renner 已提交
1425
                    self.fold_unnameable(item)
1426 1427
                }
            }
J
John Renner 已提交
1428
            _ => self.fold_unnameable(item),
1429
        }
1430 1431
    }

1432
    fn fold_trait_item(&mut self, item: ast::TraitItem) -> OneVector<ast::TraitItem> {
1433 1434
        let item = configure!(self, item);

1435 1436
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1437
            let item = Annotatable::TraitItem(P(item));
1438
            return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems)
1439
                .make_trait_items()
1440 1441 1442 1443 1444
        }

        match item.node {
            ast::TraitItemKind::Macro(mac) => {
                let ast::TraitItem { attrs, span, .. } = item;
1445
                self.check_attributes(&attrs);
1446
                self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
1447 1448 1449 1450 1451
            }
            _ => fold::noop_fold_trait_item(item, self),
        }
    }

1452
    fn fold_impl_item(&mut self, item: ast::ImplItem) -> OneVector<ast::ImplItem> {
1453 1454
        let item = configure!(self, item);

1455 1456
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1457
            let item = Annotatable::ImplItem(P(item));
1458
            return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems)
1459
                .make_impl_items();
1460 1461 1462 1463 1464
        }

        match item.node {
            ast::ImplItemKind::Macro(mac) => {
                let ast::ImplItem { attrs, span, .. } = item;
1465
                self.check_attributes(&attrs);
1466
                self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
1467
            }
1468
            _ => fold::noop_fold_impl_item(item, self),
1469
        }
1470 1471
    }

1472
    fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
1473
        let ty = match ty.node {
1474
            ast::TyKind::Mac(_) => ty.into_inner(),
1475 1476 1477 1478
            _ => return fold::noop_fold_ty(ty, self),
        };

        match ty.node {
1479
            ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
1480 1481
            _ => unreachable!(),
        }
1482
    }
1483 1484 1485 1486 1487

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

1488
    fn fold_foreign_item(&mut self,
1489
                         foreign_item: ast::ForeignItem) -> OneVector<ast::ForeignItem> {
1490 1491
        let (attr, traits, foreign_item) = self.classify_item(foreign_item);

V
Vadim Petrochenkov 已提交
1492
        if attr.is_some() || !traits.is_empty() {
1493
            let item = Annotatable::ForeignItem(P(foreign_item));
1494
            return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
1495 1496 1497 1498 1499
                .make_foreign_items();
        }

        if let ast::ForeignItemKind::Macro(mac) = foreign_item.node {
            self.check_attributes(&foreign_item.attrs);
1500
            return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
1501 1502 1503 1504 1505 1506
                .make_foreign_items();
        }

        noop_fold_foreign_item(foreign_item, self)
    }

1507
    fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
1508 1509 1510 1511
        match item {
            ast::ItemKind::MacroDef(..) => item,
            _ => noop_fold_item_kind(self.cfg.configure_item_kind(item), self),
        }
1512
    }
1513

1514 1515 1516 1517 1518
    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)
    }

1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
    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) => {
1553 1554 1555 1556
                            self.cx.span_err(at.span,
                                             &format!("couldn't read {}: {}",
                                                      filename.display(),
                                                      e));
1557 1558 1559 1560 1561
                        }
                    }

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

1564 1565
                            // Add this input file to the code map to make it available as
                            // dependency information
D
Donato Sciarra 已提交
1566
                            self.cx.codemap().new_source_file(filename.into(), src);
1567

1568 1569
                            let include_info = vec![
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
1570 1571
                                        attr::mk_name_value_item_str(Ident::from_str("file"),
                                                                     dummy_spanned(file)))),
1572
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
1573
                                        attr::mk_name_value_item_str(Ident::from_str("contents"),
1574
                                                            dummy_spanned(src_interned)))),
1575 1576
                            ];

1577 1578 1579
                            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)));
1580 1581
                        }
                        Err(_) => {
1582 1583 1584
                            self.cx.span_err(at.span,
                                             &format!("{} wasn't a utf-8 file",
                                                      filename.display()));
1585 1586 1587 1588 1589 1590 1591
                        }
                    }
                } else {
                    items.push(noop_fold_meta_list_item(it, self));
                }
            }

1592
            let meta = attr::mk_list_item(DUMMY_SP, Ident::from_str("doc"), items);
1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603
            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)
        }
    }

1604
    fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
1605 1606 1607 1608 1609 1610
        if self.monotonic {
            assert_eq!(id, ast::DUMMY_NODE_ID);
            self.cx.resolver.next_node_id()
        } else {
            id
        }
1611
    }
1612 1613
}

1614
pub struct ExpansionConfig<'feat> {
1615
    pub crate_name: String,
1616
    pub features: Option<&'feat Features>,
P
Paul Collier 已提交
1617
    pub recursion_limit: usize,
1618
    pub trace_mac: bool,
1619
    pub should_test: bool, // If false, strip `#[test]` nodes
1620 1621
    pub single_step: bool,
    pub keep_macs: bool,
1622 1623
}

1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
macro_rules! feature_tests {
    ($( fn $getter:ident = $field:ident, )*) => {
        $(
            pub fn $getter(&self) -> bool {
                match self.features {
                    Some(&Features { $field: true, .. }) => true,
                    _ => false,
                }
            }
        )*
    }
}

1637 1638
impl<'feat> ExpansionConfig<'feat> {
    pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1639
        ExpansionConfig {
1640
            crate_name,
1641
            features: None,
1642
            recursion_limit: 1024,
1643
            trace_mac: false,
1644
            should_test: false,
1645 1646
            single_step: false,
            keep_macs: false,
1647 1648
        }
    }
1649

1650
    feature_tests! {
1651 1652
        fn enable_quotes = quote,
        fn enable_asm = asm,
1653
        fn enable_global_asm = global_asm,
1654 1655 1656
        fn enable_log_syntax = log_syntax,
        fn enable_concat_idents = concat_idents,
        fn enable_trace_macros = trace_macros,
1657
        fn enable_allow_internal_unstable = allow_internal_unstable,
1658
        fn enable_custom_derive = custom_derive,
1659
        fn enable_format_args_nl = format_args_nl,
1660
        fn macros_in_extern_enabled = macros_in_extern,
1661
        fn proc_macro_mod = proc_macro_mod,
1662
        fn proc_macro_gen = proc_macro_gen,
1663 1664
        fn proc_macro_expr = proc_macro_expr,
        fn proc_macro_non_items = proc_macro_non_items,
1665
    }
1666 1667
}

1668
// A Marker adds the given mark to the syntax context.
1669
#[derive(Debug)]
1670
pub struct Marker(pub Mark);
1671

E
Eduard Burtescu 已提交
1672
impl Folder for Marker {
1673
    fn new_span(&mut self, span: Span) -> Span {
1674
        span.apply_mark(self.0)
1675
    }
1676 1677 1678 1679

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