From 252ad18415723a7485b0e2950f1b641109c9d4ef Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 7 Feb 2025 14:53:34 +0100 Subject: [PATCH 1/4] Improve the documentation of `Display` and `FromStr`, and their interactions In particular: - `Display` is not necessarily lossless - The output of `Display` might not be parseable by `FromStr`, and might not produce the same value if it is. - Calling `.parse()` on the output of `Display` is usually a mistake unless a type's documented output and input formats match. - The input formats accepted by `FromStr` depend on the type. --- library/core/src/fmt/mod.rs | 9 +++++++++ library/core/src/str/traits.rs | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 5978cb660f6b3..c25ef9ba512f3 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -928,6 +928,15 @@ pub use macros::Debug; /// [tostring]: ../../std/string/trait.ToString.html /// [tostring_function]: ../../std/string/trait.ToString.html#tymethod.to_string /// +/// # Completeness and parseability +/// +/// `Display` for a type might not necessarily be a lossless or complete representation of the type. +/// It may omit internal state, precision, or other information the type does not consider important +/// for user-facing output, as determined by the type. As such, the output of `Display` might not be +/// possible to parse, and even if it is, the result of parsing might not exactly match the original +/// value. Calling `.parse()` on the output from `Display` is usually a mistake, unless the type has +/// provided and documented additional guarantees about its `Display` and `FromStr` implementations. +/// /// # Internationalization /// /// Because a type can only have one `Display` implementation, it is often preferable diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 4baf9aacad7b3..85d5fa1ef923f 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -756,6 +756,15 @@ unsafe impl SliceIndex for ops::RangeToInclusive { /// parse an `i32` with `FromStr`, but not a `&i32`. You can parse a struct that /// contains an `i32`, but not one that contains an `&i32`. /// +/// # Input format +/// +/// The input format expected by a type's `FromStr` implementation depends on the type. Check the +/// type's documentation for the input formats it knows how to parse. Note that the input format of +/// a type's `FromStr` implementation might not necessarily accept the output format of its +/// `Display` implementation; thus, calling `.parse()` on the output from `Display` is usually a +/// mistake, unless the type has provided and documented additional guarantees about its `Display` +/// and `FromStr` implementations. +/// /// # Examples /// /// Basic implementation of `FromStr` on an example `Point` type: From f412d05e50d0a682502e225b41db77bf4aa302e2 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 7 Feb 2025 15:31:55 +0100 Subject: [PATCH 2/4] Add some more description of interactions between `Display` and `FromStr` --- library/core/src/str/traits.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 85d5fa1ef923f..2f425c82dc8bd 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -765,6 +765,12 @@ unsafe impl SliceIndex for ops::RangeToInclusive { /// mistake, unless the type has provided and documented additional guarantees about its `Display` /// and `FromStr` implementations. /// +/// If a type happens to have a lossless `Display` implementation whose output is meant to be +/// conveniently machine-parseable and not just meant for human consumption, then the type may wish +/// to accept the same format in `FromStr`, and document that usage. Having both `Display` and +/// `FromStr` implementations where the result of `Display` cannot be parsed with `FromStr` may +/// surprise users. (However, the result of such parsing may not have the same value as the input.) +/// /// # Examples /// /// Basic implementation of `FromStr` on an example `Point` type: From 7ba5d26636b61ffbbefe1999254e66348e652c1a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 3 Jun 2025 15:34:37 -0700 Subject: [PATCH 3/4] `FromStr`: Rework explanation of `FromStr`/`Display` round-tripping - Drop the phrasing "usually a mistake". - Mention that `Display` may not be lossless. - Drop a misplaced parenthetical about round-tripping that didn't fit the paragraph it was in. --- library/core/src/str/traits.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 2f425c82dc8bd..b9559c8317133 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -756,20 +756,19 @@ unsafe impl SliceIndex for ops::RangeToInclusive { /// parse an `i32` with `FromStr`, but not a `&i32`. You can parse a struct that /// contains an `i32`, but not one that contains an `&i32`. /// -/// # Input format +/// # Input format and round-tripping /// /// The input format expected by a type's `FromStr` implementation depends on the type. Check the /// type's documentation for the input formats it knows how to parse. Note that the input format of /// a type's `FromStr` implementation might not necessarily accept the output format of its -/// `Display` implementation; thus, calling `.parse()` on the output from `Display` is usually a -/// mistake, unless the type has provided and documented additional guarantees about its `Display` -/// and `FromStr` implementations. +/// `Display` implementation, and even if it does, the `Display` implementation may not be lossless +/// so the round-trip may lose information. /// -/// If a type happens to have a lossless `Display` implementation whose output is meant to be +/// However, if a type has a lossless `Display` implementation whose output is meant to be /// conveniently machine-parseable and not just meant for human consumption, then the type may wish /// to accept the same format in `FromStr`, and document that usage. Having both `Display` and /// `FromStr` implementations where the result of `Display` cannot be parsed with `FromStr` may -/// surprise users. (However, the result of such parsing may not have the same value as the input.) +/// surprise users. /// /// # Examples /// From 742014e7e3576f3053e7c63fc930c4d5b5b7a477 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 3 Jun 2025 15:39:46 -0700 Subject: [PATCH 4/4] `Display`: Rework explanation of `FromStr`/`Display` round-tripping - Drop "usually a mistake" - Add phrasing from `FromStr` about round-tripping, and about how the inability to round-trip may surprise users. --- library/core/src/fmt/mod.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index c25ef9ba512f3..145e581d1fb51 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -934,8 +934,13 @@ pub use macros::Debug; /// It may omit internal state, precision, or other information the type does not consider important /// for user-facing output, as determined by the type. As such, the output of `Display` might not be /// possible to parse, and even if it is, the result of parsing might not exactly match the original -/// value. Calling `.parse()` on the output from `Display` is usually a mistake, unless the type has -/// provided and documented additional guarantees about its `Display` and `FromStr` implementations. +/// value. +/// +/// However, if a type has a lossless `Display` implementation whose output is meant to be +/// conveniently machine-parseable and not just meant for human consumption, then the type may wish +/// to accept the same format in `FromStr`, and document that usage. Having both `Display` and +/// `FromStr` implementations where the result of `Display` cannot be parsed with `FromStr` may +/// surprise users. /// /// # Internationalization ///