From 1835cbeb6574997ec5188cb22b9538c61976d2b4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 2 May 2019 20:56:07 +0300 Subject: [PATCH] don't amplify errors in format! with bad literals --- src/libsyntax/ext/base.rs | 1 + src/libsyntax/parse/mod.rs | 21 +++++++++++++------- src/test/ui/fmt/format-string-error-2.rs | 1 - src/test/ui/fmt/format-string-error-2.stderr | 16 +++------------ src/test/ui/str/str-as-char.fixed | 3 +-- src/test/ui/str/str-as-char.rs | 1 - src/test/ui/str/str-as-char.stderr | 12 +---------- 7 files changed, 20 insertions(+), 35 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 452cc2f2c65..cc19acb61ad 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -998,6 +998,7 @@ pub fn expr_to_spanned_string<'a>( Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), + ast::LitKind::Err(_) => None, _ => Some(cx.struct_span_err(l.span, err_msg)) }, ast::ExprKind::Err => None, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index d6d4f8e8f04..34a86bab229 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -33,7 +33,7 @@ pub mod classify; pub(crate) mod unescape; -use unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte, EscapeError}; +use unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte}; pub(crate) mod unescape_error_reporting; @@ -355,16 +355,14 @@ macro_rules! err { token::Byte(i) => { let lit_kind = match unescape_byte(&i.as_str()) { Ok(c) => LitKind::Byte(c), - Err((_, EscapeError::MoreThanOneChar)) => LitKind::Err(i), - Err(_) => LitKind::Byte(0), + Err(_) => LitKind::Err(i), }; (true, Some(lit_kind)) }, token::Char(i) => { let lit_kind = match unescape_char(&i.as_str()) { Ok(c) => LitKind::Char(c), - Err((_, EscapeError::MoreThanOneChar)) => LitKind::Err(i), - Err(_) => LitKind::Char('\u{FFFD}'), + Err(_) => LitKind::Err(i), }; (true, Some(lit_kind)) }, @@ -380,17 +378,22 @@ macro_rules! err { // reuse the symbol from the Token. Otherwise, we must generate a // new symbol because the string in the LitKind is different to the // string in the Token. + let mut has_error = false; let s = &sym.as_str(); if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') { let mut buf = String::with_capacity(s.len()); unescape_str(s, &mut |_, unescaped_char| { match unescaped_char { Ok(c) => buf.push(c), - Err(_) => buf.push('\u{FFFD}'), + Err(_) => has_error = true, } }); + if has_error { + return (true, Some(LitKind::Err(sym))); + } sym = Symbol::intern(&buf) } + (true, Some(LitKind::Str(sym, ast::StrStyle::Cooked))) } token::StrRaw(mut sym, n) => { @@ -404,12 +407,16 @@ macro_rules! err { token::ByteStr(i) => { let s = &i.as_str(); let mut buf = Vec::with_capacity(s.len()); + let mut has_error = false; unescape_byte_str(s, &mut |_, unescaped_byte| { match unescaped_byte { Ok(c) => buf.push(c), - Err(_) => buf.push(0), + Err(_) => has_error = true, } }); + if has_error { + return (true, Some(LitKind::Err(i))); + } buf.shrink_to_fit(); (true, Some(LitKind::ByteStr(Lrc::new(buf)))) } diff --git a/src/test/ui/fmt/format-string-error-2.rs b/src/test/ui/fmt/format-string-error-2.rs index e9169d338f7..8ca98fc266a 100644 --- a/src/test/ui/fmt/format-string-error-2.rs +++ b/src/test/ui/fmt/format-string-error-2.rs @@ -77,7 +77,6 @@ fn main() { println!("\x7B}\u8 {", 1); //~^ ERROR incorrect unicode escape sequence - //~| ERROR invalid format string: expected `'}'` but string was terminated // note: raw strings don't escape `\xFF` and `\u{FF}` sequences println!(r#"\x7B}\u{8} {"#, 1); diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index 6656cc82369..227ec27efc8 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -157,18 +157,8 @@ LL | println!("\x7B}\u{8} {", 1); | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'` but string was terminated - --> $DIR/format-string-error-2.rs:78:27 - | -LL | println!("\x7B}\u8 {", 1); - | -^ expected `'}'` in format string - | | - | because of this opening brace - | - = note: if you intended to print `{`, you can escape it using `{{` - error: invalid format string: unmatched `}` found - --> $DIR/format-string-error-2.rs:83:21 + --> $DIR/format-string-error-2.rs:82:21 | LL | println!(r#"\x7B}\u{8} {"#, 1); | ^ unmatched `}` in format string @@ -176,12 +166,12 @@ LL | println!(r#"\x7B}\u{8} {"#, 1); = note: if you intended to print `}`, you can escape it using `}}` error: invalid format string: unmatched `}` found - --> $DIR/format-string-error-2.rs:86:21 + --> $DIR/format-string-error-2.rs:85:21 | LL | println!(r#"\x7B}\u8 {"#, 1); | ^ unmatched `}` in format string | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors diff --git a/src/test/ui/str/str-as-char.fixed b/src/test/ui/str/str-as-char.fixed index accead5c850..42bbef83917 100644 --- a/src/test/ui/str/str-as-char.fixed +++ b/src/test/ui/str/str-as-char.fixed @@ -1,6 +1,5 @@ // run-rustfix fn main() { - println!("{}", "●●"); //~ ERROR character literal may only contain one codepoint - //~^ ERROR format argument must be a string literal + println!("●●"); //~ ERROR character literal may only contain one codepoint } diff --git a/src/test/ui/str/str-as-char.rs b/src/test/ui/str/str-as-char.rs index fb179ec7245..09b9dfc590d 100644 --- a/src/test/ui/str/str-as-char.rs +++ b/src/test/ui/str/str-as-char.rs @@ -2,5 +2,4 @@ fn main() { println!('●●'); //~ ERROR character literal may only contain one codepoint - //~^ ERROR format argument must be a string literal } diff --git a/src/test/ui/str/str-as-char.stderr b/src/test/ui/str/str-as-char.stderr index 162f0888a29..540a1b55376 100644 --- a/src/test/ui/str/str-as-char.stderr +++ b/src/test/ui/str/str-as-char.stderr @@ -8,15 +8,5 @@ help: if you meant to write a `str` literal, use double quotes LL | println!("●●"); | ^^^^ -error: format argument must be a string literal - --> $DIR/str-as-char.rs:4:14 - | -LL | println!('●●'); - | ^^^^ -help: you might be missing a string literal to format with - | -LL | println!("{}", '●●'); - | ^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error