From 1288883932e04317cbf075989cfc17369bff038c Mon Sep 17 00:00:00 2001 From: Elias Holzmann <9659253+EliasHolzmann@users.noreply.github.com> Date: Sat, 30 Apr 2022 02:38:22 +0200 Subject: [PATCH 1/5] std::fmt: Fixed documentation for specifying precision via `.*` The documentation stated that in case of the syntax `{:.*}`, "the `` part refers to the value to print, and the precision must come in the input preceding ``". This is not correct: the part does indeed refer to the value to print, but the precision does not come in the input preciding arg, but in the next implicit input (as if specified with {}). Fixes #96413. --- library/alloc/src/fmt.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 501a6353b2c..5f6849a9b63 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -221,10 +221,12 @@ //! //! 3. An asterisk `.*`: //! -//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the -//! first input holds the `usize` precision, and the second holds the value to print. Note that -//! in this case, if one uses the format string `{:.*}`, then the `` part refers -//! to the *value* to print, and the `precision` must come in the input preceding ``. +//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: +//! - If a format string in the fashion of `{:.*}` is used, then the first input holds +//! the `usize` precision, and the second holds the value to print. +//! - If a format string in the fashion of `{:.*}` is used, then the `` part +//! refers to the value to print, and the `precision` is taken like it was specified with an +//! omitted positional parameter (`{}` instead of `{:}`). //! //! For example, the following calls all print the same thing `Hello x is 0.01000`: //! @@ -242,8 +244,12 @@ //! // specified in first of next two args (5)} //! println!("Hello {} is {:.*}", "x", 5, 0.01); //! +//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision +//! // specified in next arg (5)} +//! println!("Hello {1} is {2:.*}", 5, "x", 0.01); +//! //! // Hello {next arg ("x")} is {arg 2 (0.01) with precision -//! // specified in its predecessor (5)} +//! // specified in next arg (5)} //! println!("Hello {} is {2:.*}", "x", 5, 0.01); //! //! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified From afd80a21b0fd2fb378e01a49b95d9a7d61536ca6 Mon Sep 17 00:00:00 2001 From: Elias Holzmann <9659253+EliasHolzmann@users.noreply.github.com> Date: Sat, 30 Apr 2022 02:39:27 +0200 Subject: [PATCH 2/5] std::fmt: Added argument index comments to examples for specifying precision The examples for specifying the precision have comments explaining which argument the specifier is referring to. However, for implicit positional arguments, the examples simply talk about "next arg". To make it easier for readers to follow the comments, "next arg" was supplemented with the actual resulting argument index. --- library/alloc/src/fmt.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 5f6849a9b63..361e821dd37 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -240,19 +240,19 @@ //! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)} //! println!("Hello {0} is {2:.1$}", "x", 5, 0.01); //! -//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision -//! // specified in first of next two args (5)} +//! // Hello {next arg -> arg 0 ("x")} is {second of next two args -> arg 2 (0.01) with precision +//! // specified in first of next two args -> arg 1 (5)} //! println!("Hello {} is {:.*}", "x", 5, 0.01); //! //! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision -//! // specified in next arg (5)} +//! // specified in next arg -> arg 0 (5)} //! println!("Hello {1} is {2:.*}", 5, "x", 0.01); //! -//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision -//! // specified in next arg (5)} +//! // Hello {next arg -> arg 0 ("x")} is {arg 2 (0.01) with precision +//! // specified in next arg -> arg 1 (5)} //! println!("Hello {} is {2:.*}", "x", 5, 0.01); //! -//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified +//! // Hello {next arg -> arg 0 ("x")} is {arg "number" (0.01) with precision specified //! // in arg "prec" (5)} //! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); //! ``` From 79d9afda137cfeb30cefdce397851b8e20db4ae1 Mon Sep 17 00:00:00 2001 From: Elias Holzmann <9659253+EliasHolzmann@users.noreply.github.com> Date: Sat, 30 Apr 2022 02:39:59 +0200 Subject: [PATCH 3/5] std::fmt: Fix the grammar documentation According to the grammar documented, the format specifier `{: }` should not be legal because of the whitespace it contains. However, in reality, this is perfectly fine because the actual implementation allows spaces before the closing brace. Fixes #71088. Also, the exact meaning of most of the terminal symbols was not specified, for example the meaning of `identifier`. --- library/alloc/src/fmt.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 361e821dd37..7b12f6e86c1 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -310,7 +310,7 @@ //! ```text //! format_string := text [ maybe_format text ] * //! maybe_format := '{' '{' | '}' '}' | format -//! format := '{' [ argument ] [ ':' format_spec ] '}' +//! format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}' //! argument := integer | identifier //! //! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type @@ -323,7 +323,12 @@ //! count := parameter | integer //! parameter := argument '$' //! ``` -//! In the above grammar, `text` must not contain any `'{'` or `'}'` characters. +//! In the above grammar, +//! - `text` must not contain any `'{'` or `'}'` characters, +//! - `ws` is any character for which [`char::is_whitespace`] returns `true`, has no semantic +//! meaning and is completely optional, +//! - `integer` is a decimal integer that may contain leading zeroes and +//! - `identifier` is an `IDENTIFIER_OR_KEYWORD` (not an `IDENTIFIER`) as defined by the [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html). //! //! # Formatting traits //! From c70f3ab5e53916a2e0210a24b67c64f2b700a06f Mon Sep 17 00:00:00 2001 From: Elias Holzmann <9659253+EliasHolzmann@users.noreply.github.com> Date: Sat, 30 Apr 2022 02:40:39 +0200 Subject: [PATCH 4/5] std::fmt: Removed reference to Formatter::buf and other private fields Formatter::buf is not a public field and therefore isn't very helpful in user- facing documentation. Also, the other public fields of Formatter were made private during stabilization of std::fmt (4af3494bb0) and can now only be read via accessor methods. --- library/alloc/src/fmt.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 7b12f6e86c1..635a3ffa3c5 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -369,9 +369,9 @@ //! ``` //! //! Your type will be passed as `self` by-reference, and then the function -//! should emit output into the `f.buf` stream. It is up to each format trait -//! implementation to correctly adhere to the requested formatting parameters. -//! The values of these parameters will be listed in the fields of the +//! should emit output into the Formatter `f` which implements `fmt::Write`. It is up to each +//! format trait implementation to correctly adhere to the requested formatting parameters. +//! The values of these parameters can be accessed with methods of the //! [`Formatter`] struct. In order to help with this, the [`Formatter`] struct also //! provides some helper methods. //! From f3b86c37ebdddbc7555ba560b6c4b4f4d44f991d Mon Sep 17 00:00:00 2001 From: Elias Holzmann <9659253+EliasHolzmann@users.noreply.github.com> Date: Sat, 30 Apr 2022 02:41:32 +0200 Subject: [PATCH 5/5] std::fmt: Improved list of formatting macros Two improvements: 1. write! can not only receive a `io::Write`, but also a `fmt::Write` as first argument. 2. The description texts now contain links to the actual macros for easier navigation. --- library/alloc/src/fmt.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 635a3ffa3c5..73b75ea4d83 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -460,7 +460,7 @@ //! //! ```ignore (only-for-syntax-highlight) //! format! // described above -//! write! // first argument is a &mut io::Write, the destination +//! write! // first argument is either a &mut io::Write or a &mut fmt::Write, the destination //! writeln! // same as write but appends a newline //! print! // the format string is printed to the standard output //! println! // same as print but appends a newline @@ -471,11 +471,11 @@ //! //! ### `write!` //! -//! This and [`writeln!`] are two macros which are used to emit the format string +//! [`write!`] and [`writeln!`] are two macros which are used to emit the format string //! to a specified stream. This is used to prevent intermediate allocations of //! format strings and instead directly write the output. Under the hood, this //! function is actually invoking the [`write_fmt`] function defined on the -//! [`std::io::Write`] trait. Example usage is: +//! [`std::io::Write`] and the [`std::fmt::Write`] trait. Example usage is: //! //! ``` //! # #![allow(unused_must_use)] @@ -502,7 +502,7 @@ //! //! ### `format_args!` //! -//! This is a curious macro used to safely pass around +//! [`format_args!`] is a curious macro used to safely pass around //! an opaque object describing the format string. This object //! does not require any heap allocations to create, and it only //! references information on the stack. Under the hood, all of @@ -540,10 +540,12 @@ //! [`to_string`]: crate::string::ToString::to_string "ToString::to_string" //! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt //! [`std::io::Write`]: ../../std/io/trait.Write.html +//! [`std::fmt::Write`]: ../../std/fmt/trait.Write.html //! [`print!`]: ../../std/macro.print.html "print!" //! [`println!`]: ../../std/macro.println.html "println!" //! [`eprint!`]: ../../std/macro.eprint.html "eprint!" //! [`eprintln!`]: ../../std/macro.eprintln.html "eprintln!" +//! [`format_args!`]: ../../std/macro.format_args.html "format_args!" //! [`fmt::Arguments`]: Arguments "fmt::Arguments" //! [`format`]: format() "fmt::format"