mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Fix format_args capture for macro expanded format strings
This commit is contained in:
parent
f914b82a75
commit
71db0dd918
@ -159,7 +159,7 @@ pub fn make_format_args(
|
||||
append_newline: bool,
|
||||
) -> Result<FormatArgs, ()> {
|
||||
let msg = "format argument must be a string literal";
|
||||
let fmt_span = efmt.span;
|
||||
let unexpanded_fmt_span = efmt.span;
|
||||
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));
|
||||
@ -174,7 +174,7 @@ pub fn make_format_args(
|
||||
};
|
||||
if !suggested {
|
||||
err.span_suggestion(
|
||||
fmt_span.shrink_to_lo(),
|
||||
unexpanded_fmt_span.shrink_to_lo(),
|
||||
"you might be missing a string literal to format with",
|
||||
format!("\"{}\", ", sugg_fmt),
|
||||
Applicability::MaybeIncorrect,
|
||||
@ -192,7 +192,7 @@ pub fn make_format_args(
|
||||
};
|
||||
|
||||
let fmt_str = fmt_str.as_str(); // for the suggestions below
|
||||
let fmt_snippet = ecx.source_map().span_to_snippet(fmt_span).ok();
|
||||
let fmt_snippet = ecx.source_map().span_to_snippet(unexpanded_fmt_span).ok();
|
||||
let mut parser = parse::Parser::new(
|
||||
fmt_str,
|
||||
str_style,
|
||||
|
28
src/test/ui/fmt/auxiliary/format-string-proc-macro.rs
Normal file
28
src/test/ui/fmt/auxiliary/format-string-proc-macro.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// force-host
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
use proc_macro::{Literal, Span, TokenStream, TokenTree};
|
||||
|
||||
#[proc_macro]
|
||||
pub fn foo_with_input_span(input: TokenStream) -> TokenStream {
|
||||
let span = input.into_iter().next().unwrap().span();
|
||||
|
||||
let mut lit = Literal::string("{foo}");
|
||||
lit.set_span(span);
|
||||
|
||||
TokenStream::from(TokenTree::Literal(lit))
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn err_with_input_span(input: TokenStream) -> TokenStream {
|
||||
let span = input.into_iter().next().unwrap().span();
|
||||
|
||||
let mut lit = Literal::string(" }");
|
||||
lit.set_span(span);
|
||||
|
||||
TokenStream::from(TokenTree::Literal(lit))
|
||||
}
|
@ -1,4 +1,22 @@
|
||||
// aux-build:format-string-proc-macro.rs
|
||||
|
||||
#[macro_use]
|
||||
extern crate format_string_proc_macro;
|
||||
|
||||
macro_rules! def_site {
|
||||
() => { "{foo}" } //~ ERROR: there is no argument named `foo`
|
||||
}
|
||||
|
||||
macro_rules! call_site {
|
||||
($fmt:literal) => { $fmt }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
format!(concat!("{foo}")); //~ ERROR: there is no argument named `foo`
|
||||
format!(concat!("{ba", "r} {}"), 1); //~ ERROR: there is no argument named `bar`
|
||||
|
||||
format!(def_site!());
|
||||
format!(call_site!("{foo}")); //~ ERROR: there is no argument named `foo`
|
||||
|
||||
format!(foo_with_input_span!("")); //~ ERROR: there is no argument named `foo`
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: there is no argument named `foo`
|
||||
--> $DIR/format-args-capture-macro-hygiene.rs:2:13
|
||||
--> $DIR/format-args-capture-macro-hygiene.rs:15:13
|
||||
|
|
||||
LL | format!(concat!("{foo}"));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -9,7 +9,7 @@ LL | format!(concat!("{foo}"));
|
||||
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: there is no argument named `bar`
|
||||
--> $DIR/format-args-capture-macro-hygiene.rs:3:13
|
||||
--> $DIR/format-args-capture-macro-hygiene.rs:16:13
|
||||
|
|
||||
LL | format!(concat!("{ba", "r} {}"), 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -18,5 +18,36 @@ LL | format!(concat!("{ba", "r} {}"), 1);
|
||||
= note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
|
||||
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: there is no argument named `foo`
|
||||
--> $DIR/format-args-capture-macro-hygiene.rs:7:13
|
||||
|
|
||||
LL | () => { "{foo}" }
|
||||
| ^^^^^^^
|
||||
...
|
||||
LL | format!(def_site!());
|
||||
| ----------- in this macro invocation
|
||||
|
|
||||
= note: did you intend to capture a variable `foo` from the surrounding scope?
|
||||
= note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
|
||||
= note: this error originates in the macro `def_site` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: there is no argument named `foo`
|
||||
--> $DIR/format-args-capture-macro-hygiene.rs:19:24
|
||||
|
|
||||
LL | format!(call_site!("{foo}"));
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: did you intend to capture a variable `foo` from the surrounding scope?
|
||||
= note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
|
||||
|
||||
error: there is no argument named `foo`
|
||||
--> $DIR/format-args-capture-macro-hygiene.rs:21:34
|
||||
|
|
||||
LL | format!(foo_with_input_span!(""));
|
||||
| ^^
|
||||
|
|
||||
= note: did you intend to capture a variable `foo` from the surrounding scope?
|
||||
= note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
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
|
||||
|
@ -1,3 +1,9 @@
|
||||
// aux-build:format-string-proc-macro.rs
|
||||
|
||||
#[macro_use]
|
||||
extern crate format_string_proc_macro;
|
||||
|
||||
|
||||
// If the format string is another macro invocation, rustc would previously
|
||||
// compute nonsensical spans, such as:
|
||||
//
|
||||
@ -12,4 +18,7 @@
|
||||
fn main() {
|
||||
format!(concat!("abc}"));
|
||||
//~^ ERROR: invalid format string: unmatched `}` found
|
||||
|
||||
format!(err_with_input_span!(""));
|
||||
//~^ ERROR: invalid format string: unmatched `}` found
|
||||
}
|
19
src/test/ui/fmt/format-expanded-string.stderr
Normal file
19
src/test/ui/fmt/format-expanded-string.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/format-expanded-string.rs:19: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: invalid format string: unmatched `}` found
|
||||
--> $DIR/format-expanded-string.rs:22:34
|
||||
|
|
||||
LL | format!(err_with_input_span!(""));
|
||||
| ^^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user