Rollup merge of #37613 - DanielKeep:eww-you-got-printf-in-your-format, r=alexcrichton
Add foreign formatting directive detection.
This teaches `format_args!` how to interpret format printf- and
shell-style format directives. This is used in cases where there are
unused formatting arguments, and the reason for that *might* be because
the programmer is trying to use the wrong kind of formatting string.
This was prompted by an issue encountered by simulacrum on the #rust IRC
channel. In short: although `println!` told them that they weren't using
all of the conversion arguments, the problem was in using printf-syle
directives rather than ones `println!` would undertand.
Where possible, `format_args!` will tell the programmer what they should
use instead. For example, it will suggest replacing `%05d` with `{:0>5}`,
or `%2$.*3$s` with `{1:.3$}`. Even if it cannot suggest a replacement,
it will explicitly note that Rust does not support that style of directive,
and direct the user to the `std::fmt` documentation.
-----
**Example**: given:
```rust
fn main() {
println!("%.*3$s %s!\n", "Hello,", "World", 4);
println!("%1$*2$.*3$f", 123.456);
}
```
The compiler outputs the following:
```text
error: multiple unused formatting arguments
--> local/fmt.rs:2:5
|
2 | println!("%.*3$s %s!\n", "Hello,", "World", 4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: argument never used
--> local/fmt.rs:2:30
|
2 | println!("%.*3$s %s!\n", "Hello,", "World", 4);
| ^^^^^^^^
note: argument never used
--> local/fmt.rs:2:40
|
2 | println!("%.*3$s %s!\n", "Hello,", "World", 4);
| ^^^^^^^
note: argument never used
--> local/fmt.rs:2:49
|
2 | println!("%.*3$s %s!\n", "Hello,", "World", 4);
| ^
= help: `%.*3$s` should be written as `{:.2$}`
= help: `%s` should be written as `{}`
= note: printf formatting not supported; see the documentation for `std::fmt`
= note: this error originates in a macro outside of the current crate
error: argument never used
--> local/fmt.rs:6:29
|
6 | println!("%1$*2$.*3$f", 123.456);
| ^^^^^^^
|
= help: `%1$*2$.*3$f` should be written as `{0:1$.2$}`
= note: printf formatting not supported; see the documentation for `std::fmt`
```
This commit is contained in:
commit
b619dcdaeb
6 changed files with 1163 additions and 2 deletions
20
src/test/ui/macros/format-foreign.rs
Normal file
20
src/test/ui/macros/format-foreign.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
println!("%.*3$s %s!\n", "Hello,", "World", 4);
|
||||
println!("%1$*2$.*3$f", 123.456);
|
||||
|
||||
// This should *not* produce hints, on the basis that there's equally as
|
||||
// many "correct" format specifiers. It's *probably* just an actual typo.
|
||||
println!("{} %f", "one", 2.0);
|
||||
|
||||
println!("Hi there, $NAME.", NAME="Tim");
|
||||
}
|
||||
52
src/test/ui/macros/format-foreign.stderr
Normal file
52
src/test/ui/macros/format-foreign.stderr
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
error: multiple unused formatting arguments
|
||||
--> $DIR/format-foreign.rs:12:5
|
||||
|
|
||||
12 | println!("%.*3$s %s!/n", "Hello,", "World", 4);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: argument never used
|
||||
--> $DIR/format-foreign.rs:12:30
|
||||
|
|
||||
12 | println!("%.*3$s %s!/n", "Hello,", "World", 4);
|
||||
| ^^^^^^^^
|
||||
note: argument never used
|
||||
--> $DIR/format-foreign.rs:12:40
|
||||
|
|
||||
12 | println!("%.*3$s %s!/n", "Hello,", "World", 4);
|
||||
| ^^^^^^^
|
||||
note: argument never used
|
||||
--> $DIR/format-foreign.rs:12:49
|
||||
|
|
||||
12 | println!("%.*3$s %s!/n", "Hello,", "World", 4);
|
||||
| ^
|
||||
= help: `%.*3$s` should be written as `{:.2$}`
|
||||
= help: `%s` should be written as `{}`
|
||||
= note: printf formatting not supported; see the documentation for `std::fmt`
|
||||
= note: this error originates in a macro outside of the current crate
|
||||
|
||||
error: argument never used
|
||||
--> $DIR/format-foreign.rs:13:29
|
||||
|
|
||||
13 | println!("%1$*2$.*3$f", 123.456);
|
||||
| ^^^^^^^
|
||||
|
|
||||
= help: `%1$*2$.*3$f` should be written as `{0:1$.2$}`
|
||||
= note: printf formatting not supported; see the documentation for `std::fmt`
|
||||
|
||||
error: argument never used
|
||||
--> $DIR/format-foreign.rs:17:30
|
||||
|
|
||||
17 | println!("{} %f", "one", 2.0);
|
||||
| ^^^
|
||||
|
||||
error: named argument never used
|
||||
--> $DIR/format-foreign.rs:19:39
|
||||
|
|
||||
19 | println!("Hi there, $NAME.", NAME="Tim");
|
||||
| ^^^^^
|
||||
|
|
||||
= help: `$NAME` should be written as `{NAME}`
|
||||
= note: shell formatting not supported; see the documentation for `std::fmt`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue