Skip to content

Commit

Permalink
Improve char escaping in lexer messages
Browse files Browse the repository at this point in the history
Currently ', " and \ are escaped as \', \" and \\ respectively. This
leads to confusing messages such as `error: unknown start of token: \\`
when encountering a single backslash.

Fix by emitting printable ASCII characters directly. This will still
escape \r, \n, \t and Unicode characters.

Fixes #47902
  • Loading branch information
etaoins committed Jan 31, 2018
1 parent 560a2f4 commit b9441f2
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 13 deletions.
31 changes: 19 additions & 12 deletions src/libsyntax/parse/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,27 @@ impl<'a> StringReader<'a> {
self.err_span(self.mk_sp(from_pos, to_pos), m)
}

/// Pushes a character to a message string for error reporting
fn push_escaped_char_for_msg(m: &mut String, c: char) {
match c {
'\u{20}'...'\u{7e}' => {
// Don't escape \, ' or " for user-facing messages
m.push(c);
}
_ => {
for c in c.escape_default() {
m.push(c);
}
}
}
}

/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
/// escaped character to the error message
fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError {
let mut m = m.to_string();
m.push_str(": ");
for c in c.escape_default() {
m.push(c)
}
Self::push_escaped_char_for_msg(&mut m, c);
self.fatal_span_(from_pos, to_pos, &m[..])
}
fn struct_fatal_span_char(&self,
Expand All @@ -264,9 +277,7 @@ impl<'a> StringReader<'a> {
-> DiagnosticBuilder<'a> {
let mut m = m.to_string();
m.push_str(": ");
for c in c.escape_default() {
m.push(c)
}
Self::push_escaped_char_for_msg(&mut m, c);
self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
}

Expand All @@ -275,9 +286,7 @@ impl<'a> StringReader<'a> {
fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) {
let mut m = m.to_string();
m.push_str(": ");
for c in c.escape_default() {
m.push(c)
}
Self::push_escaped_char_for_msg(&mut m, c);
self.err_span_(from_pos, to_pos, &m[..]);
}
fn struct_err_span_char(&self,
Expand All @@ -288,9 +297,7 @@ impl<'a> StringReader<'a> {
-> DiagnosticBuilder<'a> {
let mut m = m.to_string();
m.push_str(": ");
for c in c.escape_default() {
m.push(c)
}
Self::push_escaped_char_for_msg(&mut m, c);
self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..])
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/parse-fail/bad-char-literals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
fn main() {
// these literals are just silly.
''';
//~^ ERROR: character constant must be escaped: \'
//~^ ERROR: character constant must be escaped: '

// note that this is a literal "\n" byte
'
Expand Down
13 changes: 13 additions & 0 deletions src/test/parse-fail/lex-stray-backslash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: -Z parse-only

\ //~ ERROR: unknown start of token: \

0 comments on commit b9441f2

Please sign in to comment.