diff options
| author | Andre Bogus <bogusandre@gmail.com> | 2021-02-26 22:00:16 +0100 |
|---|---|---|
| committer | Andre Bogus <bogusandre@gmail.com> | 2021-02-27 15:28:58 +0100 |
| commit | 8abc5fd3be35c39fdb93335acebf15dbbac180be (patch) | |
| tree | 5d3cf092fa1d8c5d2d00b84bd2b76795d5195c79 /compiler/rustc_errors | |
| parent | cecdb181ade91c0a5ffab9a148dba68fc7d00ee3 (diff) | |
| download | rust-8abc5fd3be35c39fdb93335acebf15dbbac180be.tar.gz rust-8abc5fd3be35c39fdb93335acebf15dbbac180be.zip | |
Even faster counting of digits for error line numbers
Diffstat (limited to 'compiler/rustc_errors')
| -rw-r--r-- | compiler/rustc_errors/src/emitter.rs | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 42c3d5e48fe..9b6f67166bd 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1713,18 +1713,8 @@ impl EmitterWriter { let max_line_num_len = if self.ui_testing { ANONYMIZED_LINE_NUM.len() } else { - // Instead of using .to_string().len(), we iteratively count the - // number of digits to avoid allocation. This strategy has sizable - // performance gains over the old string strategy. - let mut n = self.get_max_line_num(span, children); - let mut num_digits = 0; - loop { - num_digits += 1; - n /= 10; - if n == 0 { - break num_digits; - } - } + let n = self.get_max_line_num(span, children); + num_decimal_digits(n) }; match self.emit_message_default(span, message, code, level, max_line_num_len, false) { @@ -1952,6 +1942,30 @@ impl FileWithAnnotatedLines { } } +// instead of taking the String length or dividing by 10 while > 0, we multiply a limit by 10 until +// we're higher. If the loop isn't exited by the `return`, the last multiplication will wrap, which +// is OK, because while we cannot fit a higher power of 10 in a usize, the loop will end anyway. +// This is also why we need the max number of decimal digits within a `usize`. +fn num_decimal_digits(num: usize) -> usize { + #[cfg(target_pointer_width = "64")] + const MAX_DIGITS: usize = 20; + + #[cfg(target_pointer_width = "32")] + const MAX_DIGITS: usize = 10; + + #[cfg(target_pointer_width = "16")] + const MAX_DIGITS: usize = 5; + + let mut lim = 10; + for num_digits in 1..MAX_DIGITS { + if num < lim { + return num_digits; + } + lim = lim.wrapping_mul(10); + } + MAX_DIGITS +} + fn replace_tabs(str: &str) -> String { str.replace('\t', " ") } |
