From 62187b12c202c1ada2569211da090d16950c3640 Mon Sep 17 00:00:00 2001 From: miam-miam100 <49870539+miam-miam100@users.noreply.github.com> Date: Tue, 19 Jul 2022 22:25:26 +0100 Subject: [PATCH 1/2] Add diagnostic width span when '0$' is used as width. --- compiler/rustc_parse_format/src/lib.rs | 3 ++- compiler/rustc_parse_format/src/tests.rs | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index f6fa19030acb9..6e7553f5e496b 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -572,9 +572,10 @@ impl<'a> Parser<'a> { // '0' flag and then an ill-formatted format string with just a '$' // and no count, but this is better if we instead interpret this as // no '0' flag and '0$' as the width instead. - if self.consume('$') { + if let Some(end) = self.consume_pos('$') { spec.width = CountIsParam(0); havewidth = true; + spec.width_span = Some(self.to_span_index(end - 1).to(self.to_span_index(end + 1))); } else { spec.flags |= 1 << (FlagSignAwareZeroPad as u32); } diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index c9667922ee7c3..9c305b4996a13 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -178,6 +178,23 @@ fn format_counts() { }, })], ); + same( + "{1:0$.10x}", + &[NextArgument(Argument { + position: ArgumentIs(1), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountIs(10), + width: CountIsParam(0), + precision_span: None, + width_span: Some(InnerSpan::new(4, 6)), + ty: "x", + ty_span: None, + }, + })], + ); same( "{:.*x}", &[NextArgument(Argument { From f8dfc4bf350bad5140a7d1e7a9030b91dbdc4ce4 Mon Sep 17 00:00:00 2001 From: miam-miam100 <49870539+miam-miam100@users.noreply.github.com> Date: Wed, 20 Jul 2022 13:40:45 +0100 Subject: [PATCH 2/2] Fix off by one error and add ui test. --- compiler/rustc_builtin_macros/src/format.rs | 2 +- src/test/ui/fmt/ifmt-bad-arg.rs | 3 +++ src/test/ui/fmt/ifmt-bad-arg.stderr | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 3b7e2102ffa9b..bce466921d0ff 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -485,7 +485,7 @@ impl<'a, 'b> Context<'a, 'b> { if let Some(span) = fmt.width_span { let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end)); match fmt.width { - parse::CountIsParam(pos) if pos > self.num_args() => { + parse::CountIsParam(pos) if pos >= self.num_args() => { e.span_label( span, &format!( diff --git a/src/test/ui/fmt/ifmt-bad-arg.rs b/src/test/ui/fmt/ifmt-bad-arg.rs index b3e54ed32aac7..84f4cc7f4ccd8 100644 --- a/src/test/ui/fmt/ifmt-bad-arg.rs +++ b/src/test/ui/fmt/ifmt-bad-arg.rs @@ -86,6 +86,9 @@ tenth number: {}", println!("{:foo}", 1); //~ ERROR unknown format trait `foo` println!("{5} {:4$} {6:7$}", 1); //~^ ERROR invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument) + let foo = 1; + println!("{foo:0$}"); + //~^ ERROR invalid reference to positional argument 0 (no arguments were given) // We used to ICE here because we tried to unconditionally access the first argument, which // doesn't exist. diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr index d181fe14107e7..5439ee173985b 100644 --- a/src/test/ui/fmt/ifmt-bad-arg.stderr +++ b/src/test/ui/fmt/ifmt-bad-arg.stderr @@ -251,8 +251,19 @@ LL | println!("{5} {:4$} {6:7$}", 1); = note: positional arguments are zero-based = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html +error: invalid reference to positional argument 0 (no arguments were given) + --> $DIR/ifmt-bad-arg.rs:90:15 + | +LL | println!("{foo:0$}"); + | ^^^^^--^ + | | + | this width flag expects an `usize` argument at position 0, but no arguments were given + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + error: 2 positional arguments in format string, but no arguments were given - --> $DIR/ifmt-bad-arg.rs:92:15 + --> $DIR/ifmt-bad-arg.rs:95:15 | LL | println!("{:.*}"); | ^^--^ @@ -328,7 +339,7 @@ LL | pub fn from_usize(x: &usize) -> ArgumentV1<'_> { | ^^^^^^^^^^ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 36 previous errors +error: aborting due to 37 previous errors Some errors have detailed explanations: E0308, E0425. For more information about an error, try `rustc --explain E0308`.