Skip to content

Commit 4457180

Browse files
committed
Rollup merge of rust-lang#53521 - alexcrichton:optimize-lit-token, r=michaelwoerister
syntax: Optimize some literal parsing Currently in the `wasm-bindgen` project we have a very very large crate that's procedurally generated, `web-sys`. To generate this crate we parse all of a browser's WebIDL and we then generate bindings for all of the APIs contained within. The resulting Rust file is 18MB large (wow!) and currently takes a very long time to compile in debug mode. On the nightly compiler a *debug* build takes 90s for the crate to finish. I was curious what was taking so long and upon investigating a *massive* portion of the time was spent in the `lit_token` method of the compiler, primarily formatting strings via `format!`. Upon some more investigation it looks like the `byte_str_lit` was allocating an error message once per byte, causing a very large number of allocations to happen for large literals, of which wasm-bindgen generates quite a few (some are MB large). This commit fixes the issue by lazily allocating the error message, only doing so if the error message is actually needed (which should be never). As a result, the debug mode compilation time for our `web-sys` crate decreased from 90s to 20s, a very nice improvement! (although we've still got some work to do).
2 parents b5519db + 5bf2ad3 commit 4457180

File tree

1 file changed

+4
-6
lines changed

1 file changed

+4
-6
lines changed

src/libsyntax/parse/mod.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ fn byte_lit(lit: &str) -> (u8, usize) {
533533
fn byte_str_lit(lit: &str) -> Lrc<Vec<u8>> {
534534
let mut res = Vec::with_capacity(lit.len());
535535

536-
let error = |i| format!("lexer should have rejected {} at {}", lit, i);
536+
let error = |i| panic!("lexer should have rejected {} at {}", lit, i);
537537

538538
/// Eat everything up to a non-whitespace
539539
fn eat<I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) {
@@ -552,12 +552,11 @@ fn byte_str_lit(lit: &str) -> Lrc<Vec<u8>> {
552552
loop {
553553
match chars.next() {
554554
Some((i, b'\\')) => {
555-
let em = error(i);
556-
match chars.peek().expect(&em).1 {
555+
match chars.peek().unwrap_or_else(|| error(i)).1 {
557556
b'\n' => eat(&mut chars),
558557
b'\r' => {
559558
chars.next();
560-
if chars.peek().expect(&em).1 != b'\n' {
559+
if chars.peek().unwrap_or_else(|| error(i)).1 != b'\n' {
561560
panic!("lexer accepted bare CR");
562561
}
563562
eat(&mut chars);
@@ -574,8 +573,7 @@ fn byte_str_lit(lit: &str) -> Lrc<Vec<u8>> {
574573
}
575574
},
576575
Some((i, b'\r')) => {
577-
let em = error(i);
578-
if chars.peek().expect(&em).1 != b'\n' {
576+
if chars.peek().unwrap_or_else(|| error(i)).1 != b'\n' {
579577
panic!("lexer accepted bare CR");
580578
}
581579
chars.next();

0 commit comments

Comments
 (0)