From d5d389e4f11b1fad2d42453942f81271bbddee78 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 May 2018 11:50:21 +1000 Subject: [PATCH 1/2] Use escape_default() for strings in LitKind::token(). This avoids converting every char to \u{...} form, which bloats the resulting strings unnecessarily. It also provides consistency with the existing escape_default() calls in LitKind::token() used for raw string literals, char literals, and raw byte char literals. There are two benefits from this change. - Compilation is faster. Most of the rustc-perf benchmarks see a non-trivial speedup, particularly for incremental rebuilds, with the best speedup over 13%, and multiple others over 10%. - Generated rlibs are smaller. An extreme example is libfutures.rlib, which shrinks from 2073306 bytes to 1765927 bytes, a 15% reduction. --- src/libsyntax/attr.rs | 5 +---- src/libsyntax/lib.rs | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index c68a743303a..05fabbee389 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -1228,10 +1228,7 @@ impl LitKind { match *self { LitKind::Str(string, ast::StrStyle::Cooked) => { - let mut escaped = String::new(); - for ch in string.as_str().chars() { - escaped.extend(ch.escape_unicode()); - } + let escaped = string.as_str().escape_default(); Token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None) } LitKind::Str(string, ast::StrStyle::Raw(n)) => { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 870ce1926ad..f148aaf7267 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -25,6 +25,7 @@ #![feature(non_exhaustive)] #![feature(const_atomic_usize_new)] #![feature(rustc_attrs)] +#![feature(str_escape)] #![recursion_limit="256"] From 7a56360ecef1dca261110281e78385fc8f14b154 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 May 2018 08:55:58 +1000 Subject: [PATCH 2/2] Remove parse::escape_default(). str::escape_default() can be used instead. --- src/libsyntax/parse/mod.rs | 8 ++------ src/libsyntax/print/pprust.rs | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ff09c6aa2f0..f252020bc31 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -298,14 +298,10 @@ pub fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) { } } -pub fn escape_default(s: &str) -> String { - s.chars().map(char::escape_default).flat_map(|x| x).collect() -} - /// Parse a string representing a string literal into its final form. Does /// unescaping. pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String { - debug!("parse_str_lit: given {}", escape_default(lit)); + debug!("str_lit: given {}", lit.escape_default()); let mut res = String::with_capacity(lit.len()); let error = |i| format!("lexer should have rejected {} at {}", lit, i); @@ -374,7 +370,7 @@ pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String { /// Parse a string representing a raw string literal into its final form. The /// only operation this does is convert embedded CRLF into a single LF. pub fn raw_str_lit(lit: &str) -> String { - debug!("raw_str_lit: given {}", escape_default(lit)); + debug!("raw_str_lit: given {}", lit.escape_default()); let mut res = String::with_capacity(lit.len()); let mut chars = lit.chars().peekable(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 88860df10e2..27c5a14ff0e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -656,7 +656,7 @@ pub trait PrintState<'a> { style: ast::StrStyle) -> io::Result<()> { let st = match style { ast::StrStyle::Cooked => { - (format!("\"{}\"", parse::escape_default(st))) + (format!("\"{}\"", st.escape_default())) } ast::StrStyle::Raw(n) => { (format!("r{delim}\"{string}\"{delim}",