Skip to content

Commit 1835cbe

Browse files
committed
don't amplify errors in format! with bad literals
1 parent bfa5f27 commit 1835cbe

File tree

7 files changed

+20
-35
lines changed

7 files changed

+20
-35
lines changed

src/libsyntax/ext/base.rs

+1
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,7 @@ pub fn expr_to_spanned_string<'a>(
998998
Err(match expr.node {
999999
ast::ExprKind::Lit(ref l) => match l.node {
10001000
ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))),
1001+
ast::LitKind::Err(_) => None,
10011002
_ => Some(cx.struct_span_err(l.span, err_msg))
10021003
},
10031004
ast::ExprKind::Err => None,

src/libsyntax/parse/mod.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub mod attr;
3333
pub mod classify;
3434

3535
pub(crate) mod unescape;
36-
use unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte, EscapeError};
36+
use unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte};
3737

3838
pub(crate) mod unescape_error_reporting;
3939

@@ -355,16 +355,14 @@ crate fn lit_token(lit: token::Lit, suf: Option<Symbol>, diag: Option<(Span, &Ha
355355
token::Byte(i) => {
356356
let lit_kind = match unescape_byte(&i.as_str()) {
357357
Ok(c) => LitKind::Byte(c),
358-
Err((_, EscapeError::MoreThanOneChar)) => LitKind::Err(i),
359-
Err(_) => LitKind::Byte(0),
358+
Err(_) => LitKind::Err(i),
360359
};
361360
(true, Some(lit_kind))
362361
},
363362
token::Char(i) => {
364363
let lit_kind = match unescape_char(&i.as_str()) {
365364
Ok(c) => LitKind::Char(c),
366-
Err((_, EscapeError::MoreThanOneChar)) => LitKind::Err(i),
367-
Err(_) => LitKind::Char('\u{FFFD}'),
365+
Err(_) => LitKind::Err(i),
368366
};
369367
(true, Some(lit_kind))
370368
},
@@ -380,17 +378,22 @@ crate fn lit_token(lit: token::Lit, suf: Option<Symbol>, diag: Option<(Span, &Ha
380378
// reuse the symbol from the Token. Otherwise, we must generate a
381379
// new symbol because the string in the LitKind is different to the
382380
// string in the Token.
381+
let mut has_error = false;
383382
let s = &sym.as_str();
384383
if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') {
385384
let mut buf = String::with_capacity(s.len());
386385
unescape_str(s, &mut |_, unescaped_char| {
387386
match unescaped_char {
388387
Ok(c) => buf.push(c),
389-
Err(_) => buf.push('\u{FFFD}'),
388+
Err(_) => has_error = true,
390389
}
391390
});
391+
if has_error {
392+
return (true, Some(LitKind::Err(sym)));
393+
}
392394
sym = Symbol::intern(&buf)
393395
}
396+
394397
(true, Some(LitKind::Str(sym, ast::StrStyle::Cooked)))
395398
}
396399
token::StrRaw(mut sym, n) => {
@@ -404,12 +407,16 @@ crate fn lit_token(lit: token::Lit, suf: Option<Symbol>, diag: Option<(Span, &Ha
404407
token::ByteStr(i) => {
405408
let s = &i.as_str();
406409
let mut buf = Vec::with_capacity(s.len());
410+
let mut has_error = false;
407411
unescape_byte_str(s, &mut |_, unescaped_byte| {
408412
match unescaped_byte {
409413
Ok(c) => buf.push(c),
410-
Err(_) => buf.push(0),
414+
Err(_) => has_error = true,
411415
}
412416
});
417+
if has_error {
418+
return (true, Some(LitKind::Err(i)));
419+
}
413420
buf.shrink_to_fit();
414421
(true, Some(LitKind::ByteStr(Lrc::new(buf))))
415422
}

src/test/ui/fmt/format-string-error-2.rs

-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ raw { \n
7777

7878
println!("\x7B}\u8 {", 1);
7979
//~^ ERROR incorrect unicode escape sequence
80-
//~| ERROR invalid format string: expected `'}'` but string was terminated
8180

8281
// note: raw strings don't escape `\xFF` and `\u{FF}` sequences
8382
println!(r#"\x7B}\u{8} {"#, 1);

src/test/ui/fmt/format-string-error-2.stderr

+3-13
Original file line numberDiff line numberDiff line change
@@ -157,31 +157,21 @@ LL | println!("\x7B}\u{8} {", 1);
157157
|
158158
= note: if you intended to print `{`, you can escape it using `{{`
159159

160-
error: invalid format string: expected `'}'` but string was terminated
161-
--> $DIR/format-string-error-2.rs:78:27
162-
|
163-
LL | println!("\x7B}\u8 {", 1);
164-
| -^ expected `'}'` in format string
165-
| |
166-
| because of this opening brace
167-
|
168-
= note: if you intended to print `{`, you can escape it using `{{`
169-
170160
error: invalid format string: unmatched `}` found
171-
--> $DIR/format-string-error-2.rs:83:21
161+
--> $DIR/format-string-error-2.rs:82:21
172162
|
173163
LL | println!(r#"\x7B}\u{8} {"#, 1);
174164
| ^ unmatched `}` in format string
175165
|
176166
= note: if you intended to print `}`, you can escape it using `}}`
177167

178168
error: invalid format string: unmatched `}` found
179-
--> $DIR/format-string-error-2.rs:86:21
169+
--> $DIR/format-string-error-2.rs:85:21
180170
|
181171
LL | println!(r#"\x7B}\u8 {"#, 1);
182172
| ^ unmatched `}` in format string
183173
|
184174
= note: if you intended to print `}`, you can escape it using `}}`
185175

186-
error: aborting due to 19 previous errors
176+
error: aborting due to 18 previous errors
187177

src/test/ui/str/str-as-char.fixed

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// run-rustfix
22

33
fn main() {
4-
println!("{}", "●●"); //~ ERROR character literal may only contain one codepoint
5-
//~^ ERROR format argument must be a string literal
4+
println!("●●"); //~ ERROR character literal may only contain one codepoint
65
}

src/test/ui/str/str-as-char.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@
22

33
fn main() {
44
println!('●●'); //~ ERROR character literal may only contain one codepoint
5-
//~^ ERROR format argument must be a string literal
65
}

src/test/ui/str/str-as-char.stderr

+1-11
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,5 @@ help: if you meant to write a `str` literal, use double quotes
88
LL | println!("●●");
99
| ^^^^
1010

11-
error: format argument must be a string literal
12-
--> $DIR/str-as-char.rs:4:14
13-
|
14-
LL | println!('●●');
15-
| ^^^^
16-
help: you might be missing a string literal to format with
17-
|
18-
LL | println!("{}", '●●');
19-
| ^^^^^
20-
21-
error: aborting due to 2 previous errors
11+
error: aborting due to previous error
2212

0 commit comments

Comments
 (0)