diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-07-20 18:58:17 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-20 18:58:17 +0200 |
| commit | 9e197b75f0e5ad17dc1bb1431853bd4df7cff408 (patch) | |
| tree | 68b799e1e2bba41291b34e52e832e7900571c9ce | |
| parent | 82d9ae9ca1a21ba1fa5648e03395ade87ca762f0 (diff) | |
| parent | f8dfc4bf350bad5140a7d1e7a9030b91dbdc4ce4 (diff) | |
| download | rust-9e197b75f0e5ad17dc1bb1431853bd4df7cff408.tar.gz rust-9e197b75f0e5ad17dc1bb1431853bd4df7cff408.zip | |
Rollup merge of #99480 - miam-miam100:arg-format, r=oli-obk
Diagnostic width span is not added when '0$' is used as width in format strings
When the following code is run rustc does not add diagnostic spans for the width argument. Such spans are necessary for a clippy lint that I am currently writing.
```rust
println!("Hello {1:0$}!", 5, "x");
// ^^
// Should have a span here
```
| -rw-r--r-- | compiler/rustc_builtin_macros/src/format.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse_format/src/lib.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_parse_format/src/tests.rs | 17 | ||||
| -rw-r--r-- | src/test/ui/fmt/ifmt-bad-arg.rs | 3 | ||||
| -rw-r--r-- | src/test/ui/fmt/ifmt-bad-arg.stderr | 15 |
5 files changed, 36 insertions, 4 deletions
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 3b7e2102ffa..bce466921d0 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/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index f6fa19030ac..6e7553f5e49 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 c9667922ee7..9c305b4996a 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -179,6 +179,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 { position: ArgumentImplicitlyIs(1), diff --git a/src/test/ui/fmt/ifmt-bad-arg.rs b/src/test/ui/fmt/ifmt-bad-arg.rs index b3e54ed32aa..84f4cc7f4cc 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 d181fe14107..5439ee17398 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`. |
