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

11
use ast::{self, Block, Ident, NodeId, PatKind, Path};
J
Jeffrey Seyfried 已提交
12
use ast::{MacStmtStyle, StmtKind, ItemKind};
13
use attr::{self, HasAttrs};
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 545
            def_site: None,
            format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
            allow_internal_unstable: false,
            allow_internal_unsafe: false,
            edition: ext.edition(),
546 547
        });

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

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

646
        fragment.visit_with(&mut DisallowModules {
647 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
            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) {
                // ...
            }
        }
    }

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

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

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

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

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

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

783 784 785
                    let input: Vec<_> = mac.node.stream().into_trees().collect();
                    kind.make_from(expander.expand(self.cx, span, ident, input))
                }
786 787
            }

788
            MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
789
                self.cx.span_err(path.span,
J
Jeffrey Seyfried 已提交
790
                                 &format!("`{}` can only be used in attributes", path));
791
                self.cx.trace_macros_diag();
792
                kind.dummy(span)
793
            }
794

795
            ProcMacroDerive(..) | BuiltinDerive(..) => {
J
Jeffrey Seyfried 已提交
796
                self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
797
                self.cx.trace_macros_diag();
798
                kind.dummy(span)
799 800
            }

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

822
                    let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
823
                    let result = self.parse_ast_fragment(tok_result, kind, path, span);
824 825
                    self.gate_proc_macro_expansion(span, &result);
                    result
826
                }
827
            }
828 829
        };

830 831 832
        if opt_expanded.is_some() {
            opt_expanded
        } else {
833
            let msg = format!("non-{kind} macro in {kind} position: {name}",
834
                              name = path.segments[0].ident.name, kind = kind.name());
835
            self.cx.span_err(path.span, &msg);
836
            self.cx.trace_macros_diag();
837
            kind.dummy(span)
838
        }
839
    }
J
Jeffrey Seyfried 已提交
840

841
    fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
842
        let kind = match kind {
843 844 845 846 847 848 849 850 851
            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,
852 853 854 855 856 857 858 859 860 861 862 863 864
        };
        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),
        );
    }

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

J
Jeffrey Seyfried 已提交
878 879 880
        let pretty_name = Symbol::intern(&format!("derive({})", path));
        let span = path.span;
        let attr = ast::Attribute {
881 882
            path, span,
            tokens: TokenStream::empty(),
J
Jeffrey Seyfried 已提交
883 884 885
            // irrelevant:
            id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
        };
886

887
        let mut expn_info = ExpnInfo {
888
            call_site: span,
889 890 891 892 893
            def_site: None,
            format: MacroAttribute(pretty_name),
            allow_internal_unstable: false,
            allow_internal_unsafe: false,
            edition: ext.edition(),
894
        };
895 896

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

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

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

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

struct InvocationCollector<'a, 'b: 'a> {
    cx: &'a mut ExtCtxt<'b>,
1022
    cfg: StripUnconfigured<'a>,
1023
    invocations: Vec<Invocation>,
1024
    monotonic: bool,
1025 1026 1027
}

impl<'a, 'b> InvocationCollector<'a, 'b> {
1028
    fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
J
Jeffrey Seyfried 已提交
1029
        let mark = Mark::fresh(self.cx.current_expansion.mark);
1030
        self.invocations.push(Invocation {
1031
            kind,
1032
            fragment_kind,
J
Jeffrey Seyfried 已提交
1033
            expansion_data: ExpansionData {
1034
                mark,
J
Jeffrey Seyfried 已提交
1035 1036 1037
                depth: self.cx.current_expansion.depth + 1,
                ..self.cx.current_expansion.clone()
            },
1038
        });
1039
        placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
1040
    }
1041

1042
    fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
1043
        self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
1044
    }
1045

1046 1047
    fn collect_attr(&mut self,
                    attr: Option<ast::Attribute>,
J
Jeffrey Seyfried 已提交
1048
                    traits: Vec<Path>,
1049
                    item: Annotatable,
1050 1051
                    kind: AstFragmentKind)
                    -> AstFragment {
1052
        self.collect(kind, InvocationKind::Attr { attr, traits, item })
1053 1054
    }

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

1061
        item = item.map_attrs(|mut attrs| {
1062 1063
            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
                                                                                     true) {
1064 1065 1066
                attr = Some(legacy_attr_invoc);
                return attrs;
            }
1067

1068 1069 1070 1071
            if self.cx.ecfg.proc_macro_enabled() {
                attr = find_attr_invoc(&mut attrs);
            }
            traits = collect_derives(&mut self.cx, &mut attrs);
1072 1073
            attrs
        });
1074

1075
        (attr, traits, item)
1076 1077
    }

1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
    /// 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)
    }

1100 1101 1102
    fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
        self.cfg.configure(node)
    }
1103 1104 1105 1106 1107 1108

    // 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 已提交
1109
            self.check_attribute_inner(attr, features);
1110 1111 1112 1113 1114 1115 1116

            // 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();
            }
1117 1118
        }
    }
1119 1120 1121

    fn check_attribute(&mut self, at: &ast::Attribute) {
        let features = self.cx.ecfg.features.unwrap();
S
Seiichi Uchida 已提交
1122 1123 1124 1125
        self.check_attribute_inner(at, features);
    }

    fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) {
1126 1127
        feature_gate::check_attribute(at, self.cx.parse_sess, features);
    }
1128 1129
}

1130
pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
1131 1132 1133
    attrs.iter()
         .position(|a| !attr::is_known(a) && !is_builtin_attr(a))
         .map(|i| attrs.remove(i))
1134 1135
}

1136
impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
1137
    fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
1138
        let mut expr = self.cfg.configure_expr(expr).into_inner();
1139 1140
        expr.node = self.cfg.configure_expr_kind(expr.node);

1141 1142
        // ignore derives so they remain unused
        let (attr, expr) = self.classify_nonitem(expr);
1143

1144
        if attr.is_some() {
1145 1146 1147 1148
            // 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));

1149 1150 1151
            // AstFragmentKind::Expr requires the macro to emit an expression
            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
                                     AstFragmentKind::Expr).make_expr();
1152 1153
        }

1154
        if let ast::ExprKind::Mac(mac) = expr.node {
1155
            self.check_attributes(&expr.attrs);
1156
            self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr()
1157 1158 1159
        } else {
            P(noop_fold_expr(expr, self))
        }
1160 1161
    }

1162
    fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
1163
        let mut expr = configure!(self, expr).into_inner();
1164 1165
        expr.node = self.cfg.configure_expr_kind(expr.node);

1166 1167
        // ignore derives so they remain unused
        let (attr, expr) = self.classify_nonitem(expr);
1168

1169
        if attr.is_some() {
1170 1171
            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));

1172
            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
1173
                                     AstFragmentKind::OptExpr)
1174 1175 1176
                .make_opt_expr();
        }

1177
        if let ast::ExprKind::Mac(mac) = expr.node {
1178
            self.check_attributes(&expr.attrs);
1179
            self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr()
1180 1181 1182
        } else {
            Some(P(noop_fold_expr(expr, self)))
        }
1183 1184
    }

1185
    fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
1186
        let pat = self.cfg.configure_pat(pat);
1187 1188
        match pat.node {
            PatKind::Mac(_) => {}
1189
            _ => return noop_fold_pat(pat, self),
1190
        }
K
Keegan McAllister 已提交
1191

1192
        pat.and_then(|pat| match pat.node {
1193
            PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
1194 1195
            _ => unreachable!(),
        })
1196 1197
    }

1198
    fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
1199
        let mut stmt = match self.cfg.configure_stmt(stmt) {
1200
            Some(stmt) => stmt,
1201
            None => return SmallVector::new(),
1202 1203
        };

1204 1205
        // we'll expand attributes on expressions separately
        if !stmt.is_expr() {
1206 1207 1208 1209 1210 1211 1212 1213
            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)
            };
1214 1215 1216

            if attr.is_some() || !derives.is_empty() {
                return self.collect_attr(attr, derives,
1217
                                         Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts)
1218 1219
                    .make_stmts();
            }
1220

1221 1222
            stmt = stmt_;
        }
1223

1224 1225 1226
        if let StmtKind::Mac(mac) = stmt.node {
            let (mac, style, attrs) = mac.into_inner();
            self.check_attributes(&attrs);
1227
            let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts)
1228 1229 1230 1231 1232 1233 1234 1235
                                        .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());
                }
1236
            }
1237 1238

            return placeholder;
1239 1240
        }

1241 1242 1243 1244 1245 1246
        // 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()

1247 1248
    }

S
Steven Fackler 已提交
1249
    fn fold_block(&mut self, block: P<Block>) -> P<Block> {
1250 1251
        let old_directory_ownership = self.cx.current_expansion.directory_ownership;
        self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
J
Jeffrey Seyfried 已提交
1252
        let result = noop_fold_block(block, self);
1253
        self.cx.current_expansion.directory_ownership = old_directory_ownership;
1254
        result
1255 1256
    }

1257
    fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
1258 1259
        let item = configure!(self, item);

1260 1261
        let (attr, traits, mut item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1262
            let item = Annotatable::Item(item);
1263
            return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
1264 1265 1266 1267
        }

        match item.node {
            ast::ItemKind::Mac(..) => {
1268
                self.check_attributes(&item.attrs);
1269
                item.and_then(|item| match item.node {
1270
                    ItemKind::Mac(mac) => {
1271
                        self.collect(AstFragmentKind::Items, InvocationKind::Bang {
1272
                            mac,
1273 1274
                            ident: Some(item.ident),
                            span: item.span,
1275
                        }).make_items()
1276 1277 1278 1279 1280
                    }
                    _ => unreachable!(),
                })
            }
            ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
1281 1282 1283 1284
                if item.ident == keywords::Invalid.ident() {
                    return noop_fold_item(item, self);
                }

1285
                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1286 1287
                let mut module = (*self.cx.current_expansion.module).clone();
                module.mod_path.push(item.ident);
1288 1289 1290 1291

                // 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 已提交
1292
                let inline_module = item.span.contains(inner) || inner == DUMMY_SP;
1293 1294

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

1320 1321
                let orig_module =
                    mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
J
Jeffrey Seyfried 已提交
1322
                let result = noop_fold_item(item, self);
1323
                self.cx.current_expansion.module = orig_module;
1324
                self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1325
                result
1326
            }
1327 1328 1329
            // 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)) {
1330 1331 1332 1333
                    item = item.map(|mut item| {
                        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
                        item
                    });
1334 1335 1336
                }
                noop_fold_item(item, self)
            }
1337 1338
            _ => noop_fold_item(item, self),
        }
1339 1340
    }

1341
    fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
1342 1343
        let item = configure!(self, item);

1344 1345
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1346
            let item = Annotatable::TraitItem(P(item));
1347
            return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems)
1348
                .make_trait_items()
1349 1350 1351 1352 1353
        }

        match item.node {
            ast::TraitItemKind::Macro(mac) => {
                let ast::TraitItem { attrs, span, .. } = item;
1354
                self.check_attributes(&attrs);
1355
                self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
1356 1357 1358 1359 1360 1361
            }
            _ => fold::noop_fold_trait_item(item, self),
        }
    }

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

1364 1365
        let (attr, traits, item) = self.classify_item(item);
        if attr.is_some() || !traits.is_empty() {
1366
            let item = Annotatable::ImplItem(P(item));
1367
            return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems)
1368
                .make_impl_items();
1369 1370 1371 1372 1373
        }

        match item.node {
            ast::ImplItemKind::Macro(mac) => {
                let ast::ImplItem { attrs, span, .. } = item;
1374
                self.check_attributes(&attrs);
1375
                self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
1376
            }
1377
            _ => fold::noop_fold_impl_item(item, self),
1378
        }
1379 1380
    }

1381
    fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
1382
        let ty = match ty.node {
1383
            ast::TyKind::Mac(_) => ty.into_inner(),
1384 1385 1386 1387
            _ => return fold::noop_fold_ty(ty, self),
        };

        match ty.node {
1388
            ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
1389 1390
            _ => unreachable!(),
        }
1391
    }
1392 1393 1394 1395 1396

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

1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
    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));
1416
            return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
                .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);
            }

1428
            return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
1429 1430 1431 1432 1433 1434
                .make_foreign_items();
        }

        noop_fold_foreign_item(foreign_item, self)
    }

1435
    fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
1436 1437 1438 1439
        match item {
            ast::ItemKind::MacroDef(..) => item,
            _ => noop_fold_item_kind(self.cfg.configure_item_kind(item), self),
        }
1440
    }
1441

1442 1443 1444 1445 1446
    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)
    }

1447 1448 1449 1450 1451 1452 1453 1454 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
    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) => {
1481 1482 1483 1484
                            self.cx.span_err(at.span,
                                             &format!("couldn't read {}: {}",
                                                      filename.display(),
                                                      e));
1485 1486 1487 1488 1489
                        }
                    }

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

1492 1493
                            // Add this input file to the code map to make it available as
                            // dependency information
1494
                            self.cx.codemap().new_filemap(filename.into(), src);
1495

1496 1497
                            let include_info = vec![
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
1498 1499
                                        attr::mk_name_value_item_str(Ident::from_str("file"),
                                                                     dummy_spanned(file)))),
1500
                                dummy_spanned(ast::NestedMetaItemKind::MetaItem(
1501
                                        attr::mk_name_value_item_str(Ident::from_str("contents"),
1502
                                                            dummy_spanned(src_interned)))),
1503 1504
                            ];

1505 1506 1507
                            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)));
1508 1509
                        }
                        Err(_) => {
1510 1511 1512
                            self.cx.span_err(at.span,
                                             &format!("{} wasn't a utf-8 file",
                                                      filename.display()));
1513 1514 1515 1516 1517 1518 1519
                        }
                    }
                } else {
                    items.push(noop_fold_meta_list_item(it, self));
                }
            }

1520
            let meta = attr::mk_list_item(DUMMY_SP, Ident::from_str("doc"), items);
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
            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)
        }
    }

1532
    fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
1533 1534 1535 1536 1537 1538
        if self.monotonic {
            assert_eq!(id, ast::DUMMY_NODE_ID);
            self.cx.resolver.next_node_id()
        } else {
            id
        }
1539
    }
1540 1541
}

1542
pub struct ExpansionConfig<'feat> {
1543
    pub crate_name: String,
1544
    pub features: Option<&'feat Features>,
P
Paul Collier 已提交
1545
    pub recursion_limit: usize,
1546
    pub trace_mac: bool,
1547
    pub should_test: bool, // If false, strip `#[test]` nodes
1548 1549
    pub single_step: bool,
    pub keep_macs: bool,
1550 1551
}

1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
macro_rules! feature_tests {
    ($( fn $getter:ident = $field:ident, )*) => {
        $(
            pub fn $getter(&self) -> bool {
                match self.features {
                    Some(&Features { $field: true, .. }) => true,
                    _ => false,
                }
            }
        )*
    }
}

1565 1566
impl<'feat> ExpansionConfig<'feat> {
    pub fn default(crate_name: String) -> ExpansionConfig<'static> {
1567
        ExpansionConfig {
1568
            crate_name,
1569
            features: None,
1570
            recursion_limit: 1024,
1571
            trace_mac: false,
1572
            should_test: false,
1573 1574
            single_step: false,
            keep_macs: false,
1575 1576
        }
    }
1577

1578
    feature_tests! {
1579 1580
        fn enable_quotes = quote,
        fn enable_asm = asm,
1581
        fn enable_global_asm = global_asm,
1582 1583 1584
        fn enable_log_syntax = log_syntax,
        fn enable_concat_idents = concat_idents,
        fn enable_trace_macros = trace_macros,
1585
        fn enable_allow_internal_unstable = allow_internal_unstable,
1586
        fn enable_custom_derive = custom_derive,
1587
        fn proc_macro_enabled = proc_macro,
1588
        fn macros_in_extern_enabled = macros_in_extern,
1589
        fn proc_macro_mod = proc_macro_mod,
1590
        fn proc_macro_gen = proc_macro_gen,
1591 1592
        fn proc_macro_expr = proc_macro_expr,
        fn proc_macro_non_items = proc_macro_non_items,
1593
    }
1594 1595
}

1596
// A Marker adds the given mark to the syntax context.
1597
#[derive(Debug)]
1598
pub struct Marker(pub Mark);
1599

E
Eduard Burtescu 已提交
1600
impl Folder for Marker {
1601
    fn new_span(&mut self, span: Span) -> Span {
1602
        span.apply_mark(self.0)
1603
    }
1604 1605 1606 1607

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