use crate::placeholders::{placeholder, PlaceholderExpander};
use crate::proc_macro::collect_derives;
+use rustc_ast_pretty::pprust;
+use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::Features;
use rustc_parse::parser::Parser;
use rustc_parse::validate_attr;
use rustc_parse::DirectoryOwnership;
+use rustc_session::parse::{feature_err, ParseSess};
use rustc_span::source_map::respan;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{FileName, Span, DUMMY_SP};
use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
use syntax::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
-use syntax::attr::{self, is_builtin_attr, HasAttrs};
use syntax::mut_visit::*;
-use syntax::print::pprust;
use syntax::ptr::P;
-use syntax::sess::{feature_err, ParseSess};
use syntax::token;
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::util::map_in_place::MapInPlace;
-use syntax::visit::{self, Visitor};
+use syntax::visit::{self, AssocCtxt, Visitor};
use smallvec::{smallvec, SmallVec};
use std::io::ErrorKind;
$($Kind:ident($AstTy:ty) {
$kind_name:expr;
$(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
- $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident;)?
+ $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
fn $make_ast:ident;
})*
) => {
AstFragment::OptExpr(None) => {}
$($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
$($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
- visitor.$visit_ast_elt(ast_elt);
+ visitor.$visit_ast_elt(ast_elt, $($args)*);
})?)*
}
}
Pat(P<ast::Pat>) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; }
Ty(P<ast::Ty>) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; }
Stmts(SmallVec<[ast::Stmt; 1]>) {
- "statement"; many fn flat_map_stmt; fn visit_stmt; fn make_stmts;
+ "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts;
}
Items(SmallVec<[P<ast::Item>; 1]>) {
- "item"; many fn flat_map_item; fn visit_item; fn make_items;
+ "item"; many fn flat_map_item; fn visit_item(); fn make_items;
}
- TraitItems(SmallVec<[ast::AssocItem; 1]>) {
- "trait item"; many fn flat_map_trait_item; fn visit_trait_item; fn make_trait_items;
+ TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
+ "trait item";
+ many fn flat_map_trait_item;
+ fn visit_assoc_item(AssocCtxt::Trait);
+ fn make_trait_items;
}
- ImplItems(SmallVec<[ast::AssocItem; 1]>) {
- "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items;
+ ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
+ "impl item";
+ many fn flat_map_impl_item;
+ fn visit_assoc_item(AssocCtxt::Impl);
+ fn make_impl_items;
}
- ForeignItems(SmallVec<[ast::ForeignItem; 1]>) {
+ ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
"foreign item";
many fn flat_map_foreign_item;
- fn visit_foreign_item;
+ fn visit_foreign_item();
fn make_foreign_items;
}
Arms(SmallVec<[ast::Arm; 1]>) {
- "match arm"; many fn flat_map_arm; fn visit_arm; fn make_arms;
+ "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms;
}
Fields(SmallVec<[ast::Field; 1]>) {
- "field expression"; many fn flat_map_field; fn visit_field; fn make_fields;
+ "field expression"; many fn flat_map_field; fn visit_field(); fn make_fields;
}
FieldPats(SmallVec<[ast::FieldPat; 1]>) {
"field pattern";
many fn flat_map_field_pattern;
- fn visit_field_pattern;
+ fn visit_field_pattern();
fn make_field_patterns;
}
GenericParams(SmallVec<[ast::GenericParam; 1]>) {
"generic parameter";
many fn flat_map_generic_param;
- fn visit_generic_param;
+ fn visit_generic_param();
fn make_generic_params;
}
Params(SmallVec<[ast::Param; 1]>) {
- "function parameter"; many fn flat_map_param; fn visit_param; fn make_params;
+ "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params;
}
StructFields(SmallVec<[ast::StructField; 1]>) {
"field";
many fn flat_map_struct_field;
- fn visit_struct_field;
+ fn visit_struct_field();
fn make_struct_fields;
}
Variants(SmallVec<[ast::Variant; 1]>) {
- "variant"; many fn flat_map_variant; fn visit_variant; fn make_variants;
+ "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
}
}
krate.attrs = vec![];
krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
}
- _ => unreachable!(),
+ Some(ast::Item { span, kind, .. }) => {
+ krate.attrs = vec![];
+ krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
+ self.cx.span_err(
+ span,
+ &format!(
+ "expected crate top-level item to be a module after macro expansion, found a {}",
+ kind.descriptive_variant()
+ ),
+ );
+ }
};
self.cx.trace_macros_diag();
krate
// we know that fold result vector will contain exactly one element
match item {
Annotatable::Item(item) => Annotatable::Item(cfg.flat_map_item(item).pop().unwrap()),
- Annotatable::TraitItem(item) => Annotatable::TraitItem(
- item.map(|item| cfg.flat_map_trait_item(item).pop().unwrap()),
- ),
+ Annotatable::TraitItem(item) => {
+ Annotatable::TraitItem(cfg.flat_map_trait_item(item).pop().unwrap())
+ }
Annotatable::ImplItem(item) => {
- Annotatable::ImplItem(item.map(|item| cfg.flat_map_impl_item(item).pop().unwrap()))
+ Annotatable::ImplItem(cfg.flat_map_impl_item(item).pop().unwrap())
+ }
+ Annotatable::ForeignItem(item) => {
+ Annotatable::ForeignItem(cfg.flat_map_foreign_item(item).pop().unwrap())
}
- Annotatable::ForeignItem(item) => Annotatable::ForeignItem(
- item.map(|item| cfg.flat_map_foreign_item(item).pop().unwrap()),
- ),
Annotatable::Stmt(stmt) => {
Annotatable::Stmt(stmt.map(|stmt| cfg.flat_map_stmt(stmt).pop().unwrap()))
}
&format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
);
err.help(&format!(
- "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
- suggested_limit
+ "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
+ suggested_limit, self.cx.ecfg.crate_name,
));
err.emit();
self.cx.trace_macros_diag();
let item_tok = TokenTree::token(
token::Interpolated(Lrc::new(match item {
Annotatable::Item(item) => token::NtItem(item),
- Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
- Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
- Annotatable::ForeignItem(item) => {
- token::NtForeignItem(item.into_inner())
- }
+ Annotatable::TraitItem(item) => token::NtTraitItem(item),
+ Annotatable::ImplItem(item) => token::NtImplItem(item),
+ Annotatable::ForeignItem(item) => token::NtForeignItem(item),
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
Annotatable::Expr(expr) => token::NtExpr(expr),
Annotatable::Arm(..)
AstFragmentKind::ForeignItems => {
let mut items = SmallVec::new();
while this.token != token::Eof {
- items.push(this.parse_foreign_item(DUMMY_SP)?);
+ items.push(this.parse_foreign_item()?);
}
AstFragment::ForeignItems(items)
}
}
}
- fn flat_map_trait_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+ fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
let mut item = configure!(self, item);
let (attr, traits, after_derive) = self.classify_item(&mut item);
.collect_attr(
attr,
traits,
- Annotatable::TraitItem(P(item)),
+ Annotatable::TraitItem(item),
AstFragmentKind::TraitItems,
after_derive,
)
}
match item.kind {
- ast::AssocItemKind::Macro(mac) => {
- let ast::AssocItem { attrs, span, .. } = item;
- self.check_attributes(&attrs);
- self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
+ ast::AssocItemKind::Macro(..) => {
+ self.check_attributes(&item.attrs);
+ item.and_then(|item| match item.kind {
+ ast::AssocItemKind::Macro(mac) => self
+ .collect_bang(mac, item.span, AstFragmentKind::TraitItems)
+ .make_trait_items(),
+ _ => unreachable!(),
+ })
}
_ => noop_flat_map_assoc_item(item, self),
}
}
- fn flat_map_impl_item(&mut self, item: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> {
+ fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
let mut item = configure!(self, item);
let (attr, traits, after_derive) = self.classify_item(&mut item);
.collect_attr(
attr,
traits,
- Annotatable::ImplItem(P(item)),
+ Annotatable::ImplItem(item),
AstFragmentKind::ImplItems,
after_derive,
)
}
match item.kind {
- ast::AssocItemKind::Macro(mac) => {
- let ast::AssocItem { attrs, span, .. } = item;
- self.check_attributes(&attrs);
- self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
+ ast::AssocItemKind::Macro(..) => {
+ self.check_attributes(&item.attrs);
+ item.and_then(|item| match item.kind {
+ ast::AssocItemKind::Macro(mac) => self
+ .collect_bang(mac, item.span, AstFragmentKind::ImplItems)
+ .make_impl_items(),
+ _ => unreachable!(),
+ })
}
_ => noop_flat_map_assoc_item(item, self),
}
fn flat_map_foreign_item(
&mut self,
- mut foreign_item: ast::ForeignItem,
- ) -> SmallVec<[ast::ForeignItem; 1]> {
+ mut foreign_item: P<ast::ForeignItem>,
+ ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
let (attr, traits, after_derive) = self.classify_item(&mut foreign_item);
if attr.is_some() || !traits.is_empty() {
.collect_attr(
attr,
traits,
- Annotatable::ForeignItem(P(foreign_item)),
+ Annotatable::ForeignItem(foreign_item),
AstFragmentKind::ForeignItems,
after_derive,
)
.make_foreign_items();
}
- if let ast::ForeignItemKind::Macro(mac) = foreign_item.kind {
- self.check_attributes(&foreign_item.attrs);
- return self
- .collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
- .make_foreign_items();
+ match foreign_item.kind {
+ ast::ForeignItemKind::Macro(..) => {
+ self.check_attributes(&foreign_item.attrs);
+ foreign_item.and_then(|item| match item.kind {
+ ast::ForeignItemKind::Macro(mac) => self
+ .collect_bang(mac, item.span, AstFragmentKind::ForeignItems)
+ .make_foreign_items(),
+ _ => unreachable!(),
+ })
+ }
+ _ => noop_flat_map_foreign_item(foreign_item, self),
}
-
- noop_flat_map_foreign_item(foreign_item, self)
}
fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
}
let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
- *at = attr::Attribute {
+ *at = ast::Attribute {
kind: ast::AttrKind::Normal(AttrItem {
path: meta.path,
args: meta.kind.mac_args(meta.span),