From 4c274b6aea00c2327211e8295f4d97ee6e624a2b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 12 Sep 2016 13:03:21 +1000 Subject: [PATCH 1/2] Avoid an unnecessary intermediate value in char_lit(). This makes the function more concise and easier to understand. --- src/libsyntax/parse/mod.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index af95e44a567ba..31fa2cda5db5e 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -287,26 +287,21 @@ pub fn char_lit(lit: &str) -> (char, isize) { use std::char; let mut chars = lit.chars(); - let c = match (chars.next(), chars.next()) { + match (chars.next(), chars.next()) { (Some(c), None) if c != '\\' => return (c, 1), (Some('\\'), Some(c)) => match c { - '"' => Some('"'), - 'n' => Some('\n'), - 'r' => Some('\r'), - 't' => Some('\t'), - '\\' => Some('\\'), - '\'' => Some('\''), - '0' => Some('\0'), - _ => { None } + '"' => return ('"', 2), + 'n' => return ('\n', 2), + 'r' => return ('\r', 2), + 't' => return ('\t', 2), + '\\' => return ('\\', 2), + '\'' => return ('\'', 2), + '0' => return ('\0', 2), + _ => {} }, _ => panic!("lexer accepted invalid char escape `{}`", lit) }; - match c { - Some(x) => return (x, 2), - None => { } - } - let msg = format!("lexer should have rejected a bad character escape {}", lit); let msg2 = &msg[..]; From 826f673664023e79e86409296d3d67527c9b0a5a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 12 Sep 2016 14:31:51 +1000 Subject: [PATCH 2/2] Lazily construct panic messages in char_lit(). This reduces the time taken to run `rustc -Zparse-only rustc-benchmarks/issue-32278-big-array-of-strings` from 0.18s to 0.15s on my machine, and reduces the number of instructions (as measured by Cachegrind) from 1.34B to 1.01B. With the change applied, the time to fully compile that benchmark is 1.96s, so this is a 1.5% improvement. --- src/libsyntax/parse/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 31fa2cda5db5e..a1eceb6921c6d 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -302,9 +302,6 @@ pub fn char_lit(lit: &str) -> (char, isize) { _ => panic!("lexer accepted invalid char escape `{}`", lit) }; - let msg = format!("lexer should have rejected a bad character escape {}", lit); - let msg2 = &msg[..]; - fn esc(len: usize, lit: &str) -> Option<(char, isize)> { u32::from_str_radix(&lit[2..len], 16).ok() .and_then(char::from_u32) @@ -313,7 +310,10 @@ pub fn char_lit(lit: &str) -> (char, isize) { let unicode_escape = || -> Option<(char, isize)> { if lit.as_bytes()[2] == b'{' { - let idx = lit.find('}').expect(msg2); + let idx = lit.find('}').unwrap_or_else(|| { + panic!("lexer should have rejected a bad character escape {}", lit) + }); + let subslice = &lit[3..idx]; u32::from_str_radix(subslice, 16).ok() .and_then(char::from_u32) @@ -329,7 +329,9 @@ pub fn char_lit(lit: &str) -> (char, isize) { 'u' => unicode_escape(), 'U' => esc(10, lit), _ => None, - }.expect(msg2); + }.unwrap_or_else(|| { + panic!("lexer should have rejected a bad character escape {}", lit) + }) } /// Parse a string representing a string literal into its final form. Does