From 8467ceff22477fe567883e6fbd810e0f9e220686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 23 Oct 2019 17:32:33 -0700 Subject: [PATCH] Tweak format string error to point at arguments always Add secondary span labels with no text to make it clear when there's a mismatch bewteen the positional arguments in a format string and the arguments to the macro. This shouldn't affect experienced users, but it should make it easier for newcomers to more clearly understand how `format!()` and `println!()` are supposed to be used. ``` error: 2 positional arguments in format string, but there is 1 argument --> file8.rs:2:14 | 2 | format!("{} {}", 1); | ^^ ^^ - ``` instead of ``` error: 2 positional arguments in format string, but there is 1 argument --> file8.rs:2:14 | 2 | format!("{} {}", 1); | ^^ ^^ ``` --- src/libsyntax_ext/format.rs | 5 ++++- src/test/ui/fmt/format-string-error.rs | 2 ++ src/test/ui/fmt/format-string-error.stderr | 8 +++++++- src/test/ui/if/ifmt-bad-arg.stderr | 10 ++++++---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 45d9f79c28fc3..37310f46f7eed 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -278,7 +278,7 @@ impl<'a, 'b> Context<'a, 'b> { /// format string. fn report_invalid_references(&self, numbered_position_args: bool) { let mut e; - let sp = if self.is_literal { + let sp = if self.is_literal { // Point at the formatting arguments. MultiSpan::from_spans(self.arg_spans.clone()) } else { MultiSpan::from_span(self.fmtsp) @@ -304,6 +304,9 @@ impl<'a, 'b> Context<'a, 'b> { self.describe_num_args(), ), ); + for arg in &self.args { // Point at the arguments that will be formatted. + e.span_label(arg.span, ""); + } } else { let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip(); // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)` diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs index cca949aab6364..691c06a2402c5 100644 --- a/src/test/ui/fmt/format-string-error.rs +++ b/src/test/ui/fmt/format-string-error.rs @@ -48,4 +48,6 @@ fn main() { "###); //~^^^ ERROR invalid format string: unmatched `}` found + println!("{} {} {}", 1, 2); + //~^ ERROR 3 positional arguments in format string, but there are 2 arguments } diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 3dc122a7399dd..32119b18774b2 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -107,5 +107,11 @@ LL | } | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to 12 previous errors +error: 3 positional arguments in format string, but there are 2 arguments + --> $DIR/format-string-error.rs:51:15 + | +LL | println!("{} {} {}", 1, 2); + | ^^ ^^ ^^ - - + +error: aborting due to 13 previous errors diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index 336ea2254bf5a..c58cbc312335a 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -224,8 +224,9 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:78:15 | LL | println!("{} {:.*} {}", 1, 3.2, 4); - | ^^ ^^--^ ^^ --- this parameter corresponds to the precision flag - | | + | ^^ ^^--^ ^^ - --- - + | | | + | | this parameter corresponds to the precision flag | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | = note: positional arguments are zero-based @@ -235,8 +236,9 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:81:15 | LL | println!("{} {:07$.*} {}", 1, 3.2, 4); - | ^^ ^^^----^ ^^ --- this parameter corresponds to the precision flag - | | | + | ^^ ^^^----^ ^^ - --- - + | | | | + | | | this parameter corresponds to the precision flag | | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | this width flag expects an `usize` argument at position 7, but there are 3 arguments |