diff options
| author | Nicholas Nethercote <nnethercote@mozilla.com> | 2018-04-18 14:09:27 +1000 |
|---|---|---|
| committer | Nicholas Nethercote <nnethercote@mozilla.com> | 2018-04-19 09:17:40 +1000 |
| commit | 9f145022ef9390e6cfb0b2416744a393d62d3350 (patch) | |
| tree | a3cbbcba4696d6ce2a22665e2b833f6ca043cdb8 /src/libsyntax | |
| parent | 23561c6747b0916e852aaa2a5d04c0b0eeddc6de (diff) | |
| download | rust-9f145022ef9390e6cfb0b2416744a393d62d3350.tar.gz rust-9f145022ef9390e6cfb0b2416744a393d62d3350.zip | |
Avoid allocating when parsing \u{...} literals.
`char_lit` uses an allocation in order to ignore '_' chars in \u{...}
literals. This patch changes it to not do that by processing the chars
more directly.
This improves various rustc-perf benchmark measurements by up to 6%,
particularly regex, futures, clap, coercions, hyper, and encoding.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ff63c9a5c6d..0397c3297db 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -271,8 +271,16 @@ pub fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) { 'u' => { assert_eq!(lit.as_bytes()[2], b'{'); let idx = lit.find('}').unwrap(); - let s = &lit[3..idx].chars().filter(|&c| c != '_').collect::<String>(); - let v = u32::from_str_radix(&s, 16).unwrap(); + + // All digits and '_' are ascii, so treat each byte as a char. + let mut v: u32 = 0; + for c in lit[3..idx].bytes() { + let c = char::from(c); + if c != '_' { + let x = c.to_digit(16).unwrap(); + v = v.checked_mul(16).unwrap().checked_add(x).unwrap(); + } + } let c = char::from_u32(v).unwrap_or_else(|| { if let Some((span, diag)) = diag { let mut diag = diag.struct_span_err(span, "invalid unicode character escape"); |
