Skip to content

Commit 1069453

Browse files
committed
Introduce -Zmacro-stats.
It collects data about macro expansions and prints them in a table after expansion finishes. It's very useful for detecting macro bloat, especially for proc macros. Details: - It measures code snippets by pretty-printing them and then measuring lines and bytes. This required a bunch of additional pretty-printing plumbing, in `rustc_ast_pretty` and `rustc_expand`. - The measurement is done in `MacroExpander::expand_invoc`. - The measurements are stored in `ExtCtxt::macro_stats`.
1 parent 68f349c commit 1069453

File tree

14 files changed

+608
-52
lines changed

14 files changed

+608
-52
lines changed

compiler/rustc_ast_pretty/src/pprust/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ pub fn item_to_string(i: &ast::Item) -> String {
5353
State::new().item_to_string(i)
5454
}
5555

56+
pub fn assoc_item_to_string(i: &ast::AssocItem) -> String {
57+
State::new().assoc_item_to_string(i)
58+
}
59+
60+
pub fn foreign_item_to_string(i: &ast::ForeignItem) -> String {
61+
State::new().foreign_item_to_string(i)
62+
}
63+
64+
pub fn stmt_to_string(s: &ast::Stmt) -> String {
65+
State::new().stmt_to_string(s)
66+
}
67+
5668
pub fn path_to_string(p: &ast::Path) -> String {
5769
State::new().path_to_string(p)
5870
}

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
10631063
Self::to_string(|s| s.print_item(i))
10641064
}
10651065

1066+
fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String {
1067+
Self::to_string(|s| s.print_assoc_item(i))
1068+
}
1069+
1070+
fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String {
1071+
Self::to_string(|s| s.print_foreign_item(i))
1072+
}
1073+
10661074
fn path_to_string(&self, p: &ast::Path) -> String {
10671075
Self::to_string(|s| s.print_path(p, false, 0))
10681076
}

compiler/rustc_ast_pretty/src/pprust/state/item.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl<'a> State<'a> {
2828
}
2929
}
3030

31-
fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
31+
pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
3232
let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
3333
self.ann.pre(self, AnnNode::SubItem(id));
3434
self.hardbreak_if_not_bol();
@@ -548,7 +548,7 @@ impl<'a> State<'a> {
548548
}
549549
}
550550

551-
fn print_assoc_item(&mut self, item: &ast::AssocItem) {
551+
pub(crate) fn print_assoc_item(&mut self, item: &ast::AssocItem) {
552552
let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
553553
self.ann.pre(self, AnnNode::SubItem(id));
554554
self.hardbreak_if_not_bol();

compiler/rustc_expand/src/base.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_ast::tokenstream::TokenStream;
1212
use rustc_ast::visit::{AssocCtxt, Visitor};
1313
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
1414
use rustc_attr_data_structures::{AttributeKind, Deprecation, Stability, find_attr};
15-
use rustc_data_structures::fx::FxIndexMap;
15+
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
1616
use rustc_data_structures::sync;
1717
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult};
1818
use rustc_feature::Features;
@@ -727,6 +727,7 @@ pub enum SyntaxExtensionKind {
727727
/// A trivial attribute "macro" that does nothing,
728728
/// only keeps the attribute and marks it as inert,
729729
/// thus making it ineligible for further expansion.
730+
/// E.g. `#[default]`, `#[rustfmt::skip]`.
730731
NonMacroAttr,
731732

732733
/// A token-based derive macro.
@@ -1166,6 +1167,22 @@ pub struct ExpansionData {
11661167
pub is_trailing_mac: bool,
11671168
}
11681169

1170+
#[derive(Default)]
1171+
pub struct MacroStat {
1172+
/// Number of invocations of the macro.
1173+
pub count: usize,
1174+
1175+
/// Net increase in number of lines of code (when pretty-printed), i.e.
1176+
/// `lines(output) - lines(invocation)`. Can be negative because a macro
1177+
/// output may be smaller than the invocation.
1178+
pub lines: isize,
1179+
1180+
/// Net increase in number of lines of code (when pretty-printed), i.e.
1181+
/// `bytes(output) - bytes(invocation)`. Can be negative because a macro
1182+
/// output may be smaller than the invocation.
1183+
pub bytes: isize,
1184+
}
1185+
11691186
/// One of these is made during expansion and incrementally updated as we go;
11701187
/// when a macro expansion occurs, the resulting nodes have the `backtrace()
11711188
/// -> expn_data` of their expansion context stored into their span.
@@ -1189,6 +1206,8 @@ pub struct ExtCtxt<'a> {
11891206
/// in the AST, but insert it here so that we know
11901207
/// not to expand it again.
11911208
pub(super) expanded_inert_attrs: MarkedAttrs,
1209+
/// `-Zmacro-stats` data.
1210+
pub macro_stats: FxHashMap<(String, MacroKind), MacroStat>,
11921211
}
11931212

11941213
impl<'a> ExtCtxt<'a> {
@@ -1218,6 +1237,7 @@ impl<'a> ExtCtxt<'a> {
12181237
expansions: FxIndexMap::default(),
12191238
expanded_inert_attrs: MarkedAttrs::new(),
12201239
buffered_early_lint: vec![],
1240+
macro_stats: Default::default(),
12211241
}
12221242
}
12231243

0 commit comments

Comments
 (0)