Skip to content

Commit 9f14502

Browse files
committed
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.
1 parent 23561c6 commit 9f14502

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

src/libsyntax/parse/mod.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,16 @@ pub fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) {
271271
'u' => {
272272
assert_eq!(lit.as_bytes()[2], b'{');
273273
let idx = lit.find('}').unwrap();
274-
let s = &lit[3..idx].chars().filter(|&c| c != '_').collect::<String>();
275-
let v = u32::from_str_radix(&s, 16).unwrap();
274+
275+
// All digits and '_' are ascii, so treat each byte as a char.
276+
let mut v: u32 = 0;
277+
for c in lit[3..idx].bytes() {
278+
let c = char::from(c);
279+
if c != '_' {
280+
let x = c.to_digit(16).unwrap();
281+
v = v.checked_mul(16).unwrap().checked_add(x).unwrap();
282+
}
283+
}
276284
let c = char::from_u32(v).unwrap_or_else(|| {
277285
if let Some((span, diag)) = diag {
278286
let mut diag = diag.struct_span_err(span, "invalid unicode character escape");

0 commit comments

Comments
 (0)