expansion: Rename Expansion to AstFragment
This commit is contained in:
parent
869fa27d13
commit
a12726460e
5 changed files with 208 additions and 195 deletions
|
|
@ -23,7 +23,7 @@ use syntax::attr::{self, HasAttrs};
|
|||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
|
||||
use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
|
||||
use syntax::ext::expand::{self, AstFragment, AstFragmentKind, Invocation, InvocationKind};
|
||||
use syntax::ext::hygiene::{self, Mark, Transparency};
|
||||
use syntax::ext::placeholders::placeholder;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
|
|
@ -187,9 +187,10 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
self.whitelisted_legacy_custom_derives.contains(&name)
|
||||
}
|
||||
|
||||
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) {
|
||||
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
|
||||
derives: &[Mark]) {
|
||||
let invocation = self.invocations[&mark];
|
||||
self.collect_def_ids(mark, invocation, expansion);
|
||||
self.collect_def_ids(mark, invocation, fragment);
|
||||
|
||||
self.current_module = invocation.module.get();
|
||||
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
|
||||
|
|
@ -202,7 +203,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
legacy_scope: LegacyScope::Invocation(invocation),
|
||||
expansion: mark,
|
||||
};
|
||||
expansion.visit_with(&mut visitor);
|
||||
fragment.visit_with(&mut visitor);
|
||||
invocation.expansion.set(visitor.legacy_scope);
|
||||
}
|
||||
|
||||
|
|
@ -396,14 +397,14 @@ impl<'a> Resolver<'a> {
|
|||
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
|
||||
if inert_attrs.contains(&attr_name) {
|
||||
// FIXME(jseyfried) Avoid `mem::replace` here.
|
||||
let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
|
||||
let dummy_item = placeholder(AstFragmentKind::Items, ast::DUMMY_NODE_ID)
|
||||
.make_items().pop().unwrap();
|
||||
let dummy_item = Annotatable::Item(dummy_item);
|
||||
*item = mem::replace(item, dummy_item).map_attrs(|mut attrs| {
|
||||
let inert_attr = attr.take().unwrap();
|
||||
attr::mark_known(&inert_attr);
|
||||
if self.proc_macro_enabled {
|
||||
*attr = find_attr_invoc(&mut attrs);
|
||||
*attr = expand::find_attr_invoc(&mut attrs);
|
||||
}
|
||||
attrs.push(inert_attr);
|
||||
attrs
|
||||
|
|
@ -769,7 +770,7 @@ impl<'a> Resolver<'a> {
|
|||
fn collect_def_ids(&mut self,
|
||||
mark: Mark,
|
||||
invocation: &'a InvocationData<'a>,
|
||||
expansion: &Expansion) {
|
||||
fragment: &AstFragment) {
|
||||
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
|
||||
let InvocationData { def_index, .. } = *invocation;
|
||||
|
||||
|
|
@ -787,7 +788,7 @@ impl<'a> Resolver<'a> {
|
|||
let mut def_collector = DefCollector::new(&mut self.definitions, mark);
|
||||
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
|
||||
def_collector.with_parent(def_index, |def_collector| {
|
||||
expansion.visit_with(def_collector)
|
||||
fragment.visit_with(def_collector)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use codemap::{self, CodeMap, Spanned, respan};
|
|||
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
|
||||
use edition::Edition;
|
||||
use errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use ext::expand::{self, Expansion, Invocation};
|
||||
use ext::expand::{self, AstFragment, Invocation};
|
||||
use ext::hygiene::{self, Mark, SyntaxContext};
|
||||
use fold::{self, Folder};
|
||||
use parse::{self, parser, DirectoryOwnership};
|
||||
|
|
@ -697,7 +697,8 @@ pub trait Resolver {
|
|||
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
|
||||
fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
|
||||
|
||||
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]);
|
||||
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
|
||||
derives: &[Mark]);
|
||||
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
|
||||
|
||||
fn resolve_imports(&mut self);
|
||||
|
|
@ -726,7 +727,8 @@ impl Resolver for DummyResolver {
|
|||
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
|
||||
fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
|
||||
|
||||
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion, _derives: &[Mark]) {}
|
||||
fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
|
||||
_derives: &[Mark]) {}
|
||||
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
|
||||
|
||||
fn resolve_imports(&mut self) {}
|
||||
|
|
|
|||
|
|
@ -40,46 +40,51 @@ use std::mem;
|
|||
use std::rc::Rc;
|
||||
use std::path::PathBuf;
|
||||
|
||||
macro_rules! expansions {
|
||||
macro_rules! ast_fragments {
|
||||
($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
|
||||
$(.$fold:ident)* $(lift .$fold_elt:ident)*,
|
||||
$(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ExpansionKind { OptExpr, $( $kind, )* }
|
||||
pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
|
||||
/// 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.
|
||||
pub enum AstFragment { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
|
||||
|
||||
impl ExpansionKind {
|
||||
/// "Discriminant" of an AST fragment.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum AstFragmentKind { OptExpr, $( $kind, )* }
|
||||
|
||||
impl AstFragmentKind {
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
ExpansionKind::OptExpr => "expression",
|
||||
$( ExpansionKind::$kind => $kind_name, )*
|
||||
AstFragmentKind::OptExpr => "expression",
|
||||
$( AstFragmentKind::$kind => $kind_name, )*
|
||||
}
|
||||
}
|
||||
|
||||
fn make_from<'a>(self, result: Box<MacResult + 'a>) -> Option<Expansion> {
|
||||
fn make_from<'a>(self, result: Box<MacResult + 'a>) -> Option<AstFragment> {
|
||||
match self {
|
||||
ExpansionKind::OptExpr => result.make_expr().map(Some).map(Expansion::OptExpr),
|
||||
$( ExpansionKind::$kind => result.$make().map(Expansion::$kind), )*
|
||||
AstFragmentKind::OptExpr =>
|
||||
result.make_expr().map(Some).map(AstFragment::OptExpr),
|
||||
$( AstFragmentKind::$kind => result.$make().map(AstFragment::$kind), )*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Expansion {
|
||||
impl AstFragment {
|
||||
pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
|
||||
match self {
|
||||
Expansion::OptExpr(expr) => expr,
|
||||
_ => panic!("Expansion::make_* called on the wrong kind of expansion"),
|
||||
AstFragment::OptExpr(expr) => expr,
|
||||
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
||||
}
|
||||
}
|
||||
$( pub fn $make(self) -> $ty {
|
||||
match self {
|
||||
Expansion::$kind(ast) => ast,
|
||||
_ => panic!("Expansion::make_* called on the wrong kind of expansion"),
|
||||
AstFragment::$kind(ast) => ast,
|
||||
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
||||
}
|
||||
} )*
|
||||
|
||||
pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
|
||||
use self::Expansion::*;
|
||||
use self::AstFragment::*;
|
||||
match self {
|
||||
OptExpr(expr) => OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
|
||||
$($( $kind(ast) => $kind(folder.$fold(ast)), )*)*
|
||||
|
|
@ -91,10 +96,10 @@ macro_rules! expansions {
|
|||
|
||||
pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
|
||||
match *self {
|
||||
Expansion::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
|
||||
Expansion::OptExpr(None) => {}
|
||||
$($( Expansion::$kind(ref ast) => visitor.$visit(ast), )*)*
|
||||
$($( Expansion::$kind(ref ast) => for ast in &ast[..] {
|
||||
AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
|
||||
AstFragment::OptExpr(None) => {}
|
||||
$($( AstFragment::$kind(ref ast) => visitor.$visit(ast), )*)*
|
||||
$($( AstFragment::$kind(ref ast) => for ast in &ast[..] {
|
||||
visitor.$visit_elt(ast);
|
||||
}, )*)*
|
||||
}
|
||||
|
|
@ -103,25 +108,25 @@ macro_rules! expansions {
|
|||
|
||||
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
||||
fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||
self.expand(Expansion::OptExpr(Some(expr))).make_opt_expr()
|
||||
self.expand(AstFragment::OptExpr(Some(expr))).make_opt_expr()
|
||||
}
|
||||
$($(fn $fold(&mut self, node: $ty) -> $ty {
|
||||
self.expand(Expansion::$kind(node)).$make()
|
||||
self.expand(AstFragment::$kind(node)).$make()
|
||||
})*)*
|
||||
$($(fn $fold_elt(&mut self, node: $ty_elt) -> $ty {
|
||||
self.expand(Expansion::$kind(SmallVector::one(node))).$make()
|
||||
self.expand(AstFragment::$kind(SmallVector::one(node))).$make()
|
||||
})*)*
|
||||
}
|
||||
|
||||
impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
|
||||
$(fn $make(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$ty> {
|
||||
Some(self.make(ExpansionKind::$kind).$make())
|
||||
Some(self.make(AstFragmentKind::$kind).$make())
|
||||
})*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expansions! {
|
||||
ast_fragments! {
|
||||
Expr: P<ast::Expr> [], "expression", .make_expr, .fold_expr, .visit_expr;
|
||||
Pat: P<ast::Pat> [], "pattern", .make_pat, .fold_pat, .visit_pat;
|
||||
Ty: P<ast::Ty> [], "type", .make_ty, .fold_ty, .visit_ty;
|
||||
|
|
@ -137,29 +142,31 @@ expansions! {
|
|||
"foreign item", .make_foreign_items, lift .fold_foreign_item, lift .visit_foreign_item;
|
||||
}
|
||||
|
||||
impl ExpansionKind {
|
||||
fn dummy(self, span: Span) -> Option<Expansion> {
|
||||
impl AstFragmentKind {
|
||||
fn dummy(self, span: Span) -> Option<AstFragment> {
|
||||
self.make_from(DummyResult::any(span))
|
||||
}
|
||||
|
||||
fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I) -> Expansion {
|
||||
fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
|
||||
-> AstFragment {
|
||||
let mut items = items.into_iter();
|
||||
match self {
|
||||
ExpansionKind::Items =>
|
||||
Expansion::Items(items.map(Annotatable::expect_item).collect()),
|
||||
ExpansionKind::ImplItems =>
|
||||
Expansion::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
|
||||
ExpansionKind::TraitItems =>
|
||||
Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
|
||||
ExpansionKind::ForeignItems =>
|
||||
Expansion::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
|
||||
ExpansionKind::Stmts => Expansion::Stmts(items.map(Annotatable::expect_stmt).collect()),
|
||||
ExpansionKind::Expr => Expansion::Expr(
|
||||
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(
|
||||
items.next().expect("expected exactly one expression").expect_expr()
|
||||
),
|
||||
ExpansionKind::OptExpr =>
|
||||
Expansion::OptExpr(items.next().map(Annotatable::expect_expr)),
|
||||
ExpansionKind::Pat | ExpansionKind::Ty =>
|
||||
AstFragmentKind::OptExpr =>
|
||||
AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)),
|
||||
AstFragmentKind::Pat | AstFragmentKind::Ty =>
|
||||
panic!("patterns and types aren't annotatable"),
|
||||
}
|
||||
}
|
||||
|
|
@ -187,7 +194,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
|
|||
|
||||
pub struct Invocation {
|
||||
pub kind: InvocationKind,
|
||||
expansion_kind: ExpansionKind,
|
||||
fragment_kind: AstFragmentKind,
|
||||
pub expansion_data: ExpansionData,
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +251,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
|
||||
let orig_mod_span = krate.module.inner;
|
||||
|
||||
let krate_item = Expansion::Items(SmallVector::one(P(ast::Item {
|
||||
let krate_item = AstFragment::Items(SmallVector::one(P(ast::Item {
|
||||
attrs: krate.attrs,
|
||||
span: krate.span,
|
||||
node: ast::ItemKind::Mod(krate.module),
|
||||
|
|
@ -273,16 +280,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
krate
|
||||
}
|
||||
|
||||
// Fully expand all the invocations in `expansion`.
|
||||
fn expand(&mut self, expansion: Expansion) -> Expansion {
|
||||
// Fully expand all macro invocations in this AST fragment.
|
||||
fn expand(&mut self, input_fragment: AstFragment) -> AstFragment {
|
||||
let orig_expansion_data = self.cx.current_expansion.clone();
|
||||
self.cx.current_expansion.depth = 0;
|
||||
|
||||
let (expansion, mut invocations) = self.collect_invocations(expansion, &[]);
|
||||
let (fragment_with_placeholders, mut invocations)
|
||||
= self.collect_invocations(input_fragment, &[]);
|
||||
self.resolve_imports();
|
||||
invocations.reverse();
|
||||
|
||||
let mut expansions = Vec::new();
|
||||
let mut expanded_fragments = Vec::new();
|
||||
let mut derives = HashMap::new();
|
||||
let mut undetermined_invocations = Vec::new();
|
||||
let (mut progress, mut force) = (false, !self.monotonic);
|
||||
|
|
@ -314,11 +322,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
|
||||
self.cx.current_expansion.mark = scope;
|
||||
// FIXME(jseyfried): Refactor out the following logic
|
||||
let (expansion, new_invocations) = if let Some(ext) = ext {
|
||||
let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
|
||||
if let Some(ext) = ext {
|
||||
let dummy = invoc.expansion_kind.dummy(invoc.span()).unwrap();
|
||||
let expansion = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
|
||||
self.collect_invocations(expansion, &[])
|
||||
let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
|
||||
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
|
||||
self.collect_invocations(fragment, &[])
|
||||
} else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
|
||||
if !item.derive_allowed() {
|
||||
let attr = attr::find_by_name(item.attrs(), "derive")
|
||||
|
|
@ -359,27 +367,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
};
|
||||
invocations.push(Invocation {
|
||||
kind: InvocationKind::Derive { path: path.clone(), item: item },
|
||||
expansion_kind: invoc.expansion_kind,
|
||||
fragment_kind: invoc.fragment_kind,
|
||||
expansion_data: ExpansionData {
|
||||
mark,
|
||||
..invoc.expansion_data.clone()
|
||||
},
|
||||
});
|
||||
}
|
||||
let expansion = invoc.expansion_kind
|
||||
let fragment = invoc.fragment_kind
|
||||
.expect_from_annotatables(::std::iter::once(item_with_markers));
|
||||
self.collect_invocations(expansion, derives)
|
||||
self.collect_invocations(fragment, derives)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
} else {
|
||||
self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()).unwrap(), &[])
|
||||
self.collect_invocations(invoc.fragment_kind.dummy(invoc.span()).unwrap(), &[])
|
||||
};
|
||||
|
||||
if expansions.len() < depth {
|
||||
expansions.push(Vec::new());
|
||||
if expanded_fragments.len() < depth {
|
||||
expanded_fragments.push(Vec::new());
|
||||
}
|
||||
expansions[depth - 1].push((mark, expansion));
|
||||
expanded_fragments[depth - 1].push((mark, expanded_fragment));
|
||||
if !self.cx.ecfg.single_step {
|
||||
invocations.extend(new_invocations.into_iter().rev());
|
||||
}
|
||||
|
|
@ -388,14 +396,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
self.cx.current_expansion = orig_expansion_data;
|
||||
|
||||
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
|
||||
while let Some(expansions) = expansions.pop() {
|
||||
for (mark, expansion) in expansions.into_iter().rev() {
|
||||
while let Some(expanded_fragments) = expanded_fragments.pop() {
|
||||
for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() {
|
||||
let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
|
||||
placeholder_expander.add(NodeId::placeholder_from_mark(mark), expansion, derives);
|
||||
placeholder_expander.add(NodeId::placeholder_from_mark(mark),
|
||||
expanded_fragment, derives);
|
||||
}
|
||||
}
|
||||
|
||||
expansion.fold_with(&mut placeholder_expander)
|
||||
fragment_with_placeholders.fold_with(&mut placeholder_expander)
|
||||
}
|
||||
|
||||
fn resolve_imports(&mut self) {
|
||||
|
|
@ -406,9 +415,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark])
|
||||
-> (Expansion, Vec<Invocation>) {
|
||||
let result = {
|
||||
fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
|
||||
-> (AstFragment, Vec<Invocation>) {
|
||||
let (fragment_with_placeholders, invocations) = {
|
||||
let mut collector = InvocationCollector {
|
||||
cfg: StripUnconfigured {
|
||||
should_test: self.cx.ecfg.should_test,
|
||||
|
|
@ -419,17 +428,18 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
invocations: Vec::new(),
|
||||
monotonic: self.monotonic,
|
||||
};
|
||||
(expansion.fold_with(&mut collector), collector.invocations)
|
||||
(fragment.fold_with(&mut collector), collector.invocations)
|
||||
};
|
||||
|
||||
if self.monotonic {
|
||||
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
|
||||
let mark = self.cx.current_expansion.mark;
|
||||
self.cx.resolver.visit_expansion(mark, &result.0, derives);
|
||||
self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
|
||||
derives);
|
||||
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
|
||||
}
|
||||
|
||||
result
|
||||
(fragment_with_placeholders, invocations)
|
||||
}
|
||||
|
||||
fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
|
||||
|
|
@ -464,7 +474,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<Expansion> {
|
||||
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
|
||||
let result = match invoc.kind {
|
||||
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
|
||||
InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
|
||||
|
|
@ -491,8 +501,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
fn expand_attr_invoc(&mut self,
|
||||
invoc: Invocation,
|
||||
ext: &SyntaxExtension)
|
||||
-> Option<Expansion> {
|
||||
let Invocation { expansion_kind: kind, .. } = invoc;
|
||||
-> Option<AstFragment> {
|
||||
let (attr, item) = match invoc.kind {
|
||||
InvocationKind::Attr { attr, item, .. } => (attr?, item),
|
||||
_ => unreachable!(),
|
||||
|
|
@ -515,7 +524,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
let meta = attr.parse_meta(self.cx.parse_sess)
|
||||
.map_err(|mut e| { e.emit(); }).ok()?;
|
||||
let item = mac.expand(self.cx, attr.span, &meta, item);
|
||||
Some(kind.expect_from_annotatables(item))
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(item))
|
||||
}
|
||||
MultiDecorator(ref mac) => {
|
||||
let mut items = Vec::new();
|
||||
|
|
@ -523,7 +532,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
.expect("derive meta should already have been parsed");
|
||||
mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
|
||||
items.push(item);
|
||||
Some(kind.expect_from_annotatables(items))
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(items))
|
||||
}
|
||||
AttrProcMacro(ref mac, ..) => {
|
||||
self.gate_proc_macro_attr_item(attr.span, &item);
|
||||
|
|
@ -537,20 +546,21 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
})).into();
|
||||
let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
|
||||
let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
|
||||
let res = self.parse_expansion(tok_result, kind, &attr.path, attr.span);
|
||||
let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
|
||||
&attr.path, attr.span);
|
||||
self.gate_proc_macro_expansion(attr.span, &res);
|
||||
res
|
||||
}
|
||||
ProcMacroDerive(..) | BuiltinDerive(..) => {
|
||||
self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
|
||||
self.cx.trace_macros_diag();
|
||||
kind.dummy(attr.span)
|
||||
invoc.fragment_kind.dummy(attr.span)
|
||||
}
|
||||
_ => {
|
||||
let msg = &format!("macro `{}` may not be used in attributes", attr.path);
|
||||
self.cx.span_err(attr.span, msg);
|
||||
self.cx.trace_macros_diag();
|
||||
kind.dummy(attr.span)
|
||||
invoc.fragment_kind.dummy(attr.span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -598,16 +608,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
);
|
||||
}
|
||||
|
||||
fn gate_proc_macro_expansion(&self, span: Span, expansion: &Option<Expansion>) {
|
||||
fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
|
||||
if self.cx.ecfg.proc_macro_gen() {
|
||||
return
|
||||
}
|
||||
let expansion = match expansion {
|
||||
Some(expansion) => expansion,
|
||||
let fragment = match fragment {
|
||||
Some(fragment) => fragment,
|
||||
None => return,
|
||||
};
|
||||
|
||||
expansion.visit_with(&mut DisallowModules {
|
||||
fragment.visit_with(&mut DisallowModules {
|
||||
span,
|
||||
parse_sess: self.cx.parse_sess,
|
||||
});
|
||||
|
|
@ -642,12 +652,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Expand a macro invocation. Returns the result of expansion.
|
||||
/// Expand a macro invocation. Returns the resulting expanded AST fragment.
|
||||
fn expand_bang_invoc(&mut self,
|
||||
invoc: Invocation,
|
||||
ext: &SyntaxExtension)
|
||||
-> Option<Expansion> {
|
||||
let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
|
||||
-> Option<AstFragment> {
|
||||
let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind);
|
||||
let (mac, ident, span) = match invoc.kind {
|
||||
InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
|
||||
_ => unreachable!(),
|
||||
|
|
@ -790,7 +800,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
});
|
||||
|
||||
let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
|
||||
let result = self.parse_expansion(tok_result, kind, path, span);
|
||||
let result = self.parse_ast_fragment(tok_result, kind, path, span);
|
||||
self.gate_proc_macro_expansion(span, &result);
|
||||
result
|
||||
}
|
||||
|
|
@ -808,17 +818,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn gate_proc_macro_expansion_kind(&self, span: Span, kind: ExpansionKind) {
|
||||
fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
|
||||
let kind = match kind {
|
||||
ExpansionKind::Expr => "expressions",
|
||||
ExpansionKind::OptExpr => "expressions",
|
||||
ExpansionKind::Pat => "patterns",
|
||||
ExpansionKind::Ty => "types",
|
||||
ExpansionKind::Stmts => "statements",
|
||||
ExpansionKind::Items => return,
|
||||
ExpansionKind::TraitItems => return,
|
||||
ExpansionKind::ImplItems => return,
|
||||
ExpansionKind::ForeignItems => return,
|
||||
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,
|
||||
};
|
||||
if self.cx.ecfg.proc_macro_non_items() {
|
||||
return
|
||||
|
|
@ -832,12 +842,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
);
|
||||
}
|
||||
|
||||
/// Expand a derive invocation. Returns the result of expansion.
|
||||
/// Expand a derive invocation. Returns the resulting expanded AST fragment.
|
||||
fn expand_derive_invoc(&mut self,
|
||||
invoc: Invocation,
|
||||
ext: &SyntaxExtension)
|
||||
-> Option<Expansion> {
|
||||
let Invocation { expansion_kind: kind, .. } = invoc;
|
||||
-> Option<AstFragment> {
|
||||
let (path, item) = match invoc.kind {
|
||||
InvocationKind::Derive { path, item } => (path, item),
|
||||
_ => unreachable!(),
|
||||
|
|
@ -876,7 +885,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
node: ast::MetaItemKind::Word,
|
||||
};
|
||||
let items = ext.expand(self.cx, span, &dummy, item);
|
||||
Some(kind.expect_from_annotatables(items))
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(items))
|
||||
}
|
||||
BuiltinDerive(func) => {
|
||||
expn_info.callee.allow_internal_unstable = true;
|
||||
|
|
@ -884,28 +893,28 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
let span = span.with_ctxt(self.cx.backtrace());
|
||||
let mut items = Vec::new();
|
||||
func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
|
||||
Some(kind.expect_from_annotatables(items))
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(items))
|
||||
}
|
||||
_ => {
|
||||
let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
|
||||
self.cx.span_err(span, msg);
|
||||
self.cx.trace_macros_diag();
|
||||
kind.dummy(span)
|
||||
invoc.fragment_kind.dummy(span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_expansion(&mut self,
|
||||
toks: TokenStream,
|
||||
kind: ExpansionKind,
|
||||
path: &Path,
|
||||
span: Span)
|
||||
-> Option<Expansion> {
|
||||
fn parse_ast_fragment(&mut self,
|
||||
toks: TokenStream,
|
||||
kind: AstFragmentKind,
|
||||
path: &Path,
|
||||
span: Span)
|
||||
-> Option<AstFragment> {
|
||||
let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
|
||||
match parser.parse_expansion(kind, false) {
|
||||
Ok(expansion) => {
|
||||
match parser.parse_ast_fragment(kind, false) {
|
||||
Ok(fragment) => {
|
||||
parser.ensure_complete_parse(path, kind.name(), span);
|
||||
Some(expansion)
|
||||
Some(fragment)
|
||||
}
|
||||
Err(mut err) => {
|
||||
err.set_span(span);
|
||||
|
|
@ -918,40 +927,40 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bool)
|
||||
-> PResult<'a, Expansion> {
|
||||
pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warnings: bool)
|
||||
-> PResult<'a, AstFragment> {
|
||||
Ok(match kind {
|
||||
ExpansionKind::Items => {
|
||||
AstFragmentKind::Items => {
|
||||
let mut items = SmallVector::new();
|
||||
while let Some(item) = self.parse_item()? {
|
||||
items.push(item);
|
||||
}
|
||||
Expansion::Items(items)
|
||||
AstFragment::Items(items)
|
||||
}
|
||||
ExpansionKind::TraitItems => {
|
||||
AstFragmentKind::TraitItems => {
|
||||
let mut items = SmallVector::new();
|
||||
while self.token != token::Eof {
|
||||
items.push(self.parse_trait_item(&mut false)?);
|
||||
}
|
||||
Expansion::TraitItems(items)
|
||||
AstFragment::TraitItems(items)
|
||||
}
|
||||
ExpansionKind::ImplItems => {
|
||||
AstFragmentKind::ImplItems => {
|
||||
let mut items = SmallVector::new();
|
||||
while self.token != token::Eof {
|
||||
items.push(self.parse_impl_item(&mut false)?);
|
||||
}
|
||||
Expansion::ImplItems(items)
|
||||
AstFragment::ImplItems(items)
|
||||
}
|
||||
ExpansionKind::ForeignItems => {
|
||||
AstFragmentKind::ForeignItems => {
|
||||
let mut items = SmallVector::new();
|
||||
while self.token != token::Eof {
|
||||
if let Some(item) = self.parse_foreign_item()? {
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
Expansion::ForeignItems(items)
|
||||
AstFragment::ForeignItems(items)
|
||||
}
|
||||
ExpansionKind::Stmts => {
|
||||
AstFragmentKind::Stmts => {
|
||||
let mut stmts = SmallVector::new();
|
||||
while self.token != token::Eof &&
|
||||
// won't make progress on a `}`
|
||||
|
|
@ -960,18 +969,18 @@ impl<'a> Parser<'a> {
|
|||
stmts.push(stmt);
|
||||
}
|
||||
}
|
||||
Expansion::Stmts(stmts)
|
||||
AstFragment::Stmts(stmts)
|
||||
}
|
||||
ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
|
||||
ExpansionKind::OptExpr => {
|
||||
AstFragmentKind::Expr => AstFragment::Expr(self.parse_expr()?),
|
||||
AstFragmentKind::OptExpr => {
|
||||
if self.token != token::Eof {
|
||||
Expansion::OptExpr(Some(self.parse_expr()?))
|
||||
AstFragment::OptExpr(Some(self.parse_expr()?))
|
||||
} else {
|
||||
Expansion::OptExpr(None)
|
||||
AstFragment::OptExpr(None)
|
||||
}
|
||||
},
|
||||
ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
|
||||
ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
|
||||
AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?),
|
||||
AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat()?),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -998,21 +1007,21 @@ struct InvocationCollector<'a, 'b: 'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||
fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
|
||||
fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
|
||||
let mark = Mark::fresh(self.cx.current_expansion.mark);
|
||||
self.invocations.push(Invocation {
|
||||
kind,
|
||||
expansion_kind,
|
||||
fragment_kind,
|
||||
expansion_data: ExpansionData {
|
||||
mark,
|
||||
depth: self.cx.current_expansion.depth + 1,
|
||||
..self.cx.current_expansion.clone()
|
||||
},
|
||||
});
|
||||
placeholder(expansion_kind, NodeId::placeholder_from_mark(mark))
|
||||
placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
|
||||
}
|
||||
|
||||
fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion {
|
||||
fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
|
||||
self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
|
||||
}
|
||||
|
||||
|
|
@ -1020,8 +1029,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
attr: Option<ast::Attribute>,
|
||||
traits: Vec<Path>,
|
||||
item: Annotatable,
|
||||
kind: ExpansionKind)
|
||||
-> Expansion {
|
||||
kind: AstFragmentKind)
|
||||
-> AstFragment {
|
||||
self.collect(kind, InvocationKind::Attr { attr, traits, item })
|
||||
}
|
||||
|
||||
|
|
@ -1119,14 +1128,14 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
// expansion will eat the attribute so it won't error later
|
||||
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
|
||||
|
||||
// ExpansionKind::Expr requires the macro to emit an expression
|
||||
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), ExpansionKind::Expr)
|
||||
.make_expr();
|
||||
// AstFragmentKind::Expr requires the macro to emit an expression
|
||||
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
|
||||
AstFragmentKind::Expr).make_expr();
|
||||
}
|
||||
|
||||
if let ast::ExprKind::Mac(mac) = expr.node {
|
||||
self.check_attributes(&expr.attrs);
|
||||
self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr()
|
||||
self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr()
|
||||
} else {
|
||||
P(noop_fold_expr(expr, self))
|
||||
}
|
||||
|
|
@ -1143,13 +1152,13 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
|
||||
|
||||
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
|
||||
ExpansionKind::OptExpr)
|
||||
AstFragmentKind::OptExpr)
|
||||
.make_opt_expr();
|
||||
}
|
||||
|
||||
if let ast::ExprKind::Mac(mac) = expr.node {
|
||||
self.check_attributes(&expr.attrs);
|
||||
self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr()
|
||||
self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr()
|
||||
} else {
|
||||
Some(P(noop_fold_expr(expr, self)))
|
||||
}
|
||||
|
|
@ -1163,7 +1172,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
}
|
||||
|
||||
pat.and_then(|pat| match pat.node {
|
||||
PatKind::Mac(mac) => self.collect_bang(mac, pat.span, ExpansionKind::Pat).make_pat(),
|
||||
PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
|
@ -1187,7 +1196,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
|
||||
if attr.is_some() || !derives.is_empty() {
|
||||
return self.collect_attr(attr, derives,
|
||||
Annotatable::Stmt(P(stmt_)), ExpansionKind::Stmts)
|
||||
Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts)
|
||||
.make_stmts();
|
||||
}
|
||||
|
||||
|
|
@ -1197,7 +1206,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
if let StmtKind::Mac(mac) = stmt.node {
|
||||
let (mac, style, attrs) = mac.into_inner();
|
||||
self.check_attributes(&attrs);
|
||||
let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts)
|
||||
let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts)
|
||||
.make_stmts();
|
||||
|
||||
// If this is a macro invocation with a semicolon, then apply that
|
||||
|
|
@ -1233,7 +1242,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
let (attr, traits, mut item) = self.classify_item(item);
|
||||
if attr.is_some() || !traits.is_empty() {
|
||||
let item = Annotatable::Item(item);
|
||||
return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items();
|
||||
return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
|
||||
}
|
||||
|
||||
match item.node {
|
||||
|
|
@ -1241,7 +1250,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
self.check_attributes(&item.attrs);
|
||||
item.and_then(|item| match item.node {
|
||||
ItemKind::Mac(mac) => {
|
||||
self.collect(ExpansionKind::Items, InvocationKind::Bang {
|
||||
self.collect(AstFragmentKind::Items, InvocationKind::Bang {
|
||||
mac,
|
||||
ident: Some(item.ident),
|
||||
span: item.span,
|
||||
|
|
@ -1317,7 +1326,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
let (attr, traits, item) = self.classify_item(item);
|
||||
if attr.is_some() || !traits.is_empty() {
|
||||
let item = Annotatable::TraitItem(P(item));
|
||||
return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
|
||||
return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems)
|
||||
.make_trait_items()
|
||||
}
|
||||
|
||||
|
|
@ -1325,7 +1334,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
ast::TraitItemKind::Macro(mac) => {
|
||||
let ast::TraitItem { attrs, span, .. } = item;
|
||||
self.check_attributes(&attrs);
|
||||
self.collect_bang(mac, span, ExpansionKind::TraitItems).make_trait_items()
|
||||
self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
|
||||
}
|
||||
_ => fold::noop_fold_trait_item(item, self),
|
||||
}
|
||||
|
|
@ -1337,7 +1346,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
let (attr, traits, item) = self.classify_item(item);
|
||||
if attr.is_some() || !traits.is_empty() {
|
||||
let item = Annotatable::ImplItem(P(item));
|
||||
return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems)
|
||||
return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems)
|
||||
.make_impl_items();
|
||||
}
|
||||
|
||||
|
|
@ -1345,7 +1354,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
ast::ImplItemKind::Macro(mac) => {
|
||||
let ast::ImplItem { attrs, span, .. } = item;
|
||||
self.check_attributes(&attrs);
|
||||
self.collect_bang(mac, span, ExpansionKind::ImplItems).make_impl_items()
|
||||
self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
|
||||
}
|
||||
_ => fold::noop_fold_impl_item(item, self),
|
||||
}
|
||||
|
|
@ -1358,7 +1367,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
};
|
||||
|
||||
match ty.node {
|
||||
ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, ExpansionKind::Ty).make_ty(),
|
||||
ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -1386,7 +1395,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
}
|
||||
|
||||
let item = Annotatable::ForeignItem(P(foreign_item));
|
||||
return self.collect_attr(attr, traits, item, ExpansionKind::ForeignItems)
|
||||
return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
|
||||
.make_foreign_items();
|
||||
}
|
||||
|
||||
|
|
@ -1398,7 +1407,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
GateIssue::Language, explain);
|
||||
}
|
||||
|
||||
return self.collect_bang(mac, foreign_item.span, ExpansionKind::ForeignItems)
|
||||
return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
|
||||
.make_foreign_items();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
use ast::{self, NodeId};
|
||||
use codemap::{DUMMY_SP, dummy_spanned};
|
||||
use ext::base::ExtCtxt;
|
||||
use ext::expand::{Expansion, ExpansionKind};
|
||||
use ext::expand::{AstFragment, AstFragmentKind};
|
||||
use ext::hygiene::Mark;
|
||||
use tokenstream::TokenStream;
|
||||
use fold::*;
|
||||
|
|
@ -22,7 +22,7 @@ use util::small_vector::SmallVector;
|
|||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
|
||||
pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
|
||||
fn mac_placeholder() -> ast::Mac {
|
||||
dummy_spanned(ast::Mac_ {
|
||||
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
|
||||
|
|
@ -43,35 +43,36 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
|
|||
});
|
||||
|
||||
match kind {
|
||||
ExpansionKind::Expr => Expansion::Expr(expr_placeholder()),
|
||||
ExpansionKind::OptExpr => Expansion::OptExpr(Some(expr_placeholder())),
|
||||
ExpansionKind::Items => Expansion::Items(SmallVector::one(P(ast::Item {
|
||||
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
|
||||
AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
|
||||
AstFragmentKind::Items => AstFragment::Items(SmallVector::one(P(ast::Item {
|
||||
id, span, ident, vis, attrs,
|
||||
node: ast::ItemKind::Mac(mac_placeholder()),
|
||||
tokens: None,
|
||||
}))),
|
||||
ExpansionKind::TraitItems => Expansion::TraitItems(SmallVector::one(ast::TraitItem {
|
||||
AstFragmentKind::TraitItems => AstFragment::TraitItems(SmallVector::one(ast::TraitItem {
|
||||
id, span, ident, attrs, generics,
|
||||
node: ast::TraitItemKind::Macro(mac_placeholder()),
|
||||
tokens: None,
|
||||
})),
|
||||
ExpansionKind::ImplItems => Expansion::ImplItems(SmallVector::one(ast::ImplItem {
|
||||
AstFragmentKind::ImplItems => AstFragment::ImplItems(SmallVector::one(ast::ImplItem {
|
||||
id, span, ident, vis, attrs, generics,
|
||||
node: ast::ImplItemKind::Macro(mac_placeholder()),
|
||||
defaultness: ast::Defaultness::Final,
|
||||
tokens: None,
|
||||
})),
|
||||
ExpansionKind::ForeignItems => Expansion::ForeignItems(SmallVector::one(ast::ForeignItem {
|
||||
id, span, ident, vis, attrs,
|
||||
node: ast::ForeignItemKind::Macro(mac_placeholder()),
|
||||
})),
|
||||
ExpansionKind::Pat => Expansion::Pat(P(ast::Pat {
|
||||
AstFragmentKind::ForeignItems =>
|
||||
AstFragment::ForeignItems(SmallVector::one(ast::ForeignItem {
|
||||
id, span, ident, vis, attrs,
|
||||
node: ast::ForeignItemKind::Macro(mac_placeholder()),
|
||||
})),
|
||||
AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
|
||||
id, span, node: ast::PatKind::Mac(mac_placeholder()),
|
||||
})),
|
||||
ExpansionKind::Ty => Expansion::Ty(P(ast::Ty {
|
||||
AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
|
||||
id, span, node: ast::TyKind::Mac(mac_placeholder()),
|
||||
})),
|
||||
ExpansionKind::Stmts => Expansion::Stmts(SmallVector::one({
|
||||
AstFragmentKind::Stmts => AstFragment::Stmts(SmallVector::one({
|
||||
let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::ThinVec::new()));
|
||||
ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
|
||||
})),
|
||||
|
|
@ -79,7 +80,7 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
|
|||
}
|
||||
|
||||
pub struct PlaceholderExpander<'a, 'b: 'a> {
|
||||
expansions: HashMap<ast::NodeId, Expansion>,
|
||||
expanded_fragments: HashMap<ast::NodeId, AstFragment>,
|
||||
cx: &'a mut ExtCtxt<'b>,
|
||||
monotonic: bool,
|
||||
}
|
||||
|
|
@ -88,27 +89,27 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
|
|||
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
|
||||
PlaceholderExpander {
|
||||
cx,
|
||||
expansions: HashMap::new(),
|
||||
expanded_fragments: HashMap::new(),
|
||||
monotonic,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, id: ast::NodeId, expansion: Expansion, derives: Vec<Mark>) {
|
||||
let mut expansion = expansion.fold_with(self);
|
||||
if let Expansion::Items(mut items) = expansion {
|
||||
pub fn add(&mut self, id: ast::NodeId, fragment: AstFragment, derives: Vec<Mark>) {
|
||||
let mut fragment = fragment.fold_with(self);
|
||||
if let AstFragment::Items(mut items) = fragment {
|
||||
for derive in derives {
|
||||
match self.remove(NodeId::placeholder_from_mark(derive)) {
|
||||
Expansion::Items(derived_items) => items.extend(derived_items),
|
||||
AstFragment::Items(derived_items) => items.extend(derived_items),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
expansion = Expansion::Items(items);
|
||||
fragment = AstFragment::Items(items);
|
||||
}
|
||||
self.expansions.insert(id, expansion);
|
||||
self.expanded_fragments.insert(id, fragment);
|
||||
}
|
||||
|
||||
fn remove(&mut self, id: ast::NodeId) -> Expansion {
|
||||
self.expansions.remove(&id).unwrap()
|
||||
fn remove(&mut self, id: ast::NodeId) -> AstFragment {
|
||||
self.expanded_fragments.remove(&id).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,18 +160,18 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
|
|||
}
|
||||
|
||||
fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
|
||||
let (style, mut expansion) = match stmt.node {
|
||||
let (style, mut stmts) = match stmt.node {
|
||||
ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
|
||||
_ => return noop_fold_stmt(stmt, self),
|
||||
};
|
||||
|
||||
if style == ast::MacStmtStyle::Semicolon {
|
||||
if let Some(stmt) = expansion.pop() {
|
||||
expansion.push(stmt.add_trailing_semicolon());
|
||||
if let Some(stmt) = stmts.pop() {
|
||||
stmts.push(stmt.add_trailing_semicolon());
|
||||
}
|
||||
}
|
||||
|
||||
expansion
|
||||
stmts
|
||||
}
|
||||
|
||||
fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use syntax_pos::{Span, DUMMY_SP};
|
|||
use edition::Edition;
|
||||
use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
|
||||
use ext::base::{NormalTT, TTMacroExpander};
|
||||
use ext::expand::{Expansion, ExpansionKind};
|
||||
use ext::expand::{AstFragment, AstFragmentKind};
|
||||
use ext::tt::macro_parser::{Success, Error, Failure};
|
||||
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
|
||||
use ext::tt::macro_parser::{parse, parse_failure_msg};
|
||||
|
|
@ -43,21 +43,21 @@ pub struct ParserAnyMacro<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ParserAnyMacro<'a> {
|
||||
pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: ExpansionKind) -> Expansion {
|
||||
pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
|
||||
let ParserAnyMacro { site_span, macro_ident, ref mut parser } = *self;
|
||||
let expansion = panictry!(parser.parse_expansion(kind, true));
|
||||
let fragment = panictry!(parser.parse_ast_fragment(kind, true));
|
||||
|
||||
// We allow semicolons at the end of expressions -- e.g. the semicolon in
|
||||
// `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
|
||||
// but `m!()` is allowed in expression positions (c.f. issue #34706).
|
||||
if kind == ExpansionKind::Expr && parser.token == token::Semi {
|
||||
if kind == AstFragmentKind::Expr && parser.token == token::Semi {
|
||||
parser.bump();
|
||||
}
|
||||
|
||||
// Make sure we don't have any tokens left to parse so we don't silently drop anything.
|
||||
let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span));
|
||||
parser.ensure_complete_parse(&path, kind.name(), site_span);
|
||||
expansion
|
||||
fragment
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue