expand.rs 65.9 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};
14
use codemap::{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::derive::{add_derived_markers, collect_derives};
19
use ext::hygiene::{self, Mark, SyntaxContext};
20
use ext::placeholders::{placeholder, PlaceholderExpander};
21
use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
J
John Clements 已提交
22
use fold;
23
use fold::*;
24
use parse::{DirectoryOwnership, PResult, ParseSess};
J
Jeffrey Seyfried 已提交
25
use parse::token::{self, Token};
N
Nick Cameron 已提交
26
use parse::parser::Parser;
27
use ptr::P;
28
use symbol::Symbol;
29
use symbol::keywords;
30
use syntax_pos::{Span, DUMMY_SP, FileName};
31
use syntax_pos::hygiene::ExpnFormat;
J
Jeffrey Seyfried 已提交
32
use tokenstream::{TokenStream, TokenTree};
33
use util::small_vector::SmallVector;
34
use visit::{self, Visitor};
35

36
use std::collections::HashMap;
37 38
use std::fs::File;
use std::io::Read;
39
use std::mem;
J
Jeffrey Seyfried 已提交
40
use std::rc::Rc;
41
use std::path::PathBuf;
42

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

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

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

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

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

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

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

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

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

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

144
ast_fragments! {
145 146 147 148 149 150 151 152 153 154 155 156 157 158
    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; }
    Stmts(SmallVector<ast::Stmt>) { "statement"; many fn fold_stmt; fn visit_stmt; fn make_stmts; }
    Items(SmallVector<P<ast::Item>>) { "item"; many fn fold_item; fn visit_item; fn make_items; }
    TraitItems(SmallVector<ast::TraitItem>) {
        "trait item"; many fn fold_trait_item; fn visit_trait_item; fn make_trait_items;
    }
    ImplItems(SmallVector<ast::ImplItem>) {
        "impl item"; many fn fold_impl_item; fn visit_impl_item; fn make_impl_items;
    }
    ForeignItems(SmallVector<ast::ForeignItem>) {
        "foreign item"; many fn fold_foreign_item; fn visit_foreign_item; fn make_foreign_items;
    }
159 160
}

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

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

191 192 193 194 195 196 197 198 199 200
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("::");
        }

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

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

211
pub struct Invocation {
212
    pub kind: InvocationKind,
213
    fragment_kind: AstFragmentKind,
214
    pub expansion_data: ExpansionData,
215 216
}

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

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

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

impl<'a, 'b> MacroExpander<'a, 'b> {
251
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
252
        MacroExpander { cx: cx, monotonic: monotonic }
N
Nick Cameron 已提交
253
    }
254

255 256
    pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
        let mut module = ModuleData {
257
            mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
258 259 260 261
            directory: match self.cx.codemap().span_to_unmapped_path(krate.span) {
                FileName::Real(path) => path,
                other => PathBuf::from(other.to_string()),
            },
262 263
        };
        module.directory.pop();
264
        self.cx.root_path = module.directory.clone();
265
        self.cx.current_expansion.module = Rc::new(module);
266
        self.cx.current_expansion.crate_span = Some(krate.span);
267

268 269
        let orig_mod_span = krate.module.inner;

270
        let krate_item = AstFragment::Items(SmallVector::one(P(ast::Item {
271 272 273 274 275
            attrs: krate.attrs,
            span: krate.span,
            node: ast::ItemKind::Mod(krate.module),
            ident: keywords::Invalid.ident(),
            id: ast::DUMMY_NODE_ID,
276
            vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
277
            tokens: None,
278 279
        })));

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

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

304
        // Collect all macro invocations and replace them with placeholders.
305 306
        let (fragment_with_placeholders, mut invocations)
            = self.collect_invocations(input_fragment, &[]);
307 308 309

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

312 313 314 315 316
        // 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();
317
        let mut expanded_fragments = Vec::new();
318
        let mut derives = HashMap::new();
319 320 321
        let mut undetermined_invocations = Vec::new();
        let (mut progress, mut force) = (false, !self.monotonic);
        loop {
322
            let mut invoc = if let Some(invoc) = invocations.pop() {
323 324
                invoc
            } else {
325 326
                self.resolve_imports();
                if undetermined_invocations.is_empty() { break }
327 328 329 330 331 332 333
                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 };
334
            let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
335 336 337 338 339 340 341 342 343
                Ok(ext) => Some(ext),
                Err(Determinacy::Determined) => None,
                Err(Determinacy::Undetermined) => {
                    undetermined_invocations.push(invoc);
                    continue
                }
            };

            progress = true;
344 345
            let ExpansionData { depth, mark, .. } = invoc.expansion_data;
            self.cx.current_expansion = invoc.expansion_data.clone();
346

347
            self.cx.current_expansion.mark = scope;
348
            // FIXME(jseyfried): Refactor out the following logic
349
            let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
350
                if let Some(ext) = ext {
351 352 353
                    let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
                    let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
                    self.collect_invocations(fragment, &[])
354
                } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
355 356
                    if !item.derive_allowed() {
                        let attr = attr::find_by_name(item.attrs(), "derive")
357 358 359 360 361 362 363 364 365
                            .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()
                                .map(|t| format!("{}", t)).collect::<Vec<_>>();
                            let suggestion = format!("#[derive({})]", trait_list.join(", "));
366 367 368 369 370
                            err.span_suggestion_with_applicability(
                                span, "try an outer attribute", suggestion,
                                // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
                                Applicability::MaybeIncorrect
                            );
371 372
                        }
                        err.emit();
373 374
                    }

375
                    let item = self.fully_configure(item)
376
                        .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
377
                    let item_with_markers =
378
                        add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
379 380
                    let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new);

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

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

420 421
        self.cx.current_expansion = orig_expansion_data;

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

434 435 436 437 438 439 440 441
    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;
        }
    }

442 443 444 445
    /// 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.
446 447 448
    fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
                           -> (AstFragment, Vec<Invocation>) {
        let (fragment_with_placeholders, invocations) = {
449 450 451 452 453 454 455 456
            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(),
457
                monotonic: self.monotonic,
458
            };
459
            (fragment.fold_with(&mut collector), collector.invocations)
460
        };
461

462
        if self.monotonic {
463
            let err_count = self.cx.parse_sess.span_diagnostic.err_count();
464
            let mark = self.cx.current_expansion.mark;
465 466
            self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
                                                                  derives);
467
            self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
468 469
        }

470
        (fragment_with_placeholders, invocations)
471
    }
472

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
    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()))
            }
491 492 493 494 495
            Annotatable::ForeignItem(item) => {
                Annotatable::ForeignItem(
                    item.map(|item| cfg.fold_foreign_item(item).pop().unwrap())
                )
            }
496 497 498 499 500 501
            Annotatable::Stmt(stmt) => {
                Annotatable::Stmt(stmt.map(|stmt| cfg.fold_stmt(stmt).pop().unwrap()))
            }
            Annotatable::Expr(expr) => {
                Annotatable::Expr(cfg.fold_expr(expr))
            }
502 503 504
        }
    }

505
    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
506
        let result = match invoc.kind {
507 508 509
            InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
            InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?,
510 511 512 513 514
        };

        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;
515
            let mut err = self.cx.struct_span_err(info.call_site,
516
                &format!("recursion limit reached while expanding the macro `{}`",
517
                         info.format.name()));
518 519 520 521
            err.help(&format!(
                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                suggested_limit));
            err.emit();
522
            self.cx.trace_macros_diag();
523
            FatalError.raise();
524
        }
525

526
        Some(result)
527 528
    }

529 530
    fn expand_attr_invoc(&mut self,
                         invoc: Invocation,
531
                         ext: &SyntaxExtension)
532
                         -> Option<AstFragment> {
533
        let (attr, item) = match invoc.kind {
534
            InvocationKind::Attr { attr, item, .. } => (attr?, item),
535 536 537 538
            _ => unreachable!(),
        };

        attr::mark_used(&attr);
539
        invoc.expansion_data.mark.set_expn_info(ExpnInfo {
540
            call_site: attr.span,
541 542 543 544
            def_site: None,
            format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
            allow_internal_unstable: false,
            allow_internal_unsafe: false,
545
            local_inner_macros: false,
546
            edition: ext.edition(),
547 548
        });

549
        match *ext {
550
            MultiModifier(ref mac) => {
551 552
                let meta = attr.parse_meta(self.cx.parse_sess)
                               .map_err(|mut e| { e.emit(); }).ok()?;
553
                let item = mac.expand(self.cx, attr.span, &meta, item);
554
                Some(invoc.fragment_kind.expect_from_annotatables(item))
555 556 557
            }
            MultiDecorator(ref mac) => {
                let mut items = Vec::new();
558 559
                let meta = attr.parse_meta(self.cx.parse_sess)
                               .expect("derive meta should already have been parsed");
560
                mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
561
                items.push(item);
562
                Some(invoc.fragment_kind.expect_from_annotatables(items))
563
            }
564
            AttrProcMacro(ref mac, ..) => {
565
                self.gate_proc_macro_attr_item(attr.span, &item);
J
Jeffrey Seyfried 已提交
566 567
                let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
                    Annotatable::Item(item) => token::NtItem(item),
568 569
                    Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
                    Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
570
                    Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
571 572
                    Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                    Annotatable::Expr(expr) => token::NtExpr(expr),
J
Jeffrey Seyfried 已提交
573
                })).into();
574 575
                let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
                let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
576 577
                let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
                                                  &attr.path, attr.span);
578 579
                self.gate_proc_macro_expansion(attr.span, &res);
                res
580
            }
581
            ProcMacroDerive(..) | BuiltinDerive(..) => {
J
Jeffrey Seyfried 已提交
582
                self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
583
                self.cx.trace_macros_diag();
584
                invoc.fragment_kind.dummy(attr.span)
585 586
            }
            _ => {
J
Jeffrey Seyfried 已提交
587
                let msg = &format!("macro `{}` may not be used in attributes", attr.path);
588
                self.cx.span_err(attr.span, msg);
589
                self.cx.trace_macros_diag();
590
                invoc.fragment_kind.dummy(attr.span)
591
            }
592
        }
593 594
    }

595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
    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),
        );
    }

638
    fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
639 640 641
        if self.cx.ecfg.proc_macro_gen() {
            return
        }
642 643
        let fragment = match fragment {
            Some(fragment) => fragment,
644 645 646
            None => return,
        };

647
        fragment.visit_with(&mut DisallowModules {
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
            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) {
                // ...
            }
        }
    }

682
    /// Expand a macro invocation. Returns the resulting expanded AST fragment.
683 684
    fn expand_bang_invoc(&mut self,
                         invoc: Invocation,
685
                         ext: &SyntaxExtension)
686 687
                         -> Option<AstFragment> {
        let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind);
688 689
        let (mac, ident, span) = match invoc.kind {
            InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
690 691
            _ => unreachable!(),
        };
J
Jeffrey Seyfried 已提交
692
        let path = &mac.node.path;
693

694
        let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
695 696
        let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
                                          def_site_span: Option<Span>,
697
                                          allow_internal_unstable,
698
                                          allow_internal_unsafe,
699
                                          local_inner_macros,
700
                                          // can't infer this type
701 702
                                          unstable_feature: Option<(Symbol, u32)>,
                                          edition| {
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721

            // 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 已提交
722
            if ident.name != keywords::Invalid.name() {
723 724 725 726
                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 已提交
727 728 729
            }
            mark.set_expn_info(ExpnInfo {
                call_site: span,
730 731 732 733
                def_site: def_site_span,
                format: macro_bang_format(path),
                allow_internal_unstable,
                allow_internal_unsafe,
734
                local_inner_macros,
735
                edition,
J
Jeffrey Seyfried 已提交
736 737 738 739
            });
            Ok(())
        };

740
        let opt_expanded = match *ext {
741
            DeclMacro { ref expander, def_info, edition, .. } => {
742
                if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
743
                                                                    false, false, false, None,
744
                                                                    edition) {
745
                    dummy_span
746
                } else {
747
                    kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
748
                }
J
Jeffrey Seyfried 已提交
749
            }
750

751 752 753 754
            NormalTT {
                ref expander,
                def_info,
                allow_internal_unstable,
755
                allow_internal_unsafe,
756
                local_inner_macros,
757
                unstable_feature,
758
                edition,
759
            } => {
760 761 762
                if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
                                                                    allow_internal_unstable,
                                                                    allow_internal_unsafe,
763
                                                                    local_inner_macros,
764 765
                                                                    unstable_feature,
                                                                    edition) {
766
                    dummy_span
767 768
                } else {
                    kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
J
Jeffrey Seyfried 已提交
769
                }
770 771 772 773 774
            }

            IdentTT(ref expander, tt_span, allow_internal_unstable) => {
                if ident.name == keywords::Invalid.name() {
                    self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
775
                                    &format!("macro {}! expects an ident argument", path));
776
                    self.cx.trace_macros_diag();
777 778 779 780
                    kind.dummy(span)
                } else {
                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                        call_site: span,
781 782 783 784
                        def_site: tt_span,
                        format: macro_bang_format(path),
                        allow_internal_unstable,
                        allow_internal_unsafe: false,
785
                        local_inner_macros: false,
786
                        edition: hygiene::default_edition(),
787
                    });
788

789 790 791
                    let input: Vec<_> = mac.node.stream().into_trees().collect();
                    kind.make_from(expander.expand(self.cx, span, ident, input))
                }
792 793
            }

794
            MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
795
                self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
796
                                 &format!("`{}` can only be used in attributes", path));
797
                self.cx.trace_macros_diag();
798
                kind.dummy(span)
799
            }
800

801
            ProcMacroDerive(..) | BuiltinDerive(..) => {
J
Jeffrey Seyfried 已提交
802
                self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
803
                self.cx.trace_macros_diag();
804
                kind.dummy(span)
805 806
            }

807
            SyntaxExtension::ProcMacro { ref expander, allow_internal_unstable, edition } => {
808 809
                if ident.name != keywords::Invalid.name() {
                    let msg =
J
Jeffrey Seyfried 已提交
810
                        format!("macro {}! expects no ident argument, given '{}'", path, ident);
N
Nick Cameron 已提交
811
                    self.cx.span_err(path.span, &msg);
812
                    self.cx.trace_macros_diag();
813 814
                    kind.dummy(span)
                } else {
815
                    self.gate_proc_macro_expansion_kind(span, kind);
816 817
                    invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                        call_site: span,
818 819 820 821 822 823 824
                        // 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,
825
                        local_inner_macros: false,
826
                        edition,
827
                    });
828

829
                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
830
                    let result = self.parse_ast_fragment(tok_result, kind, path, span);
831 832
                    self.gate_proc_macro_expansion(span, &result);
                    result
833
                }
834
            }
835 836
        };

837 838 839
        if opt_expanded.is_some() {
            opt_expanded
        } else {
840
            let msg = format!("non-{kind} macro in {kind} position: {name}",
841
                              name = path.segments[0].ident.name, kind = kind.name());
842
            self.cx.span_err(path.span, &msg);
843
            self.cx.trace_macros_diag();
844
            kind.dummy(span)
845
        }
846
    }
J
Jeffrey Seyfried 已提交
847

848
    fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
849
        let kind = match kind {
850 851 852 853 854 855 856 857 858
            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,
859 860 861 862 863 864 865 866 867 868 869 870 871
        };
        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),
        );
    }

872
    /// Expand a derive invocation. Returns the resulting expanded AST fragment.
873 874
    fn expand_derive_invoc(&mut self,
                           invoc: Invocation,
875
                           ext: &SyntaxExtension)
876
                           -> Option<AstFragment> {
J
Jeffrey Seyfried 已提交
877 878
        let (path, item) = match invoc.kind {
            InvocationKind::Derive { path, item } => (path, item),
879 880
            _ => unreachable!(),
        };
881 882 883
        if !item.derive_allowed() {
            return None;
        }
884

J
Jeffrey Seyfried 已提交
885 886 887
        let pretty_name = Symbol::intern(&format!("derive({})", path));
        let span = path.span;
        let attr = ast::Attribute {
888 889
            path, span,
            tokens: TokenStream::empty(),
J
Jeffrey Seyfried 已提交
890 891 892
            // irrelevant:
            id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
        };
893

894
        let mut expn_info = ExpnInfo {
895
            call_site: span,
896 897 898 899
            def_site: None,
            format: MacroAttribute(pretty_name),
            allow_internal_unstable: false,
            allow_internal_unsafe: false,
900
            local_inner_macros: false,
901
            edition: ext.edition(),
902
        };
903 904

        match *ext {
905
            ProcMacroDerive(ref ext, ..) => {
906
                invoc.expansion_data.mark.set_expn_info(expn_info);
907
                let span = span.with_ctxt(self.cx.backtrace());
J
Jeffrey Seyfried 已提交
908
                let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
F
flip1995 已提交
909
                    ident: Path::from_ident(keywords::Invalid.ident()),
J
Jeffrey Seyfried 已提交
910 911 912
                    span: DUMMY_SP,
                    node: ast::MetaItemKind::Word,
                };
913
                let items = ext.expand(self.cx, span, &dummy, item);
914
                Some(invoc.fragment_kind.expect_from_annotatables(items))
915
            }
916
            BuiltinDerive(func) => {
917
                expn_info.allow_internal_unstable = true;
918
                invoc.expansion_data.mark.set_expn_info(expn_info);
919
                let span = span.with_ctxt(self.cx.backtrace());
920
                let mut items = Vec::new();
921
                func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
922
                Some(invoc.fragment_kind.expect_from_annotatables(items))
923 924
            }
            _ => {
J
Jeffrey Seyfried 已提交
925
                let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
926
                self.cx.span_err(span, msg);
927
                self.cx.trace_macros_diag();
928
                invoc.fragment_kind.dummy(span)
929 930 931 932
            }
        }
    }

933 934 935 936 937 938
    fn parse_ast_fragment(&mut self,
                          toks: TokenStream,
                          kind: AstFragmentKind,
                          path: &Path,
                          span: Span)
                          -> Option<AstFragment> {
939
        let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
940 941
        match parser.parse_ast_fragment(kind, false) {
            Ok(fragment) => {
942
                parser.ensure_complete_parse(path, kind.name(), span);
943
                Some(fragment)
944
            }
J
Jeffrey Seyfried 已提交
945
            Err(mut err) => {
946
                err.set_span(span);
J
Jeffrey Seyfried 已提交
947
                err.emit();
948
                self.cx.trace_macros_diag();
949
                kind.dummy(span)
J
Jeffrey Seyfried 已提交
950
            }
951
        }
J
Jeffrey Seyfried 已提交
952
    }
953 954
}

955
impl<'a> Parser<'a> {
956 957
    pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warnings: bool)
                              -> PResult<'a, AstFragment> {
958
        Ok(match kind {
959
            AstFragmentKind::Items => {
960
                let mut items = SmallVector::new();
961 962 963
                while let Some(item) = self.parse_item()? {
                    items.push(item);
                }
964
                AstFragment::Items(items)
965
            }
966
            AstFragmentKind::TraitItems => {
967
                let mut items = SmallVector::new();
968
                while self.token != token::Eof {
969
                    items.push(self.parse_trait_item(&mut false)?);
970
                }
971
                AstFragment::TraitItems(items)
972
            }
973
            AstFragmentKind::ImplItems => {
974
                let mut items = SmallVector::new();
975
                while self.token != token::Eof {
976
                    items.push(self.parse_impl_item(&mut false)?);
977
                }
978
                AstFragment::ImplItems(items)
979
            }
980
            AstFragmentKind::ForeignItems => {
981 982 983 984 985 986
                let mut items = SmallVector::new();
                while self.token != token::Eof {
                    if let Some(item) = self.parse_foreign_item()? {
                        items.push(item);
                    }
                }
987
                AstFragment::ForeignItems(items)
988
            }
989
            AstFragmentKind::Stmts => {
990
                let mut stmts = SmallVector::new();
G
Geoffry Song 已提交
991 992 993
                while self.token != token::Eof &&
                      // won't make progress on a `}`
                      self.token != token::CloseDelim(token::Brace) {
J
Jeffrey Seyfried 已提交
994
                    if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? {
995 996 997
                        stmts.push(stmt);
                    }
                }
998
                AstFragment::Stmts(stmts)
999
            }
1000 1001
            AstFragmentKind::Expr => AstFragment::Expr(self.parse_expr()?),
            AstFragmentKind::OptExpr => {
1002
                if self.token != token::Eof {
1003
                    AstFragment::OptExpr(Some(self.parse_expr()?))
1004
                } else {
1005
                    AstFragment::OptExpr(None)
1006 1007
                }
            },
1008 1009
            AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?),
            AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat()?),
1010 1011
        })
    }
1012

J
Jeffrey Seyfried 已提交
1013
    pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) {
1014 1015 1016
        if self.token != token::Eof {
            let msg = format!("macro expansion ignores token `{}` and any following",
                              self.this_token_to_string());
1017 1018
            // Avoid emitting backtrace info twice.
            let def_site_span = self.span.with_ctxt(SyntaxContext::empty());
1019
            let mut err = self.diagnostic().struct_span_err(def_site_span, &msg);
1020 1021
            let msg = format!("caused by the macro expansion here; the usage \
                               of `{}!` is likely invalid in {} context",
J
Jeffrey Seyfried 已提交
1022
                               macro_path, kind_name);
1023 1024 1025
            err.span_note(span, &msg).emit();
        }
    }
1026 1027 1028 1029
}

struct InvocationCollector<'a, 'b: 'a> {
    cx: &'a mut ExtCtxt<'b>,
1030
    cfg: StripUnconfigured<'a>,
1031
    invocations: Vec<Invocation>,
1032
    monotonic: bool,
1033 1034 1035
}

impl<'a, 'b> InvocationCollector<'a, 'b> {
1036
    fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
J
Jeffrey Seyfried 已提交
1037
        let mark = Mark::fresh(self.cx.current_expansion.mark);
1038
        self.invocations.push(Invocation {
1039
            kind,
1040
            fragment_kind,
J
Jeffrey Seyfried 已提交
1041
            expansion_data: ExpansionData {
1042
                mark,
J
Jeffrey Seyfried 已提交
1043 1044 1045
                depth: self.cx.current_expansion.depth + 1,
                ..self.cx.current_expansion.clone()
            },
1046
        });
1047
        placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
1048
    }
1049

1050
    fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
1051
        self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
1052
    }
1053

1054 1055
    fn collect_attr(&mut self,
                    attr: Option<ast::Attribute>,
J
Jeffrey Seyfried 已提交
1056
                    traits: Vec<Path>,
1057
                    item: Annotatable,
1058 1059
                    kind: AstFragmentKind)
                    -> AstFragment {
1060
        self.collect(kind, InvocationKind::Attr { attr, traits, item })
1061 1062
    }

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

1069
        item = item.map_attrs(|mut attrs| {
1070 1071
            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
                                                                                     true) {
1072 1073 1074
                attr = Some(legacy_attr_invoc);
                return attrs;
            }
1075

1076 1077 1078 1079
            if self.cx.ecfg.proc_macro_enabled() {
                attr = find_attr_invoc(&mut attrs);
            }
            traits = collect_derives(&mut self.cx, &mut attrs);
1080 1081
            attrs
        });
1082

1083
        (attr, traits, item)
1084 1085
    }

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
    /// 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;
            }

            if self.cx.ecfg.proc_macro_enabled() {
                attr = find_attr_invoc(&mut attrs);
            }
            attrs
        });

        (attr, item)
    }

1108 1109 1110
    fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
        self.cfg.configure(node)
    }
1111 1112 1113 1114 1115 1116

    // 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 已提交
1117
            self.check_attribute_inner(attr, features);
1118 1119 1120 1121 1122 1123 1124

            // 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();
            }
1125 1126
        }
    }
1127 1128 1129

    fn check_attribute(&mut self, at: &ast::Attribute) {
        let features = self.cx.ecfg.features.unwrap();
S
Seiichi Uchida 已提交
1130 1131 1132 1133
        self.check_attribute_inner(at, features);
    }

    fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) {
1134 1135
        feature_gate::check_attribute(at, self.cx.parse_sess, features);
    }
1136 1137
}

1138
pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
1139 1140 1141
    attrs.iter()
         .position(|a| !attr::is_known(a) && !is_builtin_attr(a))
         .map(|i| attrs.remove(i))
1142 1143
}

1144
impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
1145
    fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
1146
        let mut expr = self.cfg.configure_expr(expr).into_inner();
1147 1148
        expr.node = self.cfg.configure_expr_kind(expr.node);

1149 1150
        // ignore derives so they remain unused
        let (attr, expr) = self.classify_nonitem(expr);
1151

1152
        if attr.is_some() {
1153 1154 1155 1156
            // 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));

1157 1158 1159
            // AstFragmentKind::Expr requires the macro to emit an expression
            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
                                     AstFragmentKind::Expr).make_expr();
1160 1161
        }

1162
        if let ast::ExprKind::Mac(mac) = expr.node {
1163
            self.check_attributes(&expr.attrs);
1164
            self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr()
1165 1166 1167
        } else {
            P(noop_fold_expr(expr, self))
        }
1168 1169
    }

1170
    fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
1171
        let mut expr = configure!(self, expr).into_inner();
1172 1173
        expr.node = self.cfg.configure_expr_kind(expr.node);

1174 1175
        // ignore derives so they remain unused
        let (attr, expr) = self.classify_nonitem(expr);
1176

1177
        if attr.is_some() {
1178 1179
            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));

1180
            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
1181
                                     AstFragmentKind::OptExpr)
1182 1183 1184
                .make_opt_expr();
        }

1185
        if let ast::ExprKind::Mac(mac) = expr.node {
1186
            self.check_attributes(&expr.attrs);
1187
            self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr()
1188 1189 1190
        } else {
            Some(P(noop_fold_expr(expr, self)))
        }
1191 1192
    }

1193
    fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
1194
        let pat = self.cfg.configure_pat(pat);
1195 1196
        match pat.node {
            PatKind::Mac(_) => {}
1197
            _ => return noop_fold_pat(pat, self),
1198
        }
K
Keegan McAllister 已提交
1199

1200
        pat.and_then(|pat| match pat.node {
1201
            PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
1202 1203
            _ => unreachable!(),
        })
1204 1205
    }

1206
    fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
1207
        let mut stmt = match self.cfg.configure_stmt(stmt) {
1208
            Some(stmt) => stmt,
1209
            None => return SmallVector::new(),
1210 1211
        };

1212 1213
        // we'll expand attributes on expressions separately
        if !stmt.is_expr() {
1214 1215 1216 1217 1218 1219 1220 1221
            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)
            };
1222 1223 1224

            if attr.is_some() || !derives.is_empty() {
                return self.collect_attr(attr, derives,
1225
                                         Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts)
1226 1227
                    .make_stmts();
            }
1228

1229 1230
            stmt = stmt_;
        }
1231

1232 1233 1234
        if let StmtKind::Mac(mac) = stmt.node {
            let (mac, style, attrs) = mac.into_inner();
            self.check_attributes(&attrs);
1235
            let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts)
1236 1237 1238 1239 1240 1241 1242 1243
                                        .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());
                }
1244
            }
1245 1246

            return placeholder;
1247 1248
        }

1249 1250 1251 1252 1253 1254
        // 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()

1255 1256
    }

S
Steven Fackler 已提交
1257
    fn fold_block(&mut self, block: P<Block>) -> P<Block> {
1258 1259
        let old_directory_ownership = self.cx.current_expansion.directory_ownership;
        self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
J
Jeffrey Seyfried 已提交
1260
        let result = noop_fold_block(block, self);
1261
        self.cx.current_expansion.directory_ownership = old_directory_ownership;
1262
        result
1263 1264
    }

1265
    fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
1266 1267
        let item = configure!(self, item);

1268 1269
        let (attr, traits, mut item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1270
            let item = Annotatable::Item(item);
1271
            return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
1272 1273 1274 1275
        }

        match item.node {
            ast::ItemKind::Mac(..) => {
1276
                self.check_attributes(&item.attrs);
1277
                item.and_then(|item| match item.node {
1278
                    ItemKind::Mac(mac) => {
1279
                        self.collect(AstFragmentKind::Items, InvocationKind::Bang {
1280
                            mac,
1281 1282
                            ident: Some(item.ident),
                            span: item.span,
1283
                        }).make_items()
1284 1285 1286 1287 1288
                    }
                    _ => unreachable!(),
                })
            }
            ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
1289 1290 1291 1292
                if item.ident == keywords::Invalid.ident() {
                    return noop_fold_item(item, self);
                }

1293
                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1294 1295
                let mut module = (*self.cx.current_expansion.module).clone();
                module.mod_path.push(item.ident);
1296 1297 1298 1299

                // 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.
J
Jeffrey Seyfried 已提交
1300
                let inline_module = item.span.contains(inner) || inner == DUMMY_SP;
1301 1302

                if inline_module {
1303
                    if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
1304 1305
                        self.cx.current_expansion.directory_ownership =
                            DirectoryOwnership::Owned { relative: None };
1306
                        module.directory.push(&*path.as_str());
1307
                    } else {
V
Vadim Petrochenkov 已提交
1308
                        module.directory.push(&*item.ident.as_str());
1309
                    }
1310
                } else {
1311 1312 1313 1314 1315
                    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()),
                    };
1316
                    let directory_ownership = match path.file_name().unwrap().to_str() {
1317 1318 1319 1320 1321
                        Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
                        Some(_) => DirectoryOwnership::Owned {
                            relative: Some(item.ident),
                        },
                        None => DirectoryOwnership::UnownedViaMod(false),
1322 1323 1324 1325
                    };
                    path.pop();
                    module.directory = path;
                    self.cx.current_expansion.directory_ownership = directory_ownership;
1326 1327
                }

1328 1329
                let orig_module =
                    mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
J
Jeffrey Seyfried 已提交
1330
                let result = noop_fold_item(item, self);
1331
                self.cx.current_expansion.module = orig_module;
1332
                self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1333
                result
1334
            }
1335 1336 1337
            // Ensure that test functions are accessible from the test harness.
            ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
                if item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
1338 1339 1340 1341
                    item = item.map(|mut item| {
                        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
                        item
                    });
1342 1343 1344
                }
                noop_fold_item(item, self)
            }
1345 1346
            _ => noop_fold_item(item, self),
        }
1347 1348
    }

1349
    fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
1350 1351
        let item = configure!(self, item);

1352 1353
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1354
            let item = Annotatable::TraitItem(P(item));
1355
            return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems)
1356
                .make_trait_items()
1357 1358 1359 1360 1361
        }

        match item.node {
            ast::TraitItemKind::Macro(mac) => {
                let ast::TraitItem { attrs, span, .. } = item;
1362
                self.check_attributes(&attrs);
1363
                self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
1364 1365 1366 1367 1368 1369
            }
            _ => fold::noop_fold_trait_item(item, self),
        }
    }

    fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem> {
1370 1371
        let item = configure!(self, item);

1372 1373
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1374
            let item = Annotatable::ImplItem(P(item));
1375
            return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems)
1376
                .make_impl_items();
1377 1378 1379 1380 1381
        }

        match item.node {
            ast::ImplItemKind::Macro(mac) => {
                let ast::ImplItem { attrs, span, .. } = item;
1382
                self.check_attributes(&attrs);
1383
                self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
1384
            }
1385
            _ => fold::noop_fold_impl_item(item, self),
1386
        }
1387 1388
    }

1389
    fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
1390
        let ty = match ty.node {
1391
            ast::TyKind::Mac(_) => ty.into_inner(),
1392 1393 1394 1395
            _ => return fold::noop_fold_ty(ty, self),
        };

        match ty.node {
1396
            ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
1397 1398
            _ => unreachable!(),
        }
1399
    }
1400 1401 1402 1403 1404

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

1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
    fn fold_foreign_item(&mut self,
                         foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
        let (attr, traits, foreign_item) = self.classify_item(foreign_item);

        let explain = if self.cx.ecfg.proc_macro_enabled() {
            feature_gate::EXPLAIN_PROC_MACROS_IN_EXTERN
        } else {
            feature_gate::EXPLAIN_MACROS_IN_EXTERN
        };

        if attr.is_some() || !traits.is_empty()  {
            if !self.cx.ecfg.macros_in_extern_enabled() {
                if let Some(ref attr) = attr {
                    emit_feature_err(&self.cx.parse_sess, "macros_in_extern", attr.span,
                                     GateIssue::Language, explain);
                }
            }

            let item = Annotatable::ForeignItem(P(foreign_item));
1424
            return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
                .make_foreign_items();
        }

        if let ast::ForeignItemKind::Macro(mac) = foreign_item.node {
            self.check_attributes(&foreign_item.attrs);

            if !self.cx.ecfg.macros_in_extern_enabled() {
                emit_feature_err(&self.cx.parse_sess, "macros_in_extern", foreign_item.span,
                                 GateIssue::Language, explain);
            }

1436
            return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
1437 1438 1439 1440 1441 1442
                .make_foreign_items();
        }

        noop_fold_foreign_item(foreign_item, self)
    }

1443
    fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
1444 1445 1446 1447
        match item {
            ast::ItemKind::MacroDef(..) => item,
            _ => noop_fold_item_kind(self.cfg.configure_item_kind(item), self),
        }
1448
    }
1449

1450 1451 1452 1453 1454
    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)
    }

1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
    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) => {
1489 1490 1491 1492
                            self.cx.span_err(at.span,
                                             &format!("couldn't read {}: {}",
                                                      filename.display(),
                                                      e));
1493 1494 1495 1496 1497
                        }
                    }

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

1500 1501
                            // Add this input file to the code map to make it available as
                            // dependency information
1502
                            self.cx.codemap().new_filemap(filename.into(), src);
1503

1504 1505
                            let include_info = vec![
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
1506 1507
                                        attr::mk_name_value_item_str(Ident::from_str("file"),
                                                                     dummy_spanned(file)))),
1508
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
1509
                                        attr::mk_name_value_item_str(Ident::from_str("contents"),
1510
                                                            dummy_spanned(src_interned)))),
1511 1512
                            ];

1513 1514 1515
                            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)));
1516 1517
                        }
                        Err(_) => {
1518 1519 1520
                            self.cx.span_err(at.span,
                                             &format!("{} wasn't a utf-8 file",
                                                      filename.display()));
1521 1522 1523 1524 1525 1526 1527
                        }
                    }
                } else {
                    items.push(noop_fold_meta_list_item(it, self));
                }
            }

1528
            let meta = attr::mk_list_item(DUMMY_SP, Ident::from_str("doc"), items);
1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
            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)
        }
    }

1540
    fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
1541 1542 1543 1544 1545 1546
        if self.monotonic {
            assert_eq!(id, ast::DUMMY_NODE_ID);
            self.cx.resolver.next_node_id()
        } else {
            id
        }
1547
    }
1548 1549
}

1550
pub struct ExpansionConfig<'feat> {
1551
    pub crate_name: String,
1552
    pub features: Option<&'feat Features>,
P
Paul Collier 已提交
1553
    pub recursion_limit: usize,
1554
    pub trace_mac: bool,
1555
    pub should_test: bool, // If false, strip `#[test]` nodes
1556 1557
    pub single_step: bool,
    pub keep_macs: bool,
1558 1559
}

1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572
macro_rules! feature_tests {
    ($( fn $getter:ident = $field:ident, )*) => {
        $(
            pub fn $getter(&self) -> bool {
                match self.features {
                    Some(&Features { $field: true, .. }) => true,
                    _ => false,
                }
            }
        )*
    }
}

1573 1574
impl<'feat> ExpansionConfig<'feat> {
    pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1575
        ExpansionConfig {
1576
            crate_name,
1577
            features: None,
1578
            recursion_limit: 1024,
1579
            trace_mac: false,
1580
            should_test: false,
1581 1582
            single_step: false,
            keep_macs: false,
1583 1584
        }
    }
1585

1586
    feature_tests! {
1587 1588
        fn enable_quotes = quote,
        fn enable_asm = asm,
1589
        fn enable_global_asm = global_asm,
1590 1591 1592
        fn enable_log_syntax = log_syntax,
        fn enable_concat_idents = concat_idents,
        fn enable_trace_macros = trace_macros,
1593
        fn enable_allow_internal_unstable = allow_internal_unstable,
1594
        fn enable_custom_derive = custom_derive,
1595
        fn proc_macro_enabled = proc_macro,
1596
        fn macros_in_extern_enabled = macros_in_extern,
1597
        fn proc_macro_mod = proc_macro_mod,
1598
        fn proc_macro_gen = proc_macro_gen,
1599 1600
        fn proc_macro_expr = proc_macro_expr,
        fn proc_macro_non_items = proc_macro_non_items,
1601
    }
1602 1603
}

1604
// A Marker adds the given mark to the syntax context.
1605
#[derive(Debug)]
1606
pub struct Marker(pub Mark);
1607

E
Eduard Burtescu 已提交
1608
impl Folder for Marker {
1609
    fn new_span(&mut self, span: Span) -> Span {
1610
        span.apply_mark(self.0)
1611
    }
1612 1613 1614 1615

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