From 455723c638b0e9db34d427a82bc13f95b75a304d Mon Sep 17 00:00:00 2001 From: Daniel Keep Date: Fri, 11 Nov 2016 15:23:15 +1100 Subject: 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. --- src/test/compile-fail/ifmt-bad-arg.rs | 3 ++ src/test/ui/macros/format-foreign.rs | 20 ++++++++++++ src/test/ui/macros/format-foreign.stderr | 52 ++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/test/ui/macros/format-foreign.rs create mode 100644 src/test/ui/macros/format-foreign.stderr (limited to 'src/test') diff --git a/src/test/compile-fail/ifmt-bad-arg.rs b/src/test/compile-fail/ifmt-bad-arg.rs index 59c61a42e07..a23b4b07741 100644 --- a/src/test/compile-fail/ifmt-bad-arg.rs +++ b/src/test/compile-fail/ifmt-bad-arg.rs @@ -17,6 +17,7 @@ fn main() { //~^ ERROR: argument never used format!("{foo}"); //~ ERROR: no argument named `foo` + format!("", 1, 2); //~ ERROR: multiple unused formatting arguments format!("{}", 1, 2); //~ ERROR: argument never used format!("{1}", 1, 2); //~ ERROR: argument never used format!("{}", 1, foo=2); //~ ERROR: named argument never used @@ -53,4 +54,6 @@ fn main() { format!("foo } bar"); //~ ERROR: unmatched `}` found format!("foo }"); //~ ERROR: unmatched `}` found + + format!("foo %s baz", "bar"); //~ ERROR: argument never used } diff --git a/src/test/ui/macros/format-foreign.rs b/src/test/ui/macros/format-foreign.rs new file mode 100644 index 00000000000..cca45ca9ecd --- /dev/null +++ b/src/test/ui/macros/format-foreign.rs @@ -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 or the MIT license +// , 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"); +} diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr new file mode 100644 index 00000000000..0283052a89f --- /dev/null +++ b/src/test/ui/macros/format-foreign.stderr @@ -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 + -- cgit 1.4.1-3-g733a5