Skip to content

Commit

Permalink
Even faster counting of digits for error line numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
llogiq committed Feb 27, 2021
1 parent cecdb18 commit 8abc5fd
Showing 1 changed file with 26 additions and 12 deletions.
38 changes: 26 additions & 12 deletions compiler/rustc_errors/src/emitter.rs
Expand Up @@ -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) {
Expand Down Expand Up @@ -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', " ")
}
Expand Down

0 comments on commit 8abc5fd

Please sign in to comment.