2015-02-24 19:56:01 +01:00
|
|
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08:00
|
|
|
// 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.
|
|
|
|
|
2016-09-06 17:57:58 +12:00
|
|
|
pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT};
|
2014-11-06 00:05:53 -08:00
|
|
|
|
2017-01-24 01:31:49 +10:30
|
|
|
use ast::{self, Attribute, Name, PatKind, MetaItem};
|
2016-06-12 12:45:16 +00:00
|
|
|
use attr::HasAttrs;
|
2017-03-17 04:04:41 +00:00
|
|
|
use codemap::{self, CodeMap, Spanned, respan};
|
|
|
|
use syntax_pos::{Span, DUMMY_SP};
|
|
|
|
use errors::DiagnosticBuilder;
|
2017-03-01 08:44:05 +00:00
|
|
|
use ext::expand::{self, Expansion, Invocation};
|
2017-03-17 04:04:41 +00:00
|
|
|
use ext::hygiene::{Mark, SyntaxContext};
|
2016-09-21 06:25:09 +00:00
|
|
|
use fold::{self, Folder};
|
2016-11-05 04:16:26 +00:00
|
|
|
use parse::{self, parser, DirectoryOwnership};
|
2013-03-26 16:38:07 -04:00
|
|
|
use parse::token;
|
2014-09-13 19:06:01 +03:00
|
|
|
use ptr::P;
|
2016-11-16 10:52:37 +00:00
|
|
|
use symbol::Symbol;
|
2013-11-24 23:08:53 -08:00
|
|
|
use util::small_vector::SmallVector;
|
2012-12-23 17:41:37 -05:00
|
|
|
|
2017-05-05 21:49:59 -07:00
|
|
|
use std::collections::HashMap;
|
2016-08-31 09:02:45 +00:00
|
|
|
use std::path::PathBuf;
|
2014-07-19 21:34:24 +02:00
|
|
|
use std::rc::Rc;
|
2016-08-29 16:16:43 +12:00
|
|
|
use std::default::Default;
|
|
|
|
use tokenstream::{self, TokenStream};
|
2011-06-04 15:41:45 -04:00
|
|
|
|
2014-02-27 23:49:25 -08:00
|
|
|
|
2015-01-28 08:34:18 -05:00
|
|
|
#[derive(Debug,Clone)]
|
2014-12-02 10:07:41 -08:00
|
|
|
pub enum Annotatable {
|
|
|
|
Item(P<ast::Item>),
|
2015-03-10 12:28:44 +02:00
|
|
|
TraitItem(P<ast::TraitItem>),
|
|
|
|
ImplItem(P<ast::ImplItem>),
|
2014-12-02 10:07:41 -08:00
|
|
|
}
|
|
|
|
|
2016-06-12 12:45:16 +00:00
|
|
|
impl HasAttrs for Annotatable {
|
2016-09-07 23:21:59 +00:00
|
|
|
fn attrs(&self) -> &[Attribute] {
|
2014-12-02 10:07:41 -08:00
|
|
|
match *self {
|
2016-06-12 12:45:16 +00:00
|
|
|
Annotatable::Item(ref item) => &item.attrs,
|
|
|
|
Annotatable::TraitItem(ref trait_item) => &trait_item.attrs,
|
|
|
|
Annotatable::ImplItem(ref impl_item) => &impl_item.attrs,
|
2014-12-02 10:07:41 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-07 23:21:59 +00:00
|
|
|
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
|
2014-12-02 10:07:41 -08:00
|
|
|
match self {
|
2016-06-12 12:45:16 +00:00
|
|
|
Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)),
|
|
|
|
Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)),
|
|
|
|
Annotatable::ImplItem(impl_item) => Annotatable::ImplItem(impl_item.map_attrs(f)),
|
2014-12-02 10:07:41 -08:00
|
|
|
}
|
|
|
|
}
|
2016-06-12 12:45:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Annotatable {
|
2017-03-17 04:04:41 +00:00
|
|
|
pub fn span(&self) -> Span {
|
|
|
|
match *self {
|
|
|
|
Annotatable::Item(ref item) => item.span,
|
|
|
|
Annotatable::TraitItem(ref trait_item) => trait_item.span,
|
|
|
|
Annotatable::ImplItem(ref impl_item) => impl_item.span,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-02 10:07:41 -08:00
|
|
|
pub fn expect_item(self) -> P<ast::Item> {
|
|
|
|
match self {
|
|
|
|
Annotatable::Item(i) => i,
|
|
|
|
_ => panic!("expected Item")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-28 17:34:39 +12:00
|
|
|
pub fn map_item_or<F, G>(self, mut f: F, mut or: G) -> Annotatable
|
|
|
|
where F: FnMut(P<ast::Item>) -> P<ast::Item>,
|
|
|
|
G: FnMut(Annotatable) -> Annotatable
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
Annotatable::Item(i) => Annotatable::Item(f(i)),
|
|
|
|
_ => or(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:33:09 +03:00
|
|
|
pub fn expect_trait_item(self) -> ast::TraitItem {
|
2014-12-02 10:07:41 -08:00
|
|
|
match self {
|
2016-02-11 23:33:09 +03:00
|
|
|
Annotatable::TraitItem(i) => i.unwrap(),
|
2014-12-02 10:07:41 -08:00
|
|
|
_ => panic!("expected Item")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:33:09 +03:00
|
|
|
pub fn expect_impl_item(self) -> ast::ImplItem {
|
2014-12-02 10:07:41 -08:00
|
|
|
match self {
|
2016-02-11 23:33:09 +03:00
|
|
|
Annotatable::ImplItem(i) => i.unwrap(),
|
2014-12-02 10:07:41 -08:00
|
|
|
_ => panic!("expected Item")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-16 22:59:41 +01:00
|
|
|
// A more flexible ItemDecorator.
|
|
|
|
pub trait MultiItemDecorator {
|
|
|
|
fn expand(&self,
|
|
|
|
ecx: &mut ExtCtxt,
|
|
|
|
sp: Span,
|
|
|
|
meta_item: &ast::MetaItem,
|
2015-05-22 21:10:14 +05:30
|
|
|
item: &Annotatable,
|
2015-04-28 17:34:39 +12:00
|
|
|
push: &mut FnMut(Annotatable));
|
2015-01-16 22:59:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> MultiItemDecorator for F
|
2015-05-22 21:10:14 +05:30
|
|
|
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, &mut FnMut(Annotatable))
|
2015-01-16 22:59:41 +01:00
|
|
|
{
|
|
|
|
fn expand(&self,
|
|
|
|
ecx: &mut ExtCtxt,
|
|
|
|
sp: Span,
|
|
|
|
meta_item: &ast::MetaItem,
|
2015-05-22 21:10:14 +05:30
|
|
|
item: &Annotatable,
|
2015-04-25 15:31:11 +12:00
|
|
|
push: &mut FnMut(Annotatable)) {
|
2015-01-16 22:59:41 +01:00
|
|
|
(*self)(ecx, sp, meta_item, item, push)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-12 16:05:19 +00:00
|
|
|
// `meta_item` is the annotation, and `item` is the item being modified.
|
2014-12-02 10:07:41 -08:00
|
|
|
// FIXME Decorators should follow the same pattern too.
|
|
|
|
pub trait MultiItemModifier {
|
|
|
|
fn expand(&self,
|
|
|
|
ecx: &mut ExtCtxt,
|
|
|
|
span: Span,
|
|
|
|
meta_item: &ast::MetaItem,
|
|
|
|
item: Annotatable)
|
2016-06-12 16:05:19 +00:00
|
|
|
-> Vec<Annotatable>;
|
2014-12-02 10:07:41 -08:00
|
|
|
}
|
|
|
|
|
2016-06-12 16:05:19 +00:00
|
|
|
impl<F, T> MultiItemModifier for F
|
|
|
|
where F: Fn(&mut ExtCtxt, Span, &ast::MetaItem, Annotatable) -> T,
|
|
|
|
T: Into<Vec<Annotatable>>,
|
2014-12-02 10:07:41 -08:00
|
|
|
{
|
|
|
|
fn expand(&self,
|
|
|
|
ecx: &mut ExtCtxt,
|
|
|
|
span: Span,
|
|
|
|
meta_item: &ast::MetaItem,
|
|
|
|
item: Annotatable)
|
2016-06-12 16:05:19 +00:00
|
|
|
-> Vec<Annotatable> {
|
|
|
|
(*self)(ecx, span, meta_item, item).into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<Vec<Annotatable>> for Annotatable {
|
|
|
|
fn into(self) -> Vec<Annotatable> {
|
|
|
|
vec![self]
|
2014-12-02 10:07:41 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-29 16:16:43 +12:00
|
|
|
pub trait ProcMacro {
|
|
|
|
fn expand<'cx>(&self,
|
|
|
|
ecx: &'cx mut ExtCtxt,
|
|
|
|
span: Span,
|
|
|
|
ts: TokenStream)
|
2016-09-06 17:57:58 +12:00
|
|
|
-> TokenStream;
|
2016-08-29 16:16:43 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> ProcMacro for F
|
|
|
|
where F: Fn(TokenStream) -> TokenStream
|
|
|
|
{
|
|
|
|
fn expand<'cx>(&self,
|
2016-09-06 17:57:58 +12:00
|
|
|
_ecx: &'cx mut ExtCtxt,
|
|
|
|
_span: Span,
|
2016-08-29 16:16:43 +12:00
|
|
|
ts: TokenStream)
|
2016-09-06 17:57:58 +12:00
|
|
|
-> TokenStream {
|
2016-08-29 16:16:43 +12:00
|
|
|
// FIXME setup implicit context in TLS before calling self.
|
2016-09-06 17:57:58 +12:00
|
|
|
(*self)(ts)
|
2016-08-29 16:16:43 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait AttrProcMacro {
|
|
|
|
fn expand<'cx>(&self,
|
|
|
|
ecx: &'cx mut ExtCtxt,
|
|
|
|
span: Span,
|
|
|
|
annotation: TokenStream,
|
|
|
|
annotated: TokenStream)
|
2016-09-06 17:57:58 +12:00
|
|
|
-> TokenStream;
|
2016-08-29 16:16:43 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> AttrProcMacro for F
|
|
|
|
where F: Fn(TokenStream, TokenStream) -> TokenStream
|
|
|
|
{
|
|
|
|
fn expand<'cx>(&self,
|
2016-09-06 17:57:58 +12:00
|
|
|
_ecx: &'cx mut ExtCtxt,
|
|
|
|
_span: Span,
|
2016-08-29 16:16:43 +12:00
|
|
|
annotation: TokenStream,
|
|
|
|
annotated: TokenStream)
|
2016-09-06 17:57:58 +12:00
|
|
|
-> TokenStream {
|
2016-08-29 16:16:43 +12:00
|
|
|
// FIXME setup implicit context in TLS before calling self.
|
2016-09-06 17:57:58 +12:00
|
|
|
(*self)(annotation, annotated)
|
2016-08-29 16:16:43 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-10 12:09:56 -07:00
|
|
|
/// Represents a thing that maps token trees to Macro Results
|
|
|
|
pub trait TTMacroExpander {
|
2017-02-21 05:05:59 +00:00
|
|
|
fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, input: TokenStream)
|
2014-08-27 21:46:52 -04:00
|
|
|
-> Box<MacResult+'cx>;
|
2013-08-30 14:40:05 -07:00
|
|
|
}
|
|
|
|
|
2014-01-25 13:34:26 -08:00
|
|
|
pub type MacroExpanderFn =
|
2016-06-20 08:49:33 -07:00
|
|
|
for<'cx> fn(&'cx mut ExtCtxt, Span, &[tokenstream::TokenTree])
|
|
|
|
-> Box<MacResult+'cx>;
|
2013-08-30 14:40:05 -07:00
|
|
|
|
2014-11-26 05:52:16 -05:00
|
|
|
impl<F> TTMacroExpander for F
|
2017-02-21 05:05:59 +00:00
|
|
|
where F: for<'cx> Fn(&'cx mut ExtCtxt, Span, &[tokenstream::TokenTree]) -> Box<MacResult+'cx>
|
2014-11-26 05:52:16 -05:00
|
|
|
{
|
2017-02-21 05:05:59 +00:00
|
|
|
fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, input: TokenStream)
|
2014-08-27 21:46:52 -04:00
|
|
|
-> Box<MacResult+'cx> {
|
2017-03-29 07:17:18 +00:00
|
|
|
struct AvoidInterpolatedIdents;
|
|
|
|
|
|
|
|
impl Folder for AvoidInterpolatedIdents {
|
|
|
|
fn fold_tt(&mut self, tt: tokenstream::TokenTree) -> tokenstream::TokenTree {
|
|
|
|
if let tokenstream::TokenTree::Token(_, token::Interpolated(ref nt)) = tt {
|
|
|
|
if let token::NtIdent(ident) = **nt {
|
|
|
|
return tokenstream::TokenTree::Token(ident.span, token::Ident(ident.node));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fold::noop_fold_tt(tt, self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
|
|
|
|
fold::noop_fold_mac(mac, self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let input: Vec<_> =
|
|
|
|
input.trees().map(|tt| AvoidInterpolatedIdents.fold_tt(tt)).collect();
|
|
|
|
(*self)(ecx, span, &input)
|
2013-08-30 14:40:05 -07:00
|
|
|
}
|
|
|
|
}
|
2013-07-08 15:55:14 -07:00
|
|
|
|
2014-01-25 13:34:26 -08:00
|
|
|
pub trait IdentMacroExpander {
|
2014-08-27 21:46:52 -04:00
|
|
|
fn expand<'cx>(&self,
|
|
|
|
cx: &'cx mut ExtCtxt,
|
|
|
|
sp: Span,
|
|
|
|
ident: ast::Ident,
|
2016-12-01 11:54:01 +00:00
|
|
|
token_tree: Vec<tokenstream::TokenTree>)
|
2014-08-27 21:46:52 -04:00
|
|
|
-> Box<MacResult+'cx>;
|
2013-08-30 14:40:05 -07:00
|
|
|
}
|
|
|
|
|
2014-09-10 20:59:26 -07:00
|
|
|
pub type IdentMacroExpanderFn =
|
2016-06-20 08:49:33 -07:00
|
|
|
for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec<tokenstream::TokenTree>)
|
|
|
|
-> Box<MacResult+'cx>;
|
2014-09-10 20:59:26 -07:00
|
|
|
|
2014-11-26 05:52:16 -05:00
|
|
|
impl<F> IdentMacroExpander for F
|
|
|
|
where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, ast::Ident,
|
2016-06-20 08:49:33 -07:00
|
|
|
Vec<tokenstream::TokenTree>) -> Box<MacResult+'cx>
|
2014-11-26 05:52:16 -05:00
|
|
|
{
|
2014-08-27 21:46:52 -04:00
|
|
|
fn expand<'cx>(&self,
|
|
|
|
cx: &'cx mut ExtCtxt,
|
|
|
|
sp: Span,
|
|
|
|
ident: ast::Ident,
|
2016-12-01 11:54:01 +00:00
|
|
|
token_tree: Vec<tokenstream::TokenTree>)
|
2014-11-26 05:52:16 -05:00
|
|
|
-> Box<MacResult+'cx>
|
|
|
|
{
|
|
|
|
(*self)(cx, sp, ident, token_tree)
|
2013-08-30 14:40:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-27 11:14:42 -08:00
|
|
|
// Use a macro because forwarding to a simple function has type system issues
|
2015-04-07 08:21:18 -05:00
|
|
|
macro_rules! make_stmts_default {
|
2015-02-27 11:14:42 -08:00
|
|
|
($me:expr) => {
|
2016-06-17 02:30:01 +00:00
|
|
|
$me.make_expr().map(|e| SmallVector::one(ast::Stmt {
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
span: e.span,
|
|
|
|
node: ast::StmtKind::Expr(e),
|
|
|
|
}))
|
2015-02-27 11:14:42 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-15 22:00:14 +10:00
|
|
|
/// The result of a macro expansion. The return values of the various
|
2015-02-27 11:14:42 -08:00
|
|
|
/// methods are spliced into the AST at the callsite of the macro.
|
2014-04-15 22:00:14 +10:00
|
|
|
pub trait MacResult {
|
|
|
|
/// Create an expression.
|
2014-09-13 19:06:01 +03:00
|
|
|
fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
|
2014-04-15 22:00:14 +10:00
|
|
|
None
|
|
|
|
}
|
|
|
|
/// Create zero or more items.
|
2014-09-13 19:06:01 +03:00
|
|
|
fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
|
2014-04-15 22:00:14 +10:00
|
|
|
None
|
|
|
|
}
|
2014-07-10 17:46:09 -07:00
|
|
|
|
2015-03-11 23:38:58 +02:00
|
|
|
/// Create zero or more impl items.
|
2016-02-11 23:33:09 +03:00
|
|
|
fn make_impl_items(self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
|
2014-07-10 17:46:09 -07:00
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2016-06-11 02:00:07 +01:00
|
|
|
/// Create zero or more trait items.
|
|
|
|
fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2014-05-19 13:32:51 -07:00
|
|
|
/// Create a pattern.
|
2014-09-13 19:06:01 +03:00
|
|
|
fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
|
2014-05-19 13:32:51 -07:00
|
|
|
None
|
|
|
|
}
|
2014-04-15 22:00:14 +10:00
|
|
|
|
2015-04-07 08:21:18 -05:00
|
|
|
/// Create zero or more statements.
|
2014-04-15 22:00:14 +10:00
|
|
|
///
|
|
|
|
/// By default this attempts to create an expression statement,
|
|
|
|
/// returning None if that fails.
|
2016-02-11 23:33:09 +03:00
|
|
|
fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
|
2015-04-07 08:21:18 -05:00
|
|
|
make_stmts_default!(self)
|
2014-04-15 22:00:14 +10:00
|
|
|
}
|
2015-07-25 21:54:19 -07:00
|
|
|
|
|
|
|
fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
|
|
|
|
None
|
|
|
|
}
|
2013-08-30 14:40:05 -07:00
|
|
|
}
|
2013-07-08 15:55:14 -07:00
|
|
|
|
2015-02-27 11:14:42 -08:00
|
|
|
macro_rules! make_MacEager {
|
|
|
|
( $( $fld:ident: $t:ty, )* ) => {
|
|
|
|
/// `MacResult` implementation for the common case where you've already
|
|
|
|
/// built each form of AST that you might return.
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct MacEager {
|
|
|
|
$(
|
|
|
|
pub $fld: Option<$t>,
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MacEager {
|
|
|
|
$(
|
|
|
|
pub fn $fld(v: $t) -> Box<MacResult> {
|
2015-04-15 20:56:16 -07:00
|
|
|
Box::new(MacEager {
|
2015-02-27 11:14:42 -08:00
|
|
|
$fld: Some(v),
|
|
|
|
..Default::default()
|
2015-04-15 20:56:16 -07:00
|
|
|
})
|
2015-02-27 11:14:42 -08:00
|
|
|
}
|
|
|
|
)*
|
2014-08-31 01:45:11 +03:00
|
|
|
}
|
|
|
|
}
|
2014-04-15 22:00:14 +10:00
|
|
|
}
|
2015-02-27 11:14:42 -08:00
|
|
|
|
|
|
|
make_MacEager! {
|
|
|
|
expr: P<ast::Expr>,
|
|
|
|
pat: P<ast::Pat>,
|
|
|
|
items: SmallVector<P<ast::Item>>,
|
2016-02-11 23:33:09 +03:00
|
|
|
impl_items: SmallVector<ast::ImplItem>,
|
2016-06-11 02:00:07 +01:00
|
|
|
trait_items: SmallVector<ast::TraitItem>,
|
2016-02-11 23:33:09 +03:00
|
|
|
stmts: SmallVector<ast::Stmt>,
|
2015-07-25 21:54:19 -07:00
|
|
|
ty: P<ast::Ty>,
|
2014-05-19 13:32:51 -07:00
|
|
|
}
|
2015-02-27 11:14:42 -08:00
|
|
|
|
|
|
|
impl MacResult for MacEager {
|
|
|
|
fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
|
|
|
|
self.expr
|
2014-05-19 13:32:51 -07:00
|
|
|
}
|
2015-02-27 11:14:42 -08:00
|
|
|
|
|
|
|
fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
|
|
|
|
self.items
|
2014-05-19 13:32:51 -07:00
|
|
|
}
|
2014-09-13 12:55:00 +02:00
|
|
|
|
2016-02-11 23:33:09 +03:00
|
|
|
fn make_impl_items(self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
|
2015-03-11 23:38:58 +02:00
|
|
|
self.impl_items
|
2015-02-27 11:14:42 -08:00
|
|
|
}
|
|
|
|
|
2016-06-11 02:00:07 +01:00
|
|
|
fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
|
|
|
|
self.trait_items
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:33:09 +03:00
|
|
|
fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
|
2015-04-07 08:21:18 -05:00
|
|
|
match self.stmts.as_ref().map_or(0, |s| s.len()) {
|
|
|
|
0 => make_stmts_default!(self),
|
|
|
|
_ => self.stmts,
|
2015-02-27 11:14:42 -08:00
|
|
|
}
|
2014-04-15 22:00:14 +10:00
|
|
|
}
|
2014-09-13 12:55:00 +02:00
|
|
|
|
2015-02-27 11:14:42 -08:00
|
|
|
fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
|
|
|
|
if let Some(p) = self.pat {
|
|
|
|
return Some(p);
|
|
|
|
}
|
|
|
|
if let Some(e) = self.expr {
|
2016-02-08 16:05:05 +01:00
|
|
|
if let ast::ExprKind::Lit(_) = e.node {
|
2015-02-27 11:14:42 -08:00
|
|
|
return Some(P(ast::Pat {
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
span: e.span,
|
2016-02-11 21:16:33 +03:00
|
|
|
node: PatKind::Lit(e),
|
2015-02-27 11:14:42 -08:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
2014-04-15 22:00:14 +10:00
|
|
|
}
|
2015-07-25 21:54:19 -07:00
|
|
|
|
|
|
|
fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
|
|
|
|
self.ty
|
|
|
|
}
|
2014-04-15 22:00:14 +10:00
|
|
|
}
|
2014-02-18 16:14:12 +00:00
|
|
|
|
2014-04-15 22:00:14 +10:00
|
|
|
/// Fill-in macro expansion result, to allow compilation to continue
|
|
|
|
/// after hitting errors.
|
2015-03-30 09:38:59 -04:00
|
|
|
#[derive(Copy, Clone)]
|
2014-04-15 22:00:14 +10:00
|
|
|
pub struct DummyResult {
|
|
|
|
expr_only: bool,
|
|
|
|
span: Span
|
2012-07-06 14:29:50 -07:00
|
|
|
}
|
2014-04-15 22:00:14 +10:00
|
|
|
|
|
|
|
impl DummyResult {
|
|
|
|
/// Create a default MacResult that can be anything.
|
|
|
|
///
|
|
|
|
/// Use this as a return value after hitting any errors and
|
|
|
|
/// calling `span_err`.
|
2014-08-27 21:46:52 -04:00
|
|
|
pub fn any(sp: Span) -> Box<MacResult+'static> {
|
2015-04-15 20:56:16 -07:00
|
|
|
Box::new(DummyResult { expr_only: false, span: sp })
|
2014-04-15 22:00:14 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a default MacResult that can only be an expression.
|
|
|
|
///
|
|
|
|
/// Use this for macros that must expand to an expression, so even
|
2014-06-09 00:00:52 -04:00
|
|
|
/// if an error is encountered internally, the user will receive
|
2014-04-15 22:00:14 +10:00
|
|
|
/// an error that they also used it in the wrong place.
|
2014-08-27 21:46:52 -04:00
|
|
|
pub fn expr(sp: Span) -> Box<MacResult+'static> {
|
2015-04-15 20:56:16 -07:00
|
|
|
Box::new(DummyResult { expr_only: true, span: sp })
|
2014-04-15 22:00:14 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// A plain dummy expression.
|
2014-09-13 19:06:01 +03:00
|
|
|
pub fn raw_expr(sp: Span) -> P<ast::Expr> {
|
|
|
|
P(ast::Expr {
|
2014-02-18 16:14:12 +00:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2016-02-08 17:06:20 +01:00
|
|
|
node: ast::ExprKind::Lit(P(codemap::respan(sp, ast::LitKind::Bool(false)))),
|
2014-03-18 23:14:08 +11:00
|
|
|
span: sp,
|
2016-06-18 04:01:57 +00:00
|
|
|
attrs: ast::ThinVec::new(),
|
2014-09-13 19:06:01 +03:00
|
|
|
})
|
2014-02-18 16:14:12 +00:00
|
|
|
}
|
2014-05-19 13:32:51 -07:00
|
|
|
|
|
|
|
/// A plain dummy pattern.
|
2014-09-13 19:06:01 +03:00
|
|
|
pub fn raw_pat(sp: Span) -> ast::Pat {
|
|
|
|
ast::Pat {
|
2014-05-19 13:32:51 -07:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2016-02-11 21:16:33 +03:00
|
|
|
node: PatKind::Wild,
|
2014-05-19 13:32:51 -07:00
|
|
|
span: sp,
|
|
|
|
}
|
|
|
|
}
|
2014-07-10 17:46:09 -07:00
|
|
|
|
2015-07-25 21:54:19 -07:00
|
|
|
pub fn raw_ty(sp: Span) -> P<ast::Ty> {
|
|
|
|
P(ast::Ty {
|
2015-07-25 22:17:43 -07:00
|
|
|
id: ast::DUMMY_NODE_ID,
|
2016-02-08 16:53:21 +01:00
|
|
|
node: ast::TyKind::Infer,
|
2015-07-25 21:54:19 -07:00
|
|
|
span: sp
|
|
|
|
})
|
2015-07-25 22:17:43 -07:00
|
|
|
}
|
2014-03-18 23:14:08 +11:00
|
|
|
}
|
2014-04-15 22:00:14 +10:00
|
|
|
|
|
|
|
impl MacResult for DummyResult {
|
2014-09-13 19:06:01 +03:00
|
|
|
fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> {
|
2014-04-15 22:00:14 +10:00
|
|
|
Some(DummyResult::raw_expr(self.span))
|
2014-03-18 23:14:08 +11:00
|
|
|
}
|
2015-07-25 22:17:43 -07:00
|
|
|
|
2014-09-13 19:06:01 +03:00
|
|
|
fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
|
|
|
|
Some(P(DummyResult::raw_pat(self.span)))
|
2014-05-19 13:32:51 -07:00
|
|
|
}
|
2015-07-25 22:17:43 -07:00
|
|
|
|
2014-09-13 19:06:01 +03:00
|
|
|
fn make_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Item>>> {
|
2014-07-10 17:46:09 -07:00
|
|
|
// this code needs a comment... why not always just return the Some() ?
|
|
|
|
if self.expr_only {
|
|
|
|
None
|
|
|
|
} else {
|
2016-11-02 22:33:35 -06:00
|
|
|
Some(SmallVector::new())
|
2014-07-10 17:46:09 -07:00
|
|
|
}
|
|
|
|
}
|
2015-07-25 22:17:43 -07:00
|
|
|
|
2016-02-11 23:33:09 +03:00
|
|
|
fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVector<ast::ImplItem>> {
|
2014-04-15 22:00:14 +10:00
|
|
|
if self.expr_only {
|
|
|
|
None
|
|
|
|
} else {
|
2016-11-02 22:33:35 -06:00
|
|
|
Some(SmallVector::new())
|
2014-04-15 22:00:14 +10:00
|
|
|
}
|
2014-03-18 23:14:08 +11:00
|
|
|
}
|
2015-07-25 22:17:43 -07:00
|
|
|
|
2016-06-11 02:00:07 +01:00
|
|
|
fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVector<ast::TraitItem>> {
|
|
|
|
if self.expr_only {
|
|
|
|
None
|
|
|
|
} else {
|
2016-11-02 22:33:35 -06:00
|
|
|
Some(SmallVector::new())
|
2016-06-11 02:00:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:33:09 +03:00
|
|
|
fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
|
2016-06-17 02:30:01 +00:00
|
|
|
Some(SmallVector::one(ast::Stmt {
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)),
|
|
|
|
span: self.span,
|
|
|
|
}))
|
2014-03-18 23:14:08 +11:00
|
|
|
}
|
2016-06-17 11:02:42 +00:00
|
|
|
|
|
|
|
fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
|
|
|
|
Some(DummyResult::raw_ty(self.span))
|
|
|
|
}
|
2014-01-18 01:53:10 +11:00
|
|
|
}
|
2012-07-05 12:10:33 -07:00
|
|
|
|
2017-01-24 01:31:49 +10:30
|
|
|
pub type BuiltinDeriveFn =
|
|
|
|
for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
|
|
|
|
|
2017-02-06 22:14:38 +10:30
|
|
|
/// Represents different kinds of macro invocations that can be resolved.
|
2017-02-23 20:12:33 +10:30
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
2017-02-06 22:14:38 +10:30
|
|
|
pub enum MacroKind {
|
|
|
|
/// A bang macro - foo!()
|
|
|
|
Bang,
|
|
|
|
/// An attribute macro - #[foo]
|
|
|
|
Attr,
|
|
|
|
/// A derive attribute macro - #[derive(Foo)]
|
|
|
|
Derive,
|
|
|
|
}
|
|
|
|
|
2014-02-27 23:49:25 -08:00
|
|
|
/// An enum representing the different kinds of syntax extensions.
|
2013-01-29 14:41:40 -08:00
|
|
|
pub enum SyntaxExtension {
|
2014-02-27 23:49:25 -08:00
|
|
|
/// A syntax extension that is attached to an item and creates new items
|
|
|
|
/// based upon it.
|
|
|
|
///
|
2015-01-20 20:28:36 +01:00
|
|
|
/// `#[derive(...)]` is a `MultiItemDecorator`.
|
2016-08-29 16:16:43 +12:00
|
|
|
///
|
|
|
|
/// Prefer ProcMacro or MultiModifier since they are more flexible.
|
|
|
|
MultiDecorator(Box<MultiItemDecorator>),
|
2012-06-25 15:04:50 -07:00
|
|
|
|
2014-02-27 23:49:25 -08:00
|
|
|
/// A syntax extension that is attached to an item and modifies it
|
2016-08-29 16:16:43 +12:00
|
|
|
/// in-place. Also allows decoration, i.e., creating new items.
|
|
|
|
MultiModifier(Box<MultiItemModifier>),
|
|
|
|
|
|
|
|
/// A function-like procedural macro. TokenStream -> TokenStream.
|
|
|
|
ProcMacro(Box<ProcMacro>),
|
|
|
|
|
|
|
|
/// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
|
|
|
|
/// The first TokenSteam is the attribute, the second is the annotated item.
|
|
|
|
/// Allows modification of the input items and adding new items, similar to
|
|
|
|
/// MultiModifier, but uses TokenStreams, rather than AST nodes.
|
|
|
|
AttrProcMacro(Box<AttrProcMacro>),
|
2014-12-02 10:07:41 -08:00
|
|
|
|
2014-02-27 23:49:25 -08:00
|
|
|
/// A normal, function-like syntax extension.
|
|
|
|
///
|
|
|
|
/// `bytes!` is a `NormalTT`.
|
Add #[allow_internal_unstable] to track stability for macros better.
Unstable items used in a macro expansion will now always trigger
stability warnings, *unless* the unstable items are directly inside a
macro marked with `#[allow_internal_unstable]`. IOW, the compiler warns
unless the span of the unstable item is a subspan of the definition of a
macro marked with that attribute.
E.g.
#[allow_internal_unstable]
macro_rules! foo {
($e: expr) => {{
$e;
unstable(); // no warning
only_called_by_foo!();
}}
}
macro_rules! only_called_by_foo {
() => { unstable() } // warning
}
foo!(unstable()) // warning
The unstable inside `foo` is fine, due to the attribute. But the
`unstable` inside `only_called_by_foo` is not, since that macro doesn't
have the attribute, and the `unstable` passed into `foo` is also not
fine since it isn't contained in the macro itself (that is, even though
it is only used directly in the macro).
In the process this makes the stability tracking much more precise,
e.g. previously `println!("{}", unstable())` got no warning, but now it
does. As such, this is a bug fix that may cause [breaking-change]s.
The attribute is definitely feature gated, since it explicitly allows
side-stepping the feature gating system.
2015-03-01 14:09:28 +11:00
|
|
|
///
|
|
|
|
/// The `bool` dictates whether the contents of the macro can
|
|
|
|
/// directly use `#[unstable]` things (true == yes).
|
2016-08-29 16:16:43 +12:00
|
|
|
NormalTT(Box<TTMacroExpander>, Option<Span>, bool),
|
2013-02-26 10:15:29 -08:00
|
|
|
|
2014-02-27 23:49:25 -08:00
|
|
|
/// A function-like syntax extension that has an extra ident before
|
|
|
|
/// the block.
|
|
|
|
///
|
2016-08-29 16:16:43 +12:00
|
|
|
IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
|
2016-10-15 20:50:30 +00:00
|
|
|
|
2017-01-24 08:55:08 +10:30
|
|
|
/// An attribute-like procedural macro. TokenStream -> TokenStream.
|
|
|
|
/// The input is the annotated item.
|
|
|
|
/// Allows generating code to implement a Trait for a given struct
|
|
|
|
/// or enum item.
|
2017-02-02 07:01:15 +00:00
|
|
|
ProcMacroDerive(Box<MultiItemModifier>, Vec<Symbol> /* inert attribute names */),
|
2017-01-24 01:31:49 +10:30
|
|
|
|
|
|
|
/// An attribute-like procedural macro that derives a builtin trait.
|
|
|
|
BuiltinDerive(BuiltinDeriveFn),
|
2011-06-20 17:26:17 -07:00
|
|
|
}
|
2011-06-04 15:41:45 -04:00
|
|
|
|
2017-02-06 22:14:38 +10:30
|
|
|
impl SyntaxExtension {
|
|
|
|
/// Return which kind of macro calls this syntax extension.
|
|
|
|
pub fn kind(&self) -> MacroKind {
|
|
|
|
match *self {
|
|
|
|
SyntaxExtension::NormalTT(..) |
|
|
|
|
SyntaxExtension::IdentTT(..) |
|
|
|
|
SyntaxExtension::ProcMacro(..) =>
|
|
|
|
MacroKind::Bang,
|
|
|
|
SyntaxExtension::MultiDecorator(..) |
|
|
|
|
SyntaxExtension::MultiModifier(..) |
|
|
|
|
SyntaxExtension::AttrProcMacro(..) =>
|
|
|
|
MacroKind::Attr,
|
|
|
|
SyntaxExtension::ProcMacroDerive(..) |
|
|
|
|
SyntaxExtension::BuiltinDerive(..) =>
|
|
|
|
MacroKind::Derive,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-24 16:16:10 -07:00
|
|
|
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
|
|
|
|
|
2016-09-05 03:46:05 +00:00
|
|
|
pub trait Resolver {
|
2016-09-05 00:10:27 +00:00
|
|
|
fn next_node_id(&mut self) -> ast::NodeId;
|
2016-09-23 07:23:01 +00:00
|
|
|
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
|
2016-11-08 03:16:54 +00:00
|
|
|
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
|
2016-12-22 06:03:19 +00:00
|
|
|
fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
|
2016-09-07 23:21:59 +00:00
|
|
|
|
2017-02-02 07:01:15 +00:00
|
|
|
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]);
|
2017-03-05 05:15:58 +00:00
|
|
|
fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
|
2016-09-07 23:21:59 +00:00
|
|
|
|
2016-11-10 10:11:25 +00:00
|
|
|
fn resolve_imports(&mut self);
|
2017-02-02 07:01:15 +00:00
|
|
|
// Resolves attribute and derive legacy macros from `#![plugin(..)]`.
|
|
|
|
fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
|
2017-03-01 08:44:05 +00:00
|
|
|
fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
|
|
|
|
-> Result<Option<Rc<SyntaxExtension>>, Determinacy>;
|
|
|
|
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
|
|
|
|
-> Result<Rc<SyntaxExtension>, Determinacy>;
|
2016-06-02 01:14:33 +00:00
|
|
|
}
|
|
|
|
|
2016-10-11 03:41:48 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub enum Determinacy {
|
|
|
|
Determined,
|
|
|
|
Undetermined,
|
|
|
|
}
|
|
|
|
|
2016-09-05 03:46:05 +00:00
|
|
|
pub struct DummyResolver;
|
2016-09-05 00:10:27 +00:00
|
|
|
|
2016-09-05 03:46:05 +00:00
|
|
|
impl Resolver for DummyResolver {
|
2016-09-05 00:10:27 +00:00
|
|
|
fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
|
2016-09-23 07:23:01 +00:00
|
|
|
fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
|
2016-11-08 03:16:54 +00:00
|
|
|
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
|
2016-12-22 06:03:19 +00:00
|
|
|
fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
|
2016-09-07 23:21:59 +00:00
|
|
|
|
2017-02-02 07:01:15 +00:00
|
|
|
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion, _derives: &[Mark]) {}
|
2017-03-05 05:15:58 +00:00
|
|
|
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
|
2016-09-07 23:21:59 +00:00
|
|
|
|
2016-11-10 10:11:25 +00:00
|
|
|
fn resolve_imports(&mut self) {}
|
2017-02-02 07:01:15 +00:00
|
|
|
fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
|
2017-03-01 08:44:05 +00:00
|
|
|
fn resolve_invoc(&mut self, _invoc: &mut Invocation, _scope: Mark, _force: bool)
|
|
|
|
-> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
|
|
|
|
Err(Determinacy::Determined)
|
|
|
|
}
|
2017-02-06 22:14:38 +10:30
|
|
|
fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind,
|
|
|
|
_force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
|
2017-02-01 21:03:09 +10:30
|
|
|
Err(Determinacy::Determined)
|
|
|
|
}
|
2016-09-07 23:21:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct ModuleData {
|
|
|
|
pub mod_path: Vec<ast::Ident>,
|
|
|
|
pub directory: PathBuf,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct ExpansionData {
|
|
|
|
pub mark: Mark,
|
|
|
|
pub depth: usize,
|
|
|
|
pub module: Rc<ModuleData>,
|
2016-11-05 04:16:26 +00:00
|
|
|
pub directory_ownership: DirectoryOwnership,
|
2016-06-02 01:14:33 +00:00
|
|
|
}
|
|
|
|
|
2014-06-09 13:12:30 -07:00
|
|
|
/// One of these is made during expansion and incrementally updated as we go;
|
|
|
|
/// when a macro expansion occurs, the resulting nodes have the backtrace()
|
|
|
|
/// -> expn_info of their expansion context stored into their span.
|
2013-12-25 11:10:33 -07:00
|
|
|
pub struct ExtCtxt<'a> {
|
2014-03-27 15:39:48 -07:00
|
|
|
pub parse_sess: &'a parse::ParseSess,
|
2015-02-15 21:30:45 +01:00
|
|
|
pub ecfg: expand::ExpansionConfig<'a>,
|
2015-07-29 17:01:14 -07:00
|
|
|
pub crate_root: Option<&'static str>,
|
2016-09-05 03:46:05 +00:00
|
|
|
pub resolver: &'a mut Resolver,
|
2016-09-20 06:33:42 +00:00
|
|
|
pub resolve_err_count: usize,
|
2016-09-07 23:21:59 +00:00
|
|
|
pub current_expansion: ExpansionData,
|
2017-05-05 21:49:59 -07:00
|
|
|
pub expansions: HashMap<Span, Vec<String>>,
|
2013-05-17 20:10:26 +10:00
|
|
|
}
|
2013-03-15 15:24:24 -04:00
|
|
|
|
2013-12-25 11:10:33 -07:00
|
|
|
impl<'a> ExtCtxt<'a> {
|
2016-10-27 06:36:56 +00:00
|
|
|
pub fn new(parse_sess: &'a parse::ParseSess,
|
2015-07-13 17:10:44 -07:00
|
|
|
ecfg: expand::ExpansionConfig<'a>,
|
2016-09-05 03:46:05 +00:00
|
|
|
resolver: &'a mut Resolver)
|
2016-06-02 01:14:33 +00:00
|
|
|
-> ExtCtxt<'a> {
|
2013-12-27 17:17:36 -07:00
|
|
|
ExtCtxt {
|
2013-05-17 21:27:17 +10:00
|
|
|
parse_sess: parse_sess,
|
2014-02-28 23:17:38 -08:00
|
|
|
ecfg: ecfg,
|
2015-07-29 17:01:14 -07:00
|
|
|
crate_root: None,
|
2016-09-05 03:46:05 +00:00
|
|
|
resolver: resolver,
|
2016-09-20 06:33:42 +00:00
|
|
|
resolve_err_count: 0,
|
2016-09-07 23:21:59 +00:00
|
|
|
current_expansion: ExpansionData {
|
|
|
|
mark: Mark::root(),
|
|
|
|
depth: 0,
|
|
|
|
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
|
2016-11-05 04:16:26 +00:00
|
|
|
directory_ownership: DirectoryOwnership::Owned,
|
2016-09-07 23:21:59 +00:00
|
|
|
},
|
2017-05-05 21:49:59 -07:00
|
|
|
expansions: HashMap::new(),
|
2013-05-17 21:27:17 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-07 23:11:25 +01:00
|
|
|
/// Returns a `Folder` for deeply expanding all macros in an AST node.
|
2014-07-20 16:25:35 +02:00
|
|
|
pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
|
2016-09-06 05:42:45 +00:00
|
|
|
expand::MacroExpander::new(self, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a `Folder` that deeply expands all macros and assigns all node ids in an AST node.
|
|
|
|
/// Once node ids are assigned, the node may not be expanded, removed, or otherwise modified.
|
|
|
|
pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
|
|
|
|
expand::MacroExpander::new(self, true)
|
2013-10-05 21:15:46 -07:00
|
|
|
}
|
|
|
|
|
2017-02-21 05:05:59 +00:00
|
|
|
pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> {
|
|
|
|
parse::stream_to_parser(self.parse_sess, tts.iter().cloned().collect())
|
2014-07-03 11:42:24 +02:00
|
|
|
}
|
2015-05-13 23:08:02 +03:00
|
|
|
pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() }
|
2014-03-09 16:54:34 +02:00
|
|
|
pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
|
2016-10-27 06:36:56 +00:00
|
|
|
pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config }
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn call_site(&self) -> Span {
|
2017-03-17 04:04:41 +00:00
|
|
|
match self.current_expansion.mark.expn_info() {
|
2014-01-03 15:08:48 -08:00
|
|
|
Some(expn_info) => expn_info.call_site,
|
2017-03-17 04:04:41 +00:00
|
|
|
None => DUMMY_SP,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn backtrace(&self) -> SyntaxContext {
|
|
|
|
SyntaxContext::empty().apply_mark(self.current_expansion.mark)
|
2013-05-17 20:10:26 +10:00
|
|
|
}
|
2015-06-16 21:47:09 +03:00
|
|
|
|
|
|
|
/// Returns span for the macro which originally caused the current expansion to happen.
|
|
|
|
///
|
|
|
|
/// Stops backtracing at include! boundary.
|
|
|
|
pub fn expansion_cause(&self) -> Span {
|
2017-03-17 04:04:41 +00:00
|
|
|
let mut ctxt = self.backtrace();
|
2015-06-16 21:47:09 +03:00
|
|
|
let mut last_macro = None;
|
2014-09-17 19:01:33 +03:00
|
|
|
loop {
|
2017-03-17 04:04:41 +00:00
|
|
|
if ctxt.outer().expn_info().map_or(None, |info| {
|
|
|
|
if info.callee.name() == "include" {
|
|
|
|
// Stop going up the backtrace once include! is encountered
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
ctxt = info.call_site.ctxt;
|
|
|
|
last_macro = Some(info.call_site);
|
|
|
|
return Some(());
|
2015-06-16 21:47:09 +03:00
|
|
|
}).is_none() {
|
|
|
|
break
|
2014-09-17 19:01:33 +03:00
|
|
|
}
|
|
|
|
}
|
2015-06-16 21:47:09 +03:00
|
|
|
last_macro.expect("missing expansion backtrace")
|
2014-09-17 19:01:33 +03:00
|
|
|
}
|
|
|
|
|
2015-12-21 10:00:43 +13:00
|
|
|
pub fn struct_span_warn(&self,
|
|
|
|
sp: Span,
|
|
|
|
msg: &str)
|
|
|
|
-> DiagnosticBuilder<'a> {
|
|
|
|
self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
|
|
|
|
}
|
|
|
|
pub fn struct_span_err(&self,
|
|
|
|
sp: Span,
|
|
|
|
msg: &str)
|
|
|
|
-> DiagnosticBuilder<'a> {
|
|
|
|
self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
|
|
|
|
}
|
|
|
|
pub fn struct_span_fatal(&self,
|
|
|
|
sp: Span,
|
|
|
|
msg: &str)
|
|
|
|
-> DiagnosticBuilder<'a> {
|
|
|
|
self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg)
|
|
|
|
}
|
|
|
|
|
2014-01-18 01:53:10 +11:00
|
|
|
/// Emit `msg` attached to `sp`, and stop compilation immediately.
|
|
|
|
///
|
2014-07-02 21:27:07 -04:00
|
|
|
/// `span_err` should be strongly preferred where-ever possible:
|
2014-01-18 01:53:10 +11:00
|
|
|
/// this should *only* be used when
|
|
|
|
/// - continuing has a high risk of flow-on errors (e.g. errors in
|
|
|
|
/// declaring a macro would cause all uses of that macro to
|
|
|
|
/// complain about "undefined macro"), or
|
|
|
|
/// - there is literally nothing else that can be done (however,
|
|
|
|
/// in most cases one can construct a dummy expression/item to
|
|
|
|
/// substitute; we never hit resolve/type-checking so the dummy
|
|
|
|
/// value doesn't have to match anything)
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
|
2015-03-28 21:58:51 +00:00
|
|
|
panic!(self.parse_sess.span_diagnostic.span_fatal(sp, msg));
|
2013-05-17 20:10:26 +10:00
|
|
|
}
|
2014-01-18 01:53:10 +11:00
|
|
|
|
|
|
|
/// Emit `msg` attached to `sp`, without immediately stopping
|
|
|
|
/// compilation.
|
|
|
|
///
|
|
|
|
/// Compilation will be stopped in the near future (at the end of
|
|
|
|
/// the macro expansion phase).
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn span_err(&self, sp: Span, msg: &str) {
|
2013-05-17 20:10:26 +10:00
|
|
|
self.parse_sess.span_diagnostic.span_err(sp, msg);
|
|
|
|
}
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn span_warn(&self, sp: Span, msg: &str) {
|
2013-05-17 20:10:26 +10:00
|
|
|
self.parse_sess.span_diagnostic.span_warn(sp, msg);
|
|
|
|
}
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
|
2013-05-17 20:10:26 +10:00
|
|
|
self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
|
|
|
|
}
|
2013-08-31 18:13:04 +02:00
|
|
|
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
|
2013-05-17 20:10:26 +10:00
|
|
|
self.parse_sess.span_diagnostic.span_bug(sp, msg);
|
|
|
|
}
|
2017-05-05 21:49:59 -07:00
|
|
|
pub fn trace_macros_diag(&self) {
|
|
|
|
for (sp, notes) in self.expansions.iter() {
|
|
|
|
let mut db = self.parse_sess.span_diagnostic.span_note_diag(*sp, &"trace_macro");
|
|
|
|
for note in notes {
|
|
|
|
db.note(¬e);
|
|
|
|
}
|
|
|
|
db.emit();
|
|
|
|
}
|
2017-04-24 16:27:07 -07:00
|
|
|
}
|
2013-05-31 15:17:22 -07:00
|
|
|
pub fn bug(&self, msg: &str) -> ! {
|
2015-12-14 11:17:55 +13:00
|
|
|
self.parse_sess.span_diagnostic.bug(msg);
|
2013-05-17 20:10:26 +10:00
|
|
|
}
|
2013-05-31 15:17:22 -07:00
|
|
|
pub fn trace_macros(&self) -> bool {
|
2015-04-14 15:36:38 +02:00
|
|
|
self.ecfg.trace_mac
|
2013-05-17 20:10:26 +10:00
|
|
|
}
|
2013-12-28 22:35:38 -07:00
|
|
|
pub fn set_trace_macros(&mut self, x: bool) {
|
2015-04-14 15:36:38 +02:00
|
|
|
self.ecfg.trace_mac = x
|
2013-05-17 20:10:26 +10:00
|
|
|
}
|
2013-09-02 02:50:59 +02:00
|
|
|
pub fn ident_of(&self, st: &str) -> ast::Ident {
|
2016-11-16 08:21:52 +00:00
|
|
|
ast::Ident::from_str(st)
|
2013-05-17 20:10:26 +10:00
|
|
|
}
|
2015-07-29 17:01:14 -07:00
|
|
|
pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
|
|
|
|
let mut v = Vec::new();
|
|
|
|
if let Some(s) = self.crate_root {
|
|
|
|
v.push(self.ident_of(s));
|
|
|
|
}
|
|
|
|
v.extend(components.iter().map(|s| self.ident_of(s)));
|
|
|
|
return v
|
2014-09-07 14:57:26 -07:00
|
|
|
}
|
2014-07-06 01:17:59 -07:00
|
|
|
pub fn name_of(&self, st: &str) -> ast::Name {
|
2016-11-16 08:21:52 +00:00
|
|
|
Symbol::intern(st)
|
2014-07-06 01:17:59 -07:00
|
|
|
}
|
2013-05-17 20:10:26 +10:00
|
|
|
}
|
|
|
|
|
2014-03-02 13:38:44 -08:00
|
|
|
/// Extract a string literal from the macro expanded version of `expr`,
|
|
|
|
/// emitting `err_msg` if `expr` is not a string literal. This does not stop
|
|
|
|
/// compilation on error, merely emits a non-fatal error and returns None.
|
2016-09-02 22:01:35 +00:00
|
|
|
pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
2016-11-16 10:52:37 +00:00
|
|
|
-> Option<Spanned<(Symbol, ast::StrStyle)>> {
|
2017-03-17 04:04:41 +00:00
|
|
|
// Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
|
2016-07-14 08:55:48 +00:00
|
|
|
let expr = expr.map(|mut expr| {
|
2017-03-17 04:04:41 +00:00
|
|
|
expr.span.ctxt = expr.span.ctxt.apply_mark(cx.current_expansion.mark);
|
2016-07-14 08:55:48 +00:00
|
|
|
expr
|
|
|
|
});
|
|
|
|
|
2014-03-02 13:38:44 -08:00
|
|
|
// we want to be able to handle e.g. concat("foo", "bar")
|
2014-07-20 16:25:35 +02:00
|
|
|
let expr = cx.expander().fold_expr(expr);
|
2012-08-06 12:34:08 -07:00
|
|
|
match expr.node {
|
2016-02-08 16:05:05 +01:00
|
|
|
ast::ExprKind::Lit(ref l) => match l.node {
|
2016-11-16 10:52:37 +00:00
|
|
|
ast::LitKind::Str(s, style) => return Some(respan(expr.span, (s, style))),
|
2014-01-18 01:53:10 +11:00
|
|
|
_ => cx.span_err(l.span, err_msg)
|
2014-01-09 15:05:33 +02:00
|
|
|
},
|
2014-01-18 01:53:10 +11:00
|
|
|
_ => cx.span_err(expr.span, err_msg)
|
2011-06-20 17:26:17 -07:00
|
|
|
}
|
2014-01-18 01:53:10 +11:00
|
|
|
None
|
2011-06-20 17:26:17 -07:00
|
|
|
}
|
|
|
|
|
2016-09-02 22:01:35 +00:00
|
|
|
pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
2016-11-16 10:52:37 +00:00
|
|
|
-> Option<(Symbol, ast::StrStyle)> {
|
2016-09-02 22:01:35 +00:00
|
|
|
expr_to_spanned_string(cx, expr, err_msg).map(|s| s.node)
|
|
|
|
}
|
|
|
|
|
2014-01-18 01:53:10 +11:00
|
|
|
/// Non-fatally assert that `tts` is empty. Note that this function
|
|
|
|
/// returns even when `tts` is non-empty, macros that *need* to stop
|
|
|
|
/// compilation should call
|
|
|
|
/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
|
|
|
|
/// done as rarely as possible).
|
2014-01-10 14:02:36 -08:00
|
|
|
pub fn check_zero_tts(cx: &ExtCtxt,
|
|
|
|
sp: Span,
|
2016-06-20 08:49:33 -07:00
|
|
|
tts: &[tokenstream::TokenTree],
|
2013-01-29 14:41:40 -08:00
|
|
|
name: &str) {
|
2015-03-24 16:54:09 -07:00
|
|
|
if !tts.is_empty() {
|
2015-02-20 14:08:14 -05:00
|
|
|
cx.span_err(sp, &format!("{} takes no arguments", name));
|
2012-12-12 17:08:09 -08:00
|
|
|
}
|
2012-05-14 15:32:32 -07:00
|
|
|
}
|
|
|
|
|
2014-01-18 01:53:10 +11:00
|
|
|
/// Extract the string literal from the first token of `tts`. If this
|
|
|
|
/// is not a string literal, emit an error and return None.
|
2014-10-20 23:04:16 -07:00
|
|
|
pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
|
2013-08-31 18:13:04 +02:00
|
|
|
sp: Span,
|
2016-06-20 08:49:33 -07:00
|
|
|
tts: &[tokenstream::TokenTree],
|
2013-08-07 09:47:28 -07:00
|
|
|
name: &str)
|
2014-05-22 16:57:53 -07:00
|
|
|
-> Option<String> {
|
2014-10-20 23:04:16 -07:00
|
|
|
let mut p = cx.new_parser_from_tts(tts);
|
2014-11-02 23:10:09 -08:00
|
|
|
if p.token == token::Eof {
|
2015-02-20 14:08:14 -05:00
|
|
|
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
2014-11-02 23:10:09 -08:00
|
|
|
return None
|
|
|
|
}
|
2016-09-02 22:01:35 +00:00
|
|
|
let ret = panictry!(p.parse_expr());
|
2014-10-20 23:04:16 -07:00
|
|
|
if p.token != token::Eof {
|
2015-02-20 14:08:14 -05:00
|
|
|
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
2012-01-31 23:50:12 -07:00
|
|
|
}
|
2014-10-20 23:04:16 -07:00
|
|
|
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| {
|
2015-02-03 23:31:06 +01:00
|
|
|
s.to_string()
|
2014-10-20 23:04:16 -07:00
|
|
|
})
|
2012-01-31 23:50:12 -07:00
|
|
|
}
|
2011-06-20 17:26:17 -07:00
|
|
|
|
2014-01-18 01:53:10 +11:00
|
|
|
/// Extract comma-separated expressions from `tts`. If there is a
|
|
|
|
/// parsing error, emit a non-fatal error and return None.
|
2014-03-02 13:38:44 -08:00
|
|
|
pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
|
2013-08-31 18:13:04 +02:00
|
|
|
sp: Span,
|
2016-06-20 08:49:33 -07:00
|
|
|
tts: &[tokenstream::TokenTree]) -> Option<Vec<P<ast::Expr>>> {
|
2014-07-03 11:42:24 +02:00
|
|
|
let mut p = cx.new_parser_from_tts(tts);
|
2014-02-28 13:09:09 -08:00
|
|
|
let mut es = Vec::new();
|
2014-10-27 19:22:52 +11:00
|
|
|
while p.token != token::Eof {
|
2015-11-10 16:08:26 -08:00
|
|
|
es.push(cx.expander().fold_expr(panictry!(p.parse_expr())));
|
2015-12-31 12:11:53 +13:00
|
|
|
if p.eat(&token::Comma) {
|
2014-06-23 15:51:40 +00:00
|
|
|
continue;
|
|
|
|
}
|
2014-10-27 19:22:52 +11:00
|
|
|
if p.token != token::Eof {
|
2014-01-18 01:53:10 +11:00
|
|
|
cx.span_err(sp, "expected token: `,`");
|
|
|
|
return None;
|
2012-12-12 17:08:09 -08:00
|
|
|
}
|
2012-07-12 17:59:59 -07:00
|
|
|
}
|
2014-01-18 01:53:10 +11:00
|
|
|
Some(es)
|
2012-07-12 17:59:59 -07:00
|
|
|
}
|
2016-09-06 17:57:58 +12:00
|
|
|
|
|
|
|
pub struct ChangeSpan {
|
|
|
|
pub span: Span
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Folder for ChangeSpan {
|
|
|
|
fn new_span(&mut self, _sp: Span) -> Span {
|
|
|
|
self.span
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
|
|
|
|
fold::noop_fold_mac(mac, self)
|
|
|
|
}
|
|
|
|
}
|