1
Fork 0

Overhaul to_readable_str.

It's a function that prints numbers with underscores inserted for
readability (e.g. "1_234_567"), used by `-Zmeta-stats` and
`-Zinput-stats`. It's the only thing in `rustc_middle::util::common`,
which is a bizarre location for it.

This commit:
- moves it to `rustc_data_structures`, a more logical crate for it;
- puts it in a module `thousands`, like the similar crates.io crate;
- renames it `format_with_underscores`, which is a clearer name;
- rewrites it to be more concise;
- slightly improves the testing.
This commit is contained in:
Nicholas Nethercote 2025-01-31 10:58:33 +11:00
parent 4ced93ed35
commit 0c47091006
8 changed files with 42 additions and 48 deletions

View file

@ -76,6 +76,7 @@ pub mod sync;
pub mod tagged_ptr; pub mod tagged_ptr;
pub mod temp_dir; pub mod temp_dir;
pub mod thinvec; pub mod thinvec;
pub mod thousands;
pub mod transitive_relation; pub mod transitive_relation;
pub mod unhash; pub mod unhash;
pub mod unord; pub mod unord;

View file

@ -0,0 +1,16 @@
//! This is an extremely bare-bones alternative to the `thousands` crate on
//! crates.io, for printing large numbers in a readable fashion.
#[cfg(test)]
mod tests;
// Converts the number to a string, with underscores as the thousands separator.
pub fn format_with_underscores(n: usize) -> String {
let mut s = n.to_string();
let mut i = s.len();
while i > 3 {
i -= 3;
s.insert(i, '_');
}
s
}

View file

@ -0,0 +1,14 @@
use super::*;
#[test]
fn test_format_with_underscores() {
assert_eq!("0", format_with_underscores(0));
assert_eq!("1", format_with_underscores(1));
assert_eq!("99", format_with_underscores(99));
assert_eq!("345", format_with_underscores(345));
assert_eq!("1_000", format_with_underscores(1_000));
assert_eq!("12_001", format_with_underscores(12_001));
assert_eq!("999_999", format_with_underscores(999_999));
assert_eq!("1_000_000", format_with_underscores(1_000_000));
assert_eq!("12_345_678", format_with_underscores(12_345_678));
}

View file

@ -9,6 +9,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::memmap::{Mmap, MmapMut}; use rustc_data_structures::memmap::{Mmap, MmapMut};
use rustc_data_structures::sync::{Lrc, join, par_for_each_in}; use rustc_data_structures::sync::{Lrc, join, par_for_each_in};
use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_data_structures::thousands::format_with_underscores;
use rustc_feature::Features; use rustc_feature::Features;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
@ -22,7 +23,6 @@ use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::fast_reject::{self, TreatParams}; use rustc_middle::ty::fast_reject::{self, TreatParams};
use rustc_middle::ty::{AssocItemContainer, SymbolName}; use rustc_middle::ty::{AssocItemContainer, SymbolName};
use rustc_middle::util::common::to_readable_str;
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque};
use rustc_session::config::{CrateType, OptLevel}; use rustc_session::config::{CrateType, OptLevel};
@ -782,7 +782,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
"{} {:<23}{:>10} ({:4.1}%)", "{} {:<23}{:>10} ({:4.1}%)",
prefix, prefix,
label, label,
to_readable_str(size), format_with_underscores(size),
perc(size) perc(size)
); );
} }
@ -791,7 +791,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
"{} {:<23}{:>10} (of which {:.1}% are zero bytes)", "{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
prefix, prefix,
"Total", "Total",
to_readable_str(total_bytes), format_with_underscores(total_bytes),
perc(zero_bytes) perc(zero_bytes)
); );
eprintln!("{prefix}"); eprintln!("{prefix}");

View file

@ -1,22 +0,0 @@
#[cfg(test)]
mod tests;
pub fn to_readable_str(mut val: usize) -> String {
let mut groups = vec![];
loop {
let group = val % 1000;
val /= 1000;
if val == 0 {
groups.push(group.to_string());
break;
} else {
groups.push(format!("{group:03}"));
}
}
groups.reverse();
groups.join("_")
}

View file

@ -1,14 +0,0 @@
use super::*;
#[test]
fn test_to_readable_str() {
assert_eq!("0", to_readable_str(0));
assert_eq!("1", to_readable_str(1));
assert_eq!("99", to_readable_str(99));
assert_eq!("999", to_readable_str(999));
assert_eq!("1_000", to_readable_str(1_000));
assert_eq!("1_001", to_readable_str(1_001));
assert_eq!("999_999", to_readable_str(999_999));
assert_eq!("1_000_000", to_readable_str(1_000_000));
assert_eq!("1_234_567", to_readable_str(1_234_567));
}

View file

@ -1,5 +1,4 @@
pub mod bug; pub mod bug;
pub mod common;
#[derive(Default, Copy, Clone)] #[derive(Default, Copy, Clone)]
pub struct Providers { pub struct Providers {

View file

@ -5,10 +5,10 @@
use rustc_ast::visit::BoundKind; use rustc_ast::visit::BoundKind;
use rustc_ast::{self as ast, NodeId, visit as ast_visit}; use rustc_ast::{self as ast, NodeId, visit as ast_visit};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::thousands::format_with_underscores;
use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit}; use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit};
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_middle::util::common::to_readable_str;
use rustc_span::Span; use rustc_span::Span;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
@ -144,10 +144,10 @@ impl<'k> StatCollector<'k> {
"{} {:<18}{:>10} ({:4.1}%){:>14}{:>14}", "{} {:<18}{:>10} ({:4.1}%){:>14}{:>14}",
prefix, prefix,
label, label,
to_readable_str(size), format_with_underscores(size),
percent(size, total_size), percent(size, total_size),
to_readable_str(node.stats.count), format_with_underscores(node.stats.count),
to_readable_str(node.stats.size) format_with_underscores(node.stats.size)
); );
if !node.subnodes.is_empty() { if !node.subnodes.is_empty() {
// We will soon sort, so the initial order does not matter. // We will soon sort, so the initial order does not matter.
@ -163,9 +163,9 @@ impl<'k> StatCollector<'k> {
"{} - {:<18}{:>10} ({:4.1}%){:>14}", "{} - {:<18}{:>10} ({:4.1}%){:>14}",
prefix, prefix,
label, label,
to_readable_str(size), format_with_underscores(size),
percent(size, total_size), percent(size, total_size),
to_readable_str(subnode.count), format_with_underscores(subnode.count),
); );
} }
} }
@ -175,8 +175,8 @@ impl<'k> StatCollector<'k> {
"{} {:<18}{:>10} {:>14}", "{} {:<18}{:>10} {:>14}",
prefix, prefix,
"Total", "Total",
to_readable_str(total_size), format_with_underscores(total_size),
to_readable_str(total_count), format_with_underscores(total_count),
); );
eprintln!("{prefix}"); eprintln!("{prefix}");
} }