]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/base.rs
Auto merge of #52712 - oli-obk:const_eval_cleanups, r=RalfJung
[rust.git] / src / libsyntax / ext / base.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 pub use self::SyntaxExtension::*;
12
13 use ast::{self, Attribute, Name, PatKind, MetaItem};
14 use attr::HasAttrs;
15 use codemap::{self, CodeMap, Spanned, respan};
16 use syntax_pos::{Span, MultiSpan, DUMMY_SP};
17 use edition::Edition;
18 use errors::{DiagnosticBuilder, DiagnosticId};
19 use ext::expand::{self, AstFragment, Invocation};
20 use ext::hygiene::{self, Mark, SyntaxContext, Transparency};
21 use fold::{self, Folder};
22 use parse::{self, parser, DirectoryOwnership};
23 use parse::token;
24 use ptr::P;
25 use symbol::{keywords, Ident, Symbol};
26 use util::small_vector::SmallVector;
27
28 use std::collections::HashMap;
29 use std::iter;
30 use std::path::PathBuf;
31 use std::rc::Rc;
32 use rustc_data_structures::sync::{self, Lrc};
33 use std::default::Default;
34 use tokenstream::{self, TokenStream};
35
36
37 #[derive(Debug,Clone)]
38 pub enum Annotatable {
39     Item(P<ast::Item>),
40     TraitItem(P<ast::TraitItem>),
41     ImplItem(P<ast::ImplItem>),
42     ForeignItem(P<ast::ForeignItem>),
43     Stmt(P<ast::Stmt>),
44     Expr(P<ast::Expr>),
45 }
46
47 impl HasAttrs for Annotatable {
48     fn attrs(&self) -> &[Attribute] {
49         match *self {
50             Annotatable::Item(ref item) => &item.attrs,
51             Annotatable::TraitItem(ref trait_item) => &trait_item.attrs,
52             Annotatable::ImplItem(ref impl_item) => &impl_item.attrs,
53             Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs,
54             Annotatable::Stmt(ref stmt) => stmt.attrs(),
55             Annotatable::Expr(ref expr) => &expr.attrs,
56         }
57     }
58
59     fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
60         match self {
61             Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)),
62             Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)),
63             Annotatable::ImplItem(impl_item) => Annotatable::ImplItem(impl_item.map_attrs(f)),
64             Annotatable::ForeignItem(foreign_item) =>
65                 Annotatable::ForeignItem(foreign_item.map_attrs(f)),
66             Annotatable::Stmt(stmt) => Annotatable::Stmt(stmt.map_attrs(f)),
67             Annotatable::Expr(expr) => Annotatable::Expr(expr.map_attrs(f)),
68         }
69     }
70 }
71
72 impl Annotatable {
73     pub fn span(&self) -> Span {
74         match *self {
75             Annotatable::Item(ref item) => item.span,
76             Annotatable::TraitItem(ref trait_item) => trait_item.span,
77             Annotatable::ImplItem(ref impl_item) => impl_item.span,
78             Annotatable::ForeignItem(ref foreign_item) => foreign_item.span,
79             Annotatable::Stmt(ref stmt) => stmt.span,
80             Annotatable::Expr(ref expr) => expr.span,
81         }
82     }
83
84     pub fn expect_item(self) -> P<ast::Item> {
85         match self {
86             Annotatable::Item(i) => i,
87             _ => panic!("expected Item")
88         }
89     }
90
91     pub fn map_item_or<F, G>(self, mut f: F, mut or: G) -> Annotatable
92         where F: FnMut(P<ast::Item>) -> P<ast::Item>,
93               G: FnMut(Annotatable) -> Annotatable
94     {
95         match self {
96             Annotatable::Item(i) => Annotatable::Item(f(i)),
97             _ => or(self)
98         }
99     }
100
101     pub fn expect_trait_item(self) -> ast::TraitItem {
102         match self {
103             Annotatable::TraitItem(i) => i.into_inner(),
104             _ => panic!("expected Item")
105         }
106     }
107
108     pub fn expect_impl_item(self) -> ast::ImplItem {
109         match self {
110             Annotatable::ImplItem(i) => i.into_inner(),
111             _ => panic!("expected Item")
112         }
113     }
114
115     pub fn expect_foreign_item(self) -> ast::ForeignItem {
116         match self {
117             Annotatable::ForeignItem(i) => i.into_inner(),
118             _ => panic!("expected foreign item")
119         }
120     }
121
122     pub fn expect_stmt(self) -> ast::Stmt {
123         match self {
124             Annotatable::Stmt(stmt) => stmt.into_inner(),
125             _ => panic!("expected statement"),
126         }
127     }
128
129     pub fn expect_expr(self) -> P<ast::Expr> {
130         match self {
131             Annotatable::Expr(expr) => expr,
132             _ => panic!("expected expression"),
133         }
134     }
135
136     pub fn derive_allowed(&self) -> bool {
137         match *self {
138             Annotatable::Item(ref item) => match item.node {
139                 ast::ItemKind::Struct(..) |
140                 ast::ItemKind::Enum(..) |
141                 ast::ItemKind::Union(..) => true,
142                 _ => false,
143             },
144             _ => false,
145         }
146     }
147 }
148
149 // A more flexible ItemDecorator.
150 pub trait MultiItemDecorator {
151     fn expand(&self,
152               ecx: &mut ExtCtxt,
153               sp: Span,
154               meta_item: &ast::MetaItem,
155               item: &Annotatable,
156               push: &mut dyn FnMut(Annotatable));
157 }
158
159 impl<F> MultiItemDecorator for F
160     where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, &mut dyn FnMut(Annotatable))
161 {
162     fn expand(&self,
163               ecx: &mut ExtCtxt,
164               sp: Span,
165               meta_item: &ast::MetaItem,
166               item: &Annotatable,
167               push: &mut dyn FnMut(Annotatable)) {
168         (*self)(ecx, sp, meta_item, item, push)
169     }
170 }
171
172 // `meta_item` is the annotation, and `item` is the item being modified.
173 // FIXME Decorators should follow the same pattern too.
174 pub trait MultiItemModifier {
175     fn expand(&self,
176               ecx: &mut ExtCtxt,
177               span: Span,
178               meta_item: &ast::MetaItem,
179               item: Annotatable)
180               -> Vec<Annotatable>;
181 }
182
183 impl<F, T> MultiItemModifier for F
184     where F: Fn(&mut ExtCtxt, Span, &ast::MetaItem, Annotatable) -> T,
185           T: Into<Vec<Annotatable>>,
186 {
187     fn expand(&self,
188               ecx: &mut ExtCtxt,
189               span: Span,
190               meta_item: &ast::MetaItem,
191               item: Annotatable)
192               -> Vec<Annotatable> {
193         (*self)(ecx, span, meta_item, item).into()
194     }
195 }
196
197 impl Into<Vec<Annotatable>> for Annotatable {
198     fn into(self) -> Vec<Annotatable> {
199         vec![self]
200     }
201 }
202
203 pub trait ProcMacro {
204     fn expand<'cx>(&self,
205                    ecx: &'cx mut ExtCtxt,
206                    span: Span,
207                    ts: TokenStream)
208                    -> TokenStream;
209 }
210
211 impl<F> ProcMacro for F
212     where F: Fn(TokenStream) -> TokenStream
213 {
214     fn expand<'cx>(&self,
215                    _ecx: &'cx mut ExtCtxt,
216                    _span: Span,
217                    ts: TokenStream)
218                    -> TokenStream {
219         // FIXME setup implicit context in TLS before calling self.
220         (*self)(ts)
221     }
222 }
223
224 pub trait AttrProcMacro {
225     fn expand<'cx>(&self,
226                    ecx: &'cx mut ExtCtxt,
227                    span: Span,
228                    annotation: TokenStream,
229                    annotated: TokenStream)
230                    -> TokenStream;
231 }
232
233 impl<F> AttrProcMacro for F
234     where F: Fn(TokenStream, TokenStream) -> TokenStream
235 {
236     fn expand<'cx>(&self,
237                    _ecx: &'cx mut ExtCtxt,
238                    _span: Span,
239                    annotation: TokenStream,
240                    annotated: TokenStream)
241                    -> TokenStream {
242         // FIXME setup implicit context in TLS before calling self.
243         (*self)(annotation, annotated)
244     }
245 }
246
247 /// Represents a thing that maps token trees to Macro Results
248 pub trait TTMacroExpander {
249     fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, input: TokenStream)
250                    -> Box<dyn MacResult+'cx>;
251 }
252
253 pub type MacroExpanderFn =
254     for<'cx> fn(&'cx mut ExtCtxt, Span, &[tokenstream::TokenTree])
255                 -> Box<dyn MacResult+'cx>;
256
257 impl<F> TTMacroExpander for F
258     where F: for<'cx> Fn(&'cx mut ExtCtxt, Span, &[tokenstream::TokenTree])
259     -> Box<dyn MacResult+'cx>
260 {
261     fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, input: TokenStream)
262                    -> Box<dyn MacResult+'cx> {
263         struct AvoidInterpolatedIdents;
264
265         impl Folder for AvoidInterpolatedIdents {
266             fn fold_tt(&mut self, tt: tokenstream::TokenTree) -> tokenstream::TokenTree {
267                 if let tokenstream::TokenTree::Token(_, token::Interpolated(ref nt)) = tt {
268                     if let token::NtIdent(ident, is_raw) = nt.0 {
269                         return tokenstream::TokenTree::Token(ident.span,
270                                                              token::Ident(ident, is_raw));
271                     }
272                 }
273                 fold::noop_fold_tt(tt, self)
274             }
275
276             fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
277                 fold::noop_fold_mac(mac, self)
278             }
279         }
280
281         let input: Vec<_> =
282             input.trees().map(|tt| AvoidInterpolatedIdents.fold_tt(tt)).collect();
283         (*self)(ecx, span, &input)
284     }
285 }
286
287 pub trait IdentMacroExpander {
288     fn expand<'cx>(&self,
289                    cx: &'cx mut ExtCtxt,
290                    sp: Span,
291                    ident: ast::Ident,
292                    token_tree: Vec<tokenstream::TokenTree>)
293                    -> Box<dyn MacResult+'cx>;
294 }
295
296 pub type IdentMacroExpanderFn =
297     for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec<tokenstream::TokenTree>)
298                 -> Box<dyn MacResult+'cx>;
299
300 impl<F> IdentMacroExpander for F
301     where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, ast::Ident,
302                           Vec<tokenstream::TokenTree>) -> Box<dyn MacResult+'cx>
303 {
304     fn expand<'cx>(&self,
305                    cx: &'cx mut ExtCtxt,
306                    sp: Span,
307                    ident: ast::Ident,
308                    token_tree: Vec<tokenstream::TokenTree>)
309                    -> Box<dyn MacResult+'cx>
310     {
311         (*self)(cx, sp, ident, token_tree)
312     }
313 }
314
315 // Use a macro because forwarding to a simple function has type system issues
316 macro_rules! make_stmts_default {
317     ($me:expr) => {
318         $me.make_expr().map(|e| SmallVector::one(ast::Stmt {
319             id: ast::DUMMY_NODE_ID,
320             span: e.span,
321             node: ast::StmtKind::Expr(e),
322         }))
323     }
324 }
325
326 /// The result of a macro expansion. The return values of the various
327 /// methods are spliced into the AST at the callsite of the macro.
328 pub trait MacResult {
329     /// Create an expression.
330     fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
331         None
332     }
333     /// Create zero or more items.
334     fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
335         None
336     }
337
338     /// Create zero or more impl items.
339     fn make_impl_items(self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
340         None
341     }
342
343     /// Create zero or more trait items.
344     fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
345         None
346     }
347
348     /// Create zero or more items in an `extern {}` block
349     fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> { None }
350
351     /// Create a pattern.
352     fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
353         None
354     }
355
356     /// Create zero or more statements.
357     ///
358     /// By default this attempts to create an expression statement,
359     /// returning None if that fails.
360     fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
361         make_stmts_default!(self)
362     }
363
364     fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
365         None
366     }
367 }
368
369 macro_rules! make_MacEager {
370     ( $( $fld:ident: $t:ty, )* ) => {
371         /// `MacResult` implementation for the common case where you've already
372         /// built each form of AST that you might return.
373         #[derive(Default)]
374         pub struct MacEager {
375             $(
376                 pub $fld: Option<$t>,
377             )*
378         }
379
380         impl MacEager {
381             $(
382                 pub fn $fld(v: $t) -> Box<dyn MacResult> {
383                     Box::new(MacEager {
384                         $fld: Some(v),
385                         ..Default::default()
386                     })
387                 }
388             )*
389         }
390     }
391 }
392
393 make_MacEager! {
394     expr: P<ast::Expr>,
395     pat: P<ast::Pat>,
396     items: SmallVector<P<ast::Item>>,
397     impl_items: SmallVector<ast::ImplItem>,
398     trait_items: SmallVector<ast::TraitItem>,
399     foreign_items: SmallVector<ast::ForeignItem>,
400     stmts: SmallVector<ast::Stmt>,
401     ty: P<ast::Ty>,
402 }
403
404 impl MacResult for MacEager {
405     fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
406         self.expr
407     }
408
409     fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
410         self.items
411     }
412
413     fn make_impl_items(self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
414         self.impl_items
415     }
416
417     fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
418         self.trait_items
419     }
420
421     fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
422         self.foreign_items
423     }
424
425     fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
426         match self.stmts.as_ref().map_or(0, |s| s.len()) {
427             0 => make_stmts_default!(self),
428             _ => self.stmts,
429         }
430     }
431
432     fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
433         if let Some(p) = self.pat {
434             return Some(p);
435         }
436         if let Some(e) = self.expr {
437             if let ast::ExprKind::Lit(_) = e.node {
438                 return Some(P(ast::Pat {
439                     id: ast::DUMMY_NODE_ID,
440                     span: e.span,
441                     node: PatKind::Lit(e),
442                 }));
443             }
444         }
445         None
446     }
447
448     fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
449         self.ty
450     }
451 }
452
453 /// Fill-in macro expansion result, to allow compilation to continue
454 /// after hitting errors.
455 #[derive(Copy, Clone)]
456 pub struct DummyResult {
457     expr_only: bool,
458     span: Span
459 }
460
461 impl DummyResult {
462     /// Create a default MacResult that can be anything.
463     ///
464     /// Use this as a return value after hitting any errors and
465     /// calling `span_err`.
466     pub fn any(sp: Span) -> Box<dyn MacResult+'static> {
467         Box::new(DummyResult { expr_only: false, span: sp })
468     }
469
470     /// Create a default MacResult that can only be an expression.
471     ///
472     /// Use this for macros that must expand to an expression, so even
473     /// if an error is encountered internally, the user will receive
474     /// an error that they also used it in the wrong place.
475     pub fn expr(sp: Span) -> Box<dyn MacResult+'static> {
476         Box::new(DummyResult { expr_only: true, span: sp })
477     }
478
479     /// A plain dummy expression.
480     pub fn raw_expr(sp: Span) -> P<ast::Expr> {
481         P(ast::Expr {
482             id: ast::DUMMY_NODE_ID,
483             node: ast::ExprKind::Lit(P(codemap::respan(sp, ast::LitKind::Bool(false)))),
484             span: sp,
485             attrs: ast::ThinVec::new(),
486         })
487     }
488
489     /// A plain dummy pattern.
490     pub fn raw_pat(sp: Span) -> ast::Pat {
491         ast::Pat {
492             id: ast::DUMMY_NODE_ID,
493             node: PatKind::Wild,
494             span: sp,
495         }
496     }
497
498     pub fn raw_ty(sp: Span) -> P<ast::Ty> {
499         P(ast::Ty {
500             id: ast::DUMMY_NODE_ID,
501             node: ast::TyKind::Infer,
502             span: sp
503         })
504     }
505 }
506
507 impl MacResult for DummyResult {
508     fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> {
509         Some(DummyResult::raw_expr(self.span))
510     }
511
512     fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
513         Some(P(DummyResult::raw_pat(self.span)))
514     }
515
516     fn make_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Item>>> {
517         // this code needs a comment... why not always just return the Some() ?
518         if self.expr_only {
519             None
520         } else {
521             Some(SmallVector::new())
522         }
523     }
524
525     fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVector<ast::ImplItem>> {
526         if self.expr_only {
527             None
528         } else {
529             Some(SmallVector::new())
530         }
531     }
532
533     fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVector<ast::TraitItem>> {
534         if self.expr_only {
535             None
536         } else {
537             Some(SmallVector::new())
538         }
539     }
540
541     fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
542         if self.expr_only {
543             None
544         } else {
545             Some(SmallVector::new())
546         }
547     }
548
549     fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
550         Some(SmallVector::one(ast::Stmt {
551             id: ast::DUMMY_NODE_ID,
552             node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)),
553             span: self.span,
554         }))
555     }
556
557     fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
558         Some(DummyResult::raw_ty(self.span))
559     }
560 }
561
562 pub type BuiltinDeriveFn =
563     for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable));
564
565 /// Represents different kinds of macro invocations that can be resolved.
566 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
567 pub enum MacroKind {
568     /// A bang macro - foo!()
569     Bang,
570     /// An attribute macro - #[foo]
571     Attr,
572     /// A derive attribute macro - #[derive(Foo)]
573     Derive,
574     /// A view of a procedural macro from the same crate that defines it.
575     ProcMacroStub,
576 }
577
578 impl MacroKind {
579     pub fn descr(self) -> &'static str {
580         match self {
581             MacroKind::Bang => "macro",
582             MacroKind::Attr => "attribute macro",
583             MacroKind::Derive => "derive macro",
584             MacroKind::ProcMacroStub => "crate-local procedural macro",
585         }
586     }
587 }
588
589 /// An enum representing the different kinds of syntax extensions.
590 pub enum SyntaxExtension {
591     /// A trivial "extension" that does nothing, only keeps the attribute and marks it as known.
592     NonMacroAttr,
593
594     /// A syntax extension that is attached to an item and creates new items
595     /// based upon it.
596     ///
597     /// `#[derive(...)]` is a `MultiItemDecorator`.
598     ///
599     /// Prefer ProcMacro or MultiModifier since they are more flexible.
600     MultiDecorator(Box<dyn MultiItemDecorator + sync::Sync + sync::Send>),
601
602     /// A syntax extension that is attached to an item and modifies it
603     /// in-place. Also allows decoration, i.e., creating new items.
604     MultiModifier(Box<dyn MultiItemModifier + sync::Sync + sync::Send>),
605
606     /// A function-like procedural macro. TokenStream -> TokenStream.
607     ProcMacro {
608         expander: Box<dyn ProcMacro + sync::Sync + sync::Send>,
609         allow_internal_unstable: bool,
610         edition: Edition,
611     },
612
613     /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
614     /// The first TokenSteam is the attribute, the second is the annotated item.
615     /// Allows modification of the input items and adding new items, similar to
616     /// MultiModifier, but uses TokenStreams, rather than AST nodes.
617     AttrProcMacro(Box<dyn AttrProcMacro + sync::Sync + sync::Send>, Edition),
618
619     /// A normal, function-like syntax extension.
620     ///
621     /// `bytes!` is a `NormalTT`.
622     NormalTT {
623         expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
624         def_info: Option<(ast::NodeId, Span)>,
625         /// Whether the contents of the macro can
626         /// directly use `#[unstable]` things (true == yes).
627         allow_internal_unstable: bool,
628         /// Whether the contents of the macro can use `unsafe`
629         /// without triggering the `unsafe_code` lint.
630         allow_internal_unsafe: bool,
631         /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
632         /// for a given macro.
633         local_inner_macros: bool,
634         /// The macro's feature name if it is unstable, and the stability feature
635         unstable_feature: Option<(Symbol, u32)>,
636         /// Edition of the crate in which the macro is defined
637         edition: Edition,
638     },
639
640     /// A function-like syntax extension that has an extra ident before
641     /// the block.
642     ///
643     IdentTT(Box<dyn IdentMacroExpander + sync::Sync + sync::Send>, Option<Span>, bool),
644
645     /// An attribute-like procedural macro. TokenStream -> TokenStream.
646     /// The input is the annotated item.
647     /// Allows generating code to implement a Trait for a given struct
648     /// or enum item.
649     ProcMacroDerive(Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
650                     Vec<Symbol> /* inert attribute names */, Edition),
651
652     /// An attribute-like procedural macro that derives a builtin trait.
653     BuiltinDerive(BuiltinDeriveFn),
654
655     /// A declarative macro, e.g. `macro m() {}`.
656     DeclMacro {
657         expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
658         def_info: Option<(ast::NodeId, Span)>,
659         is_transparent: bool,
660         edition: Edition,
661     }
662 }
663
664 impl SyntaxExtension {
665     /// Return which kind of macro calls this syntax extension.
666     pub fn kind(&self) -> MacroKind {
667         match *self {
668             SyntaxExtension::DeclMacro { .. } |
669             SyntaxExtension::NormalTT { .. } |
670             SyntaxExtension::IdentTT(..) |
671             SyntaxExtension::ProcMacro { .. } =>
672                 MacroKind::Bang,
673             SyntaxExtension::NonMacroAttr |
674             SyntaxExtension::MultiDecorator(..) |
675             SyntaxExtension::MultiModifier(..) |
676             SyntaxExtension::AttrProcMacro(..) =>
677                 MacroKind::Attr,
678             SyntaxExtension::ProcMacroDerive(..) |
679             SyntaxExtension::BuiltinDerive(..) =>
680                 MacroKind::Derive,
681         }
682     }
683
684     pub fn default_transparency(&self) -> Transparency {
685         match *self {
686             SyntaxExtension::ProcMacro { .. } |
687             SyntaxExtension::AttrProcMacro(..) |
688             SyntaxExtension::ProcMacroDerive(..) |
689             SyntaxExtension::DeclMacro { is_transparent: false, .. } => Transparency::Opaque,
690             SyntaxExtension::DeclMacro { is_transparent: true, .. } => Transparency::Transparent,
691             _ => Transparency::SemiTransparent,
692         }
693     }
694
695     pub fn edition(&self) -> Edition {
696         match *self {
697             SyntaxExtension::NormalTT { edition, .. } |
698             SyntaxExtension::DeclMacro { edition, .. } |
699             SyntaxExtension::ProcMacro { edition, .. } |
700             SyntaxExtension::AttrProcMacro(.., edition) |
701             SyntaxExtension::ProcMacroDerive(.., edition) => edition,
702             // Unstable legacy stuff
703             SyntaxExtension::NonMacroAttr |
704             SyntaxExtension::IdentTT(..) |
705             SyntaxExtension::MultiDecorator(..) |
706             SyntaxExtension::MultiModifier(..) |
707             SyntaxExtension::BuiltinDerive(..) => hygiene::default_edition(),
708         }
709     }
710 }
711
712 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
713
714 pub trait Resolver {
715     fn next_node_id(&mut self) -> ast::NodeId;
716     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
717     fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
718     fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
719
720     fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
721                                             derives: &[Mark]);
722     fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
723
724     fn resolve_imports(&mut self);
725     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
726     fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>, allow_derive: bool)
727                               -> Option<Attribute>;
728
729     fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
730                      -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
731     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
732                      -> Result<Lrc<SyntaxExtension>, Determinacy>;
733     fn check_unused_macros(&self);
734 }
735
736 #[derive(Copy, Clone, PartialEq, Debug)]
737 pub enum Determinacy {
738     Determined,
739     Undetermined,
740 }
741
742 pub struct DummyResolver;
743
744 impl Resolver for DummyResolver {
745     fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
746     fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
747     fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
748     fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
749
750     fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
751                                             _derives: &[Mark]) {}
752     fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
753
754     fn resolve_imports(&mut self) {}
755     fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool)
756                               -> Option<Attribute> { None }
757     fn resolve_invoc(&mut self, _invoc: &mut Invocation, _scope: Mark, _force: bool)
758                      -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
759         Err(Determinacy::Determined)
760     }
761     fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind,
762                      _force: bool) -> Result<Lrc<SyntaxExtension>, Determinacy> {
763         Err(Determinacy::Determined)
764     }
765     fn check_unused_macros(&self) {}
766 }
767
768 #[derive(Clone)]
769 pub struct ModuleData {
770     pub mod_path: Vec<ast::Ident>,
771     pub directory: PathBuf,
772 }
773
774 #[derive(Clone)]
775 pub struct ExpansionData {
776     pub mark: Mark,
777     pub depth: usize,
778     pub module: Rc<ModuleData>,
779     pub directory_ownership: DirectoryOwnership,
780     pub crate_span: Option<Span>,
781 }
782
783 /// One of these is made during expansion and incrementally updated as we go;
784 /// when a macro expansion occurs, the resulting nodes have the `backtrace()
785 /// -> expn_info` of their expansion context stored into their span.
786 pub struct ExtCtxt<'a> {
787     pub parse_sess: &'a parse::ParseSess,
788     pub ecfg: expand::ExpansionConfig<'a>,
789     pub root_path: PathBuf,
790     pub resolver: &'a mut dyn Resolver,
791     pub resolve_err_count: usize,
792     pub current_expansion: ExpansionData,
793     pub expansions: HashMap<Span, Vec<String>>,
794 }
795
796 impl<'a> ExtCtxt<'a> {
797     pub fn new(parse_sess: &'a parse::ParseSess,
798                ecfg: expand::ExpansionConfig<'a>,
799                resolver: &'a mut dyn Resolver)
800                -> ExtCtxt<'a> {
801         ExtCtxt {
802             parse_sess,
803             ecfg,
804             root_path: PathBuf::new(),
805             resolver,
806             resolve_err_count: 0,
807             current_expansion: ExpansionData {
808                 mark: Mark::root(),
809                 depth: 0,
810                 module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
811                 directory_ownership: DirectoryOwnership::Owned { relative: None },
812                 crate_span: None,
813             },
814             expansions: HashMap::new(),
815         }
816     }
817
818     /// Returns a `Folder` for deeply expanding all macros in an AST node.
819     pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
820         expand::MacroExpander::new(self, false)
821     }
822
823     /// Returns a `Folder` that deeply expands all macros and assigns all node ids in an AST node.
824     /// Once node ids are assigned, the node may not be expanded, removed, or otherwise modified.
825     pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
826         expand::MacroExpander::new(self, true)
827     }
828
829     pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> {
830         parse::stream_to_parser(self.parse_sess, tts.iter().cloned().collect())
831     }
832     pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() }
833     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
834     pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config }
835     pub fn call_site(&self) -> Span {
836         match self.current_expansion.mark.expn_info() {
837             Some(expn_info) => expn_info.call_site,
838             None => DUMMY_SP,
839         }
840     }
841     pub fn backtrace(&self) -> SyntaxContext {
842         SyntaxContext::empty().apply_mark(self.current_expansion.mark)
843     }
844
845     /// Returns span for the macro which originally caused the current expansion to happen.
846     ///
847     /// Stops backtracing at include! boundary.
848     pub fn expansion_cause(&self) -> Option<Span> {
849         let mut ctxt = self.backtrace();
850         let mut last_macro = None;
851         loop {
852             if ctxt.outer().expn_info().map_or(None, |info| {
853                 if info.format.name() == "include" {
854                     // Stop going up the backtrace once include! is encountered
855                     return None;
856                 }
857                 ctxt = info.call_site.ctxt();
858                 last_macro = Some(info.call_site);
859                 Some(())
860             }).is_none() {
861                 break
862             }
863         }
864         last_macro
865     }
866
867     pub fn struct_span_warn<S: Into<MultiSpan>>(&self,
868                                                 sp: S,
869                                                 msg: &str)
870                                                 -> DiagnosticBuilder<'a> {
871         self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
872     }
873     pub fn struct_span_err<S: Into<MultiSpan>>(&self,
874                                                sp: S,
875                                                msg: &str)
876                                                -> DiagnosticBuilder<'a> {
877         self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
878     }
879     pub fn struct_span_fatal<S: Into<MultiSpan>>(&self,
880                                                  sp: S,
881                                                  msg: &str)
882                                                  -> DiagnosticBuilder<'a> {
883         self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg)
884     }
885
886     /// Emit `msg` attached to `sp`, and stop compilation immediately.
887     ///
888     /// `span_err` should be strongly preferred where-ever possible:
889     /// this should *only* be used when:
890     ///
891     /// - continuing has a high risk of flow-on errors (e.g. errors in
892     ///   declaring a macro would cause all uses of that macro to
893     ///   complain about "undefined macro"), or
894     /// - there is literally nothing else that can be done (however,
895     ///   in most cases one can construct a dummy expression/item to
896     ///   substitute; we never hit resolve/type-checking so the dummy
897     ///   value doesn't have to match anything)
898     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
899         self.parse_sess.span_diagnostic.span_fatal(sp, msg).raise();
900     }
901
902     /// Emit `msg` attached to `sp`, without immediately stopping
903     /// compilation.
904     ///
905     /// Compilation will be stopped in the near future (at the end of
906     /// the macro expansion phase).
907     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
908         self.parse_sess.span_diagnostic.span_err(sp, msg);
909     }
910     pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
911         self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code);
912     }
913     pub fn mut_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str)
914                         -> DiagnosticBuilder<'a> {
915         self.parse_sess.span_diagnostic.mut_span_err(sp, msg)
916     }
917     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
918         self.parse_sess.span_diagnostic.span_warn(sp, msg);
919     }
920     pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
921         self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
922     }
923     pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
924         self.parse_sess.span_diagnostic.span_bug(sp, msg);
925     }
926     pub fn trace_macros_diag(&mut self) {
927         for (sp, notes) in self.expansions.iter() {
928             let mut db = self.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro");
929             for note in notes {
930                 db.note(note);
931             }
932             db.emit();
933         }
934         // Fixme: does this result in errors?
935         self.expansions.clear();
936     }
937     pub fn bug(&self, msg: &str) -> ! {
938         self.parse_sess.span_diagnostic.bug(msg);
939     }
940     pub fn trace_macros(&self) -> bool {
941         self.ecfg.trace_mac
942     }
943     pub fn set_trace_macros(&mut self, x: bool) {
944         self.ecfg.trace_mac = x
945     }
946     pub fn ident_of(&self, st: &str) -> ast::Ident {
947         ast::Ident::from_str(st)
948     }
949     pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
950         let def_site = DUMMY_SP.apply_mark(self.current_expansion.mark);
951         iter::once(Ident::new(keywords::DollarCrate.name(), def_site))
952             .chain(components.iter().map(|s| self.ident_of(s)))
953             .collect()
954     }
955     pub fn name_of(&self, st: &str) -> ast::Name {
956         Symbol::intern(st)
957     }
958
959     pub fn check_unused_macros(&self) {
960         self.resolver.check_unused_macros();
961     }
962 }
963
964 /// Extract a string literal from the macro expanded version of `expr`,
965 /// emitting `err_msg` if `expr` is not a string literal. This does not stop
966 /// compilation on error, merely emits a non-fatal error and returns None.
967 pub fn expr_to_spanned_string<'a>(
968     cx: &'a mut ExtCtxt,
969     expr: P<ast::Expr>,
970     err_msg: &str,
971 ) -> Result<Spanned<(Symbol, ast::StrStyle)>, DiagnosticBuilder<'a>> {
972     // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
973     let expr = expr.map(|mut expr| {
974         expr.span = expr.span.apply_mark(cx.current_expansion.mark);
975         expr
976     });
977
978     // we want to be able to handle e.g. `concat!("foo", "bar")`
979     let expr = cx.expander().fold_expr(expr);
980     Err(match expr.node {
981         ast::ExprKind::Lit(ref l) => match l.node {
982             ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))),
983             _ => cx.struct_span_err(l.span, err_msg)
984         },
985         _ => cx.struct_span_err(expr.span, err_msg)
986     })
987 }
988
989 pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
990                       -> Option<(Symbol, ast::StrStyle)> {
991     expr_to_spanned_string(cx, expr, err_msg)
992         .map_err(|mut err| err.emit())
993         .ok()
994         .map(|s| s.node)
995 }
996
997 /// Non-fatally assert that `tts` is empty. Note that this function
998 /// returns even when `tts` is non-empty, macros that *need* to stop
999 /// compilation should call
1000 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
1001 /// done as rarely as possible).
1002 pub fn check_zero_tts(cx: &ExtCtxt,
1003                       sp: Span,
1004                       tts: &[tokenstream::TokenTree],
1005                       name: &str) {
1006     if !tts.is_empty() {
1007         cx.span_err(sp, &format!("{} takes no arguments", name));
1008     }
1009 }
1010
1011 /// Interpreting `tts` as a comma-separated sequence of expressions,
1012 /// expect exactly one string literal, or emit an error and return None.
1013 pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
1014                                sp: Span,
1015                                tts: &[tokenstream::TokenTree],
1016                                name: &str)
1017                                -> Option<String> {
1018     let mut p = cx.new_parser_from_tts(tts);
1019     if p.token == token::Eof {
1020         cx.span_err(sp, &format!("{} takes 1 argument", name));
1021         return None
1022     }
1023     let ret = panictry!(p.parse_expr());
1024     let _ = p.eat(&token::Comma);
1025
1026     if p.token != token::Eof {
1027         cx.span_err(sp, &format!("{} takes 1 argument", name));
1028     }
1029     expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| {
1030         s.to_string()
1031     })
1032 }
1033
1034 /// Extract comma-separated expressions from `tts`. If there is a
1035 /// parsing error, emit a non-fatal error and return None.
1036 pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
1037                           sp: Span,
1038                           tts: &[tokenstream::TokenTree]) -> Option<Vec<P<ast::Expr>>> {
1039     let mut p = cx.new_parser_from_tts(tts);
1040     let mut es = Vec::new();
1041     while p.token != token::Eof {
1042         es.push(cx.expander().fold_expr(panictry!(p.parse_expr())));
1043         if p.eat(&token::Comma) {
1044             continue;
1045         }
1046         if p.token != token::Eof {
1047             cx.span_err(sp, "expected token: `,`");
1048             return None;
1049         }
1050     }
1051     Some(es)
1052 }