Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,10 @@ pub trait MacResult {
None
}

fn make_method_receiver_expr(self: Box<Self>) -> Option<Box<ast::Expr>> {
self.make_expr()
}

/// Creates zero or more items.
fn make_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
None
Expand Down
77 changes: 24 additions & 53 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,11 @@ macro_rules! ast_fragments {
$($Kind:ident($AstTy:ty) {
$kind_name:expr;
$(one
fn $mut_visit_ast:ident;
fn $visit_ast:ident;
fn $ast_to_string:path;
)?
$(many
fn $flat_map_ast_elt:ident;
fn $visit_ast_elt:ident($($args:tt)*);
fn $ast_to_string_elt:path;
)?
fn $make_ast:ident;
})*
Expand All @@ -71,23 +68,20 @@ macro_rules! ast_fragments {
/// Can also serve as an input and intermediate result for macro expansion operations.
pub enum AstFragment {
OptExpr(Option<Box<ast::Expr>>),
MethodReceiverExpr(Box<ast::Expr>),
$($Kind($AstTy),)*
}

/// "Discriminant" of an AST fragment.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum AstFragmentKind {
OptExpr,
MethodReceiverExpr,
$($Kind,)*
}

impl AstFragmentKind {
pub fn name(self) -> &'static str {
match self {
AstFragmentKind::OptExpr => "expression",
AstFragmentKind::MethodReceiverExpr => "expression",
$(AstFragmentKind::$Kind => $kind_name,)*
}
}
Expand All @@ -96,8 +90,6 @@ macro_rules! ast_fragments {
match self {
AstFragmentKind::OptExpr =>
result.make_expr().map(Some).map(AstFragment::OptExpr),
AstFragmentKind::MethodReceiverExpr =>
result.make_expr().map(AstFragment::MethodReceiverExpr),
$(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
}
}
Expand All @@ -120,21 +112,14 @@ macro_rules! ast_fragments {
pub(crate) fn make_opt_expr(self) -> Option<Box<ast::Expr>> {
match self {
AstFragment::OptExpr(expr) => expr,
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
}
}

pub(crate) fn make_method_receiver_expr(self) -> Box<ast::Expr> {
match self {
AstFragment::MethodReceiverExpr(expr) => expr,
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
_ => panic!("AstFragment::make_opt_expr called on the wrong kind of fragment"),
}
}

$(pub fn $make_ast(self) -> $AstTy {
match self {
AstFragment::$Kind(ast) => ast,
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
_ => panic!("AstFragment::{} called on the wrong kind of fragment", stringify!($make_ast)),
}
})*

Expand All @@ -149,8 +134,7 @@ macro_rules! ast_fragments {
*opt_expr = vis.filter_map_expr(expr)
}
}
AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
$($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
$($(AstFragment::$Kind(ast) => vis.$visit_ast(ast),)?)*
$($(AstFragment::$Kind(ast) =>
ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)*
}
Expand All @@ -160,27 +144,11 @@ macro_rules! ast_fragments {
match self {
AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)),
AstFragment::OptExpr(None) => {}
AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)),
$($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)*
$($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)*
}
V::Result::output()
}

pub(crate) fn to_string(&self) -> String {
match self {
AstFragment::OptExpr(Some(expr)) => pprust::expr_to_string(expr),
AstFragment::OptExpr(None) => unreachable!(),
AstFragment::MethodReceiverExpr(expr) => pprust::expr_to_string(expr),
$($(AstFragment::$Kind(ast) => $ast_to_string(ast),)?)*
$($(
AstFragment::$Kind(ast) => {
// The closure unwraps a `P` if present, or does nothing otherwise.
elems_to_string(&*ast, |ast| $ast_to_string_elt(&*ast))
}
)?)*
}
}
}

impl<'a, 'b> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a, 'b> {
Expand All @@ -195,94 +163,97 @@ macro_rules! ast_fragments {
ast_fragments! {
Expr(Box<ast::Expr>) {
"expression";
one fn visit_expr; fn visit_expr; fn pprust::expr_to_string;
one fn visit_expr;
fn make_expr;
}
MethodReceiverExpr(Box<ast::Expr>) {
"expression";
one fn visit_method_receiver_expr;
fn make_method_receiver_expr;
}
Pat(Box<ast::Pat>) {
"pattern";
one fn visit_pat; fn visit_pat; fn pprust::pat_to_string;
one fn visit_pat;
fn make_pat;
}
Ty(Box<ast::Ty>) {
"type";
one fn visit_ty; fn visit_ty; fn pprust::ty_to_string;
one fn visit_ty;
fn make_ty;
}
Stmts(SmallVec<[ast::Stmt; 1]>) {
"statement";
many fn flat_map_stmt; fn visit_stmt(); fn pprust::stmt_to_string;
many fn flat_map_stmt; fn visit_stmt();
fn make_stmts;
}
Items(SmallVec<[Box<ast::Item>; 1]>) {
"item";
many fn flat_map_item; fn visit_item(); fn pprust::item_to_string;
many fn flat_map_item; fn visit_item();
fn make_items;
}
TraitItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
"trait item";
many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Trait);
fn pprust::assoc_item_to_string;
fn make_trait_items;
}
ImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
"impl item";
many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: false });
fn pprust::assoc_item_to_string;
fn make_impl_items;
}
TraitImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
"impl item";
many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: true });
fn pprust::assoc_item_to_string;
fn make_trait_impl_items;
}
ForeignItems(SmallVec<[Box<ast::ForeignItem>; 1]>) {
"foreign item";
many fn flat_map_foreign_item; fn visit_foreign_item(); fn pprust::foreign_item_to_string;
many fn flat_map_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 unreachable_to_string;
many fn flat_map_arm; fn visit_arm();
fn make_arms;
}
ExprFields(SmallVec<[ast::ExprField; 1]>) {
"field expression";
many fn flat_map_expr_field; fn visit_expr_field(); fn unreachable_to_string;
many fn flat_map_expr_field; fn visit_expr_field();
fn make_expr_fields;
}
PatFields(SmallVec<[ast::PatField; 1]>) {
"field pattern";
many fn flat_map_pat_field; fn visit_pat_field(); fn unreachable_to_string;
many fn flat_map_pat_field; fn visit_pat_field();
fn make_pat_fields;
}
GenericParams(SmallVec<[ast::GenericParam; 1]>) {
"generic parameter";
many fn flat_map_generic_param; fn visit_generic_param(); fn unreachable_to_string;
many fn flat_map_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 unreachable_to_string;
many fn flat_map_param; fn visit_param();
fn make_params;
}
FieldDefs(SmallVec<[ast::FieldDef; 1]>) {
"field";
many fn flat_map_field_def; fn visit_field_def(); fn unreachable_to_string;
many fn flat_map_field_def; fn visit_field_def();
fn make_field_defs;
}
Variants(SmallVec<[ast::Variant; 1]>) {
"variant"; many fn flat_map_variant; fn visit_variant(); fn unreachable_to_string;
"variant";
many fn flat_map_variant; fn visit_variant();
fn make_variants;
}
WherePredicates(SmallVec<[ast::WherePredicate; 1]>) {
"where predicate";
many fn flat_map_where_predicate; fn visit_where_predicate(); fn unreachable_to_string;
many fn flat_map_where_predicate; fn visit_where_predicate();
fn make_where_predicates;
}
Crate(ast::Crate) {
"crate";
one fn visit_crate; fn visit_crate; fn unreachable_to_string;
one fn visit_crate;
fn make_crate;
}
}
Expand Down
34 changes: 30 additions & 4 deletions compiler/rustc_expand/src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,34 @@ pub(crate) fn elems_to_string<T>(elems: &SmallVec<[T; 1]>, f: impl Fn(&T) -> Str
s
}

pub(crate) fn unreachable_to_string<T>(_: &T) -> String {
unreachable!()
fn fragment_to_string(fragment: &AstFragment) -> String {
match fragment {
AstFragment::OptExpr(Some(expr))
| AstFragment::MethodReceiverExpr(expr)
| AstFragment::Expr(expr) => pprust::expr_to_string(expr),
AstFragment::Pat(ast) => pprust::pat_to_string(ast),
AstFragment::Ty(ast) => pprust::ty_to_string(ast),
AstFragment::Stmts(ast) => elems_to_string(ast, pprust::stmt_to_string),
AstFragment::Items(ast) => elems_to_string(ast, |ast| pprust::item_to_string(ast)),
AstFragment::TraitItems(ast)
| AstFragment::ImplItems(ast)
| AstFragment::TraitImplItems(ast) => {
elems_to_string(ast, |ast| pprust::assoc_item_to_string(ast))
}
AstFragment::ForeignItems(ast) => {
elems_to_string(ast, |ast| pprust::foreign_item_to_string(ast))
}
AstFragment::OptExpr(None)
| AstFragment::Crate(_)
| AstFragment::Arms(_)
| AstFragment::ExprFields(_)
| AstFragment::PatFields(_)
| AstFragment::GenericParams(_)
| AstFragment::Params(_)
| AstFragment::FieldDefs(_)
| AstFragment::Variants(_)
| AstFragment::WherePredicates(_) => unreachable!(),
}
}

pub(crate) fn update_bang_macro_stats(
Expand Down Expand Up @@ -98,7 +124,7 @@ pub(crate) fn update_attr_macro_stats(
let input = format!(
"{}\n{}",
pprust::attribute_to_string(attr),
fragment_kind.expect_from_annotatables(iter::once(item)).to_string(),
fragment_to_string(&fragment_kind.expect_from_annotatables(iter::once(item))),
);
update_macro_stats(ecx, MacroKind::Attr, fragment_kind, span, path, &input, fragment);
}
Expand Down Expand Up @@ -129,7 +155,7 @@ pub(crate) fn update_macro_stats(
// Measure the size of the output by pretty-printing it and counting
// the lines and bytes.
let name = Symbol::intern(&pprust::path_to_string(path));
let output = fragment.to_string();
let output = fragment_to_string(fragment);
let num_lines = output.trim_end().split('\n').count();
let num_bytes = output.len();

Expand Down
Loading