Rollup merge of #86104 - FabianWolff:issue-86085, r=davidtwco
Fix span calculation in format strings This pull request fixes #86085. The ICE described there is due to an error in the span calculation inside format strings, if the format string is the result of a macro invocation: ```rust fn main() { format!(concat!("abc}")); } ``` currently produces: ``` error: invalid format string: unmatched `}` found --> test.rs:2:17 | 2 | format!(concat!("abc}")); | ^ unmatched `}` in format string ``` which is obviously incorrect. This happens because the span of the entire `concat!()` is combined with the _relative_ location of the unmatched `` `}` `` in the _result_ of the macro invocation (i.e. 4). In #86085, this has led to a span that starts or ends in the middle of a multibyte character, but the root cause was the same. This pull request fixes the problem.
This commit is contained in:
commit
4ff55ecf04
@ -939,6 +939,7 @@ pub fn expand_preparsed_format_args(
|
||||
|
||||
let msg = "format argument must be a string literal";
|
||||
let fmt_sp = efmt.span;
|
||||
let efmt_kind_is_lit: bool = matches!(efmt.kind, ast::ExprKind::Lit(_));
|
||||
let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
|
||||
Ok(mut fmt) if append_newline => {
|
||||
fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
|
||||
@ -989,7 +990,19 @@ pub fn expand_preparsed_format_args(
|
||||
|
||||
if !parser.errors.is_empty() {
|
||||
let err = parser.errors.remove(0);
|
||||
let sp = fmt_span.from_inner(err.span);
|
||||
let sp = if efmt_kind_is_lit {
|
||||
fmt_span.from_inner(err.span)
|
||||
} else {
|
||||
// The format string could be another macro invocation, e.g.:
|
||||
// format!(concat!("abc", "{}"), 4);
|
||||
// However, `err.span` is an inner span relative to the *result* of
|
||||
// the macro invocation, which is why we would get a nonsensical
|
||||
// result calling `fmt_span.from_inner(err.span)` as above, and
|
||||
// might even end up inside a multibyte character (issue #86085).
|
||||
// Therefore, we conservatively report the error for the entire
|
||||
// argument span here.
|
||||
fmt_span
|
||||
};
|
||||
let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description));
|
||||
e.span_label(sp, err.label + " in format string");
|
||||
if let Some(note) = err.note {
|
||||
|
15
src/test/ui/fmt/format-concat-span.rs
Normal file
15
src/test/ui/fmt/format-concat-span.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// If the format string is another macro invocation, rustc would previously
|
||||
// compute nonsensical spans, such as:
|
||||
//
|
||||
// error: invalid format string: unmatched `}` found
|
||||
// --> test.rs:2:17
|
||||
// |
|
||||
// 2 | format!(concat!("abc}"));
|
||||
// | ^ unmatched `}` in format string
|
||||
//
|
||||
// This test checks that this behavior has been fixed.
|
||||
|
||||
fn main() {
|
||||
format!(concat!("abc}"));
|
||||
//~^ ERROR: invalid format string: unmatched `}` found
|
||||
}
|
11
src/test/ui/fmt/format-concat-span.stderr
Normal file
11
src/test/ui/fmt/format-concat-span.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/format-concat-span.rs:13:13
|
||||
|
|
||||
LL | format!(concat!("abc}"));
|
||||
| ^^^^^^^^^^^^^^^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
6
src/test/ui/fmt/issue-86085.rs
Normal file
6
src/test/ui/fmt/issue-86085.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// Tests for an ICE with the fuzzed input below.
|
||||
|
||||
fn main ( ) {
|
||||
format ! ( concat ! ( r#"lJÆ<F0908FBF>.<>"# , "r} {}" ) ) ;
|
||||
//~^ ERROR: invalid format string: unmatched `}` found
|
||||
}
|
11
src/test/ui/fmt/issue-86085.stderr
Normal file
11
src/test/ui/fmt/issue-86085.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/issue-86085.rs:4:12
|
||||
|
|
||||
LL | format ! ( concat ! ( r#"lJÆ<F0908FBF>.<>"# , "r} {}" ) ) ;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user