Skip to content

Commit d601de6

Browse files
authored
Unrolled build for #142069
Rollup merge of #142069 - nnethercote:Zmacro-stats, r=petrochenkov Introduce `-Zmacro-stats` 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. r? `@petrochenkov`
2 parents 015c777 + 376cbc3 commit d601de6

File tree

21 files changed

+715
-81
lines changed

21 files changed

+715
-81
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@ pub struct Path {
9797
pub tokens: Option<LazyAttrTokenStream>,
9898
}
9999

100+
// Succeeds if the path has a single segment that is arg-free and matches the given symbol.
100101
impl PartialEq<Symbol> for Path {
101102
#[inline]
102103
fn eq(&self, name: &Symbol) -> bool {
103104
if let [segment] = self.segments.as_ref()
104-
&& segment.args.is_none()
105-
&& segment.ident.name == *name
105+
&& segment == name
106106
{
107107
true
108108
} else {
@@ -111,6 +111,15 @@ impl PartialEq<Symbol> for Path {
111111
}
112112
}
113113

114+
// Succeeds if the path has segments that are arg-free and match the given symbols.
115+
impl PartialEq<&[Symbol]> for Path {
116+
#[inline]
117+
fn eq(&self, names: &&[Symbol]) -> bool {
118+
self.segments.len() == names.len()
119+
&& self.segments.iter().zip(names.iter()).all(|(s1, s2)| s1 == s2)
120+
}
121+
}
122+
114123
impl<CTX: rustc_span::HashStableContext> HashStable<CTX> for Path {
115124
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
116125
self.segments.len().hash_stable(hcx, hasher);
@@ -166,6 +175,14 @@ pub struct PathSegment {
166175
pub args: Option<P<GenericArgs>>,
167176
}
168177

178+
// Succeeds if the path segment is arg-free and matches the given symbol.
179+
impl PartialEq<Symbol> for PathSegment {
180+
#[inline]
181+
fn eq(&self, name: &Symbol) -> bool {
182+
self.args.is_none() && self.ident.name == *name
183+
}
184+
}
185+
169186
impl PathSegment {
170187
pub fn from_ident(ident: Ident) -> Self {
171188
PathSegment { ident, id: DUMMY_NODE_ID, args: None }

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();
Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,37 @@
1-
//! This is an extremely bare-bones alternative to the `thousands` crate on
2-
//! crates.io, for printing large numbers in a readable fashion.
1+
//! This is a bare-bones alternative to the `thousands` crate on crates.io, for
2+
//! printing large numbers in a readable fashion.
33
44
#[cfg(test)]
55
mod tests;
66

7-
// Converts the number to a string, with underscores as the thousands separator.
8-
pub fn format_with_underscores(n: usize) -> String {
9-
let mut s = n.to_string();
10-
let mut i = s.len();
11-
while i > 3 {
7+
fn format_with_underscores(mut s: String) -> String {
8+
// Ignore a leading '-'.
9+
let start = if s.starts_with('-') { 1 } else { 0 };
10+
11+
// Stop after the first non-digit, e.g. '.' or 'e' for floats.
12+
let non_digit = s[start..].find(|c: char| !c.is_digit(10));
13+
let end = if let Some(non_digit) = non_digit { start + non_digit } else { s.len() };
14+
15+
// Insert underscores within `start..end`.
16+
let mut i = end;
17+
while i > start + 3 {
1218
i -= 3;
1319
s.insert(i, '_');
1420
}
1521
s
1622
}
23+
24+
/// Print a `usize` with underscore separators.
25+
pub fn usize_with_underscores(n: usize) -> String {
26+
format_with_underscores(format!("{n}"))
27+
}
28+
29+
/// Print an `isize` with underscore separators.
30+
pub fn isize_with_underscores(n: isize) -> String {
31+
format_with_underscores(format!("{n}"))
32+
}
33+
34+
/// Print an `f64` with precision 1 (one decimal place) and underscore separators.
35+
pub fn f64p1_with_underscores(n: f64) -> String {
36+
format_with_underscores(format!("{n:.1}"))
37+
}

compiler/rustc_data_structures/src/thousands/tests.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,51 @@ use super::*;
22

33
#[test]
44
fn test_format_with_underscores() {
5-
assert_eq!("0", format_with_underscores(0));
6-
assert_eq!("1", format_with_underscores(1));
7-
assert_eq!("99", format_with_underscores(99));
8-
assert_eq!("345", format_with_underscores(345));
9-
assert_eq!("1_000", format_with_underscores(1_000));
10-
assert_eq!("12_001", format_with_underscores(12_001));
11-
assert_eq!("999_999", format_with_underscores(999_999));
12-
assert_eq!("1_000_000", format_with_underscores(1_000_000));
13-
assert_eq!("12_345_678", format_with_underscores(12_345_678));
5+
assert_eq!("", format_with_underscores("".to_string()));
6+
assert_eq!("0", format_with_underscores("0".to_string()));
7+
assert_eq!("12_345.67e14", format_with_underscores("12345.67e14".to_string()));
8+
assert_eq!("-1_234.5678e10", format_with_underscores("-1234.5678e10".to_string()));
9+
assert_eq!("------", format_with_underscores("------".to_string()));
10+
assert_eq!("abcdefgh", format_with_underscores("abcdefgh".to_string()));
11+
assert_eq!("-1b", format_with_underscores("-1b".to_string()));
12+
assert_eq!("-3_456xyz", format_with_underscores("-3456xyz".to_string()));
13+
}
14+
15+
#[test]
16+
fn test_usize_with_underscores() {
17+
assert_eq!("0", usize_with_underscores(0));
18+
assert_eq!("1", usize_with_underscores(1));
19+
assert_eq!("99", usize_with_underscores(99));
20+
assert_eq!("345", usize_with_underscores(345));
21+
assert_eq!("1_000", usize_with_underscores(1_000));
22+
assert_eq!("12_001", usize_with_underscores(12_001));
23+
assert_eq!("999_999", usize_with_underscores(999_999));
24+
assert_eq!("1_000_000", usize_with_underscores(1_000_000));
25+
assert_eq!("12_345_678", usize_with_underscores(12_345_678));
26+
}
27+
28+
#[test]
29+
fn test_isize_with_underscores() {
30+
assert_eq!("0", isize_with_underscores(0));
31+
assert_eq!("-1", isize_with_underscores(-1));
32+
assert_eq!("99", isize_with_underscores(99));
33+
assert_eq!("345", isize_with_underscores(345));
34+
assert_eq!("-1_000", isize_with_underscores(-1_000));
35+
assert_eq!("12_001", isize_with_underscores(12_001));
36+
assert_eq!("-999_999", isize_with_underscores(-999_999));
37+
assert_eq!("1_000_000", isize_with_underscores(1_000_000));
38+
assert_eq!("-12_345_678", isize_with_underscores(-12_345_678));
39+
}
40+
41+
#[test]
42+
fn test_f64p1_with_underscores() {
43+
assert_eq!("0.0", f64p1_with_underscores(0f64));
44+
assert_eq!("0.0", f64p1_with_underscores(0.00000001));
45+
assert_eq!("-0.0", f64p1_with_underscores(-0.00000001));
46+
assert_eq!("1.0", f64p1_with_underscores(0.9999999));
47+
assert_eq!("-1.0", f64p1_with_underscores(-0.9999999));
48+
assert_eq!("345.5", f64p1_with_underscores(345.4999999));
49+
assert_eq!("-100_000.0", f64p1_with_underscores(-100_000f64));
50+
assert_eq!("123_456_789.1", f64p1_with_underscores(123456789.123456789));
51+
assert_eq!("-123_456_789.1", f64p1_with_underscores(-123456789.123456789));
1452
}

compiler/rustc_expand/src/base.rs

Lines changed: 5 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.
@@ -1189,6 +1190,8 @@ pub struct ExtCtxt<'a> {
11891190
/// in the AST, but insert it here so that we know
11901191
/// not to expand it again.
11911192
pub(super) expanded_inert_attrs: MarkedAttrs,
1193+
/// `-Zmacro-stats` data.
1194+
pub macro_stats: FxHashMap<(Symbol, MacroKind), crate::stats::MacroStat>, // njn: quals
11921195
}
11931196

11941197
impl<'a> ExtCtxt<'a> {
@@ -1218,6 +1221,7 @@ impl<'a> ExtCtxt<'a> {
12181221
expansions: FxIndexMap::default(),
12191222
expanded_inert_attrs: MarkedAttrs::new(),
12201223
buffered_early_lint: vec![],
1224+
macro_stats: Default::default(),
12211225
}
12221226
}
12231227

0 commit comments

Comments
 (0)