From d2b1212558b25e69eb867402792d5b5b5a07ad19 Mon Sep 17 00:00:00 2001 From: Simon Heath Date: Wed, 30 Jan 2019 19:42:37 -0500 Subject: [PATCH 1/8] Started expanding docs for `TryFrom` and `TryInto`. The examples are still lacking for now, both for module docs and for methods/impl's. --- src/libcore/convert.rs | 44 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 5ecfa9cde032e..a3f1a3201f318 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -366,6 +366,11 @@ pub trait From: Sized { /// provides an equivalent `TryInto` implementation for free, thanks to a /// blanket implementation in the standard library. For more information on this, /// see the documentation for [`Into`]. +/// +/// # Implementing `TryInto` +/// +/// This suffers the same restrictions and reasoning as implementing +/// [`Into`], see there for details. /// /// [`TryFrom`]: trait.TryFrom.html /// [`Into`]: trait.Into.html @@ -380,7 +385,44 @@ pub trait TryInto: Sized { fn try_into(self) -> Result; } -/// Attempt to construct `Self` via a conversion. +/// Simple and safe type conversions that may fail in a controlled +/// way under some circumstances. It is the reciprocal of [`TryInto`]. +/// +/// This is useful when you are doing a type conversion that may +/// trivially succeed but may also need special handling. +/// For example, there is no way to convert an `i64` into an `i32` +/// using the [`From`] trait, because an `i64` may contain a value +/// that an `i32` cannot represent and so the conversion would lose data. +/// This might be handled by truncating the `i64` to an `i32` (essentially +/// giving the `i64`'s value modulo `i32::MAX`) or by simply returning +/// `i32::MAX`, or by some other method. The `From` trait is intended +/// for lossless conversions, so the `TryFrom` trait informs the +/// programmer when a type conversion could go bad and lets them +/// decide how to handle it. +/// +/// # Generic Implementations +/// +/// - `TryFrom for U` implies [`TryInto`]` for T` +/// - [`try_from`] is reflexive, which means that `TryFrom for T` +/// is implemented +/// +/// # Examples +/// +/// As described, [`i32`] implements `TryFrom`: +/// +/// ``` +/// let big_number = 1_000_000_000_000i64; +/// // Silently truncates `big_number`, requires detecting +/// // and handling the truncation after the fact. +/// let smaller_number = big_number as i32; +/// assert_eq!(smaller_number, -727379968); +/// +/// let try_smaller_number = i32::try_from(big_number); +/// assert!(try_smaller_number.is_err()); +/// +/// let try_successful_smaller_number = i32::try_from(3); +/// assert!(try_successful_smaller_number.is_ok()); +/// ``` #[stable(feature = "try_from", since = "1.34.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. From 12532277d5bde13c19d3b40d34c07ec78c79ff71 Mon Sep 17 00:00:00 2001 From: Simon Heath Date: Wed, 30 Jan 2019 20:19:01 -0500 Subject: [PATCH 2/8] Add basic docs to integer TryFrom impl macros. They're not as good as `From` 'cause they don't stringify the types and generate examples and so on, but it's a start. --- src/libcore/num/mod.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 3ceba83afeef8..39a1b48e0766e 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4544,6 +4544,9 @@ macro_rules! try_from_unbounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; + /// Try to create the target type from the source type. + /// This particular variant will never fail, but is included + /// for completeness's sake. #[inline] fn try_from(value: $source) -> Result { Ok(value as $target) @@ -4559,6 +4562,10 @@ macro_rules! try_from_lower_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; + /// Try to create a target number type from a + /// source type that has `source::MIN > dest::MIN`. + /// Will return an error if `source` is less than + /// `dest::MIN`. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { if u >= 0 { @@ -4578,6 +4585,10 @@ macro_rules! try_from_upper_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; + /// Try to create a target number type from a + /// source type that has `source::MAX > dest::MAX`. + /// Will return an error if `source` is greater than + /// `dest::MAX`. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { if u > (<$target>::max_value() as $source) { @@ -4597,6 +4608,11 @@ macro_rules! try_from_both_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; + /// Try to "narrow" a number from the source type + /// to the target type. Will return an error if + /// the source value is either larger than the + /// `MAX` value for the target type or smaller + /// than the `MIN` value for it. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { let min = <$target>::min_value() as $source; From c1d1c6731c22a2840eecd72b9bfb4ffc6f05647b Mon Sep 17 00:00:00 2001 From: Simon Heath Date: Thu, 31 Jan 2019 21:47:18 -0500 Subject: [PATCH 3/8] Fix a bunch of heckin' trailing whitespace --- src/libcore/convert.rs | 24 ++++++++++++------------ src/libcore/num/mod.rs | 10 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index a3f1a3201f318..f64f2fb3e9faa 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -366,9 +366,9 @@ pub trait From: Sized { /// provides an equivalent `TryInto` implementation for free, thanks to a /// blanket implementation in the standard library. For more information on this, /// see the documentation for [`Into`]. -/// +/// /// # Implementing `TryInto` -/// +/// /// This suffers the same restrictions and reasoning as implementing /// [`Into`], see there for details. /// @@ -387,25 +387,25 @@ pub trait TryInto: Sized { /// Simple and safe type conversions that may fail in a controlled /// way under some circumstances. It is the reciprocal of [`TryInto`]. -/// -/// This is useful when you are doing a type conversion that may +/// +/// This is useful when you are doing a type conversion that may /// trivially succeed but may also need special handling. /// For example, there is no way to convert an `i64` into an `i32` /// using the [`From`] trait, because an `i64` may contain a value /// that an `i32` cannot represent and so the conversion would lose data. /// This might be handled by truncating the `i64` to an `i32` (essentially -/// giving the `i64`'s value modulo `i32::MAX`) or by simply returning -/// `i32::MAX`, or by some other method. The `From` trait is intended -/// for lossless conversions, so the `TryFrom` trait informs the +/// giving the `i64`'s value modulo `i32::MAX`) or by simply returning +/// `i32::MAX`, or by some other method. The `From` trait is intended +/// for lossless conversions, so the `TryFrom` trait informs the /// programmer when a type conversion could go bad and lets them /// decide how to handle it. -/// +/// /// # Generic Implementations /// /// - `TryFrom for U` implies [`TryInto`]` for T` -/// - [`try_from`] is reflexive, which means that `TryFrom for T` +/// - [`try_from`] is reflexive, which means that `TryFrom for T` /// is implemented -/// +/// /// # Examples /// /// As described, [`i32`] implements `TryFrom`: @@ -416,10 +416,10 @@ pub trait TryInto: Sized { /// // and handling the truncation after the fact. /// let smaller_number = big_number as i32; /// assert_eq!(smaller_number, -727379968); -/// +/// /// let try_smaller_number = i32::try_from(big_number); /// assert!(try_smaller_number.is_err()); -/// +/// /// let try_successful_smaller_number = i32::try_from(3); /// assert!(try_successful_smaller_number.is_ok()); /// ``` diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 39a1b48e0766e..d8e230abaf9b9 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4564,7 +4564,7 @@ macro_rules! try_from_lower_bounded { /// Try to create a target number type from a /// source type that has `source::MIN > dest::MIN`. - /// Will return an error if `source` is less than + /// Will return an error if `source` is less than /// `dest::MIN`. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { @@ -4587,7 +4587,7 @@ macro_rules! try_from_upper_bounded { /// Try to create a target number type from a /// source type that has `source::MAX > dest::MAX`. - /// Will return an error if `source` is greater than + /// Will return an error if `source` is greater than /// `dest::MAX`. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { @@ -4609,9 +4609,9 @@ macro_rules! try_from_both_bounded { type Error = TryFromIntError; /// Try to "narrow" a number from the source type - /// to the target type. Will return an error if - /// the source value is either larger than the - /// `MAX` value for the target type or smaller + /// to the target type. Will return an error if + /// the source value is either larger than the + /// `MAX` value for the target type or smaller /// than the `MIN` value for it. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { From cc6f394d6f1ea4f452a944685d422125a5f71ac3 Mon Sep 17 00:00:00 2001 From: Simon Heath Date: Wed, 13 Feb 2019 12:52:35 -0500 Subject: [PATCH 4/8] Fix some links in TryFrom docs. --- src/libcore/convert.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index f64f2fb3e9faa..4716aea1cdd50 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -361,11 +361,12 @@ pub trait From: Sized { /// An attempted conversion that consumes `self`, which may or may not be /// expensive. /// -/// Library authors should not directly implement this trait, but should prefer -/// implementing the [`TryFrom`] trait, which offers greater flexibility and -/// provides an equivalent `TryInto` implementation for free, thanks to a -/// blanket implementation in the standard library. For more information on this, -/// see the documentation for [`Into`]. +/// Library authors should usually not directly implement this trait, +/// but should prefer implementing the [`TryFrom`] trait, which offers +/// greater flexibility and provides an equivalent `TryInto` +/// implementation for free, thanks to a blanket implementation in the +/// standard library. For more information on this, see the +/// documentation for [`Into`]. /// /// # Implementing `TryInto` /// @@ -396,7 +397,7 @@ pub trait TryInto: Sized { /// This might be handled by truncating the `i64` to an `i32` (essentially /// giving the `i64`'s value modulo `i32::MAX`) or by simply returning /// `i32::MAX`, or by some other method. The `From` trait is intended -/// for lossless conversions, so the `TryFrom` trait informs the +/// for perfect conversions, so the `TryFrom` trait informs the /// programmer when a type conversion could go bad and lets them /// decide how to handle it. /// @@ -404,7 +405,8 @@ pub trait TryInto: Sized { /// /// - `TryFrom for U` implies [`TryInto`]` for T` /// - [`try_from`] is reflexive, which means that `TryFrom for T` -/// is implemented +/// is implemented and cannot fail -- the associated `Error` type for +/// calling `T::try_from()` on a value of type `T` is `!`. /// /// # Examples /// @@ -417,12 +419,18 @@ pub trait TryInto: Sized { /// let smaller_number = big_number as i32; /// assert_eq!(smaller_number, -727379968); /// +/// // Returns an error because `big_number` is too big to +/// // fit in an `i32`. /// let try_smaller_number = i32::try_from(big_number); /// assert!(try_smaller_number.is_err()); /// +/// // Returns `Ok(3)`. /// let try_successful_smaller_number = i32::try_from(3); /// assert!(try_successful_smaller_number.is_ok()); /// ``` +/// +/// [`try_from`]: trait.TryFrom.html#tymethod.try_from +/// [`TryInto`]: trait.TryInto.html #[stable(feature = "try_from", since = "1.34.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. From 72afe51d81dd0824a009e378e9142ca7236806aa Mon Sep 17 00:00:00 2001 From: Simon Heath Date: Thu, 14 Feb 2019 09:19:03 -0500 Subject: [PATCH 5/8] Slowly figuring out how rustdoc actually works. Unfortunately trying to run doctests on my local machine is not really faster than letting Travis do it... --- src/libcore/convert.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 4716aea1cdd50..a9d1d01ccbb41 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -413,6 +413,9 @@ pub trait TryInto: Sized { /// As described, [`i32`] implements `TryFrom`: /// /// ``` +/// #![feature(try_from)] +/// use std::convert::TryFrom; +/// /// let big_number = 1_000_000_000_000i64; /// // Silently truncates `big_number`, requires detecting /// // and handling the truncation after the fact. From 60cf413a20392ae38ffbf945e3d77f892655a74f Mon Sep 17 00:00:00 2001 From: Simon Heath Date: Tue, 26 Feb 2019 23:47:55 -0500 Subject: [PATCH 6/8] Incorporated review changes. --- src/libcore/convert.rs | 4 +++- src/libcore/num/mod.rs | 48 ++++++++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index a9d1d01ccbb41..0fc182348c6c2 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -406,7 +406,9 @@ pub trait TryInto: Sized { /// - `TryFrom for U` implies [`TryInto`]` for T` /// - [`try_from`] is reflexive, which means that `TryFrom for T` /// is implemented and cannot fail -- the associated `Error` type for -/// calling `T::try_from()` on a value of type `T` is `!`. +/// calling `T::try_from()` on a value of type `T` is `Infallible`. +/// When the `!` type is stablized `Infallible` and `!` will be +/// equivalent. /// /// # Examples /// diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index d8e230abaf9b9..4a2f958b93fe7 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4544,9 +4544,14 @@ macro_rules! try_from_unbounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; - /// Try to create the target type from the source type. - /// This particular variant will never fail, but is included - /// for completeness's sake. + /// Try to create the target number type from a source + /// number type. If the source type has a larger range + /// than the target, or their ranges are disjoint (such + /// as converting a signed to unsigned number or vice + /// versa), this will return `None` if the source value + /// doesn't fit into the range of the destination value. + /// If the conversion can never fail, this is still + /// implemented for completeness's sake. #[inline] fn try_from(value: $source) -> Result { Ok(value as $target) @@ -4562,10 +4567,14 @@ macro_rules! try_from_lower_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; - /// Try to create a target number type from a - /// source type that has `source::MIN > dest::MIN`. - /// Will return an error if `source` is less than - /// `dest::MIN`. + /// Try to create the target number type from a source + /// number type. If the source type has a larger range + /// than the target, or their ranges are disjoint (such + /// as converting a signed to unsigned number or vice + /// versa), this will return `None` if the source value + /// doesn't fit into the range of the destination value. + /// If the conversion can never fail, this is still + /// implemented for completeness's sake. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { if u >= 0 { @@ -4585,10 +4594,14 @@ macro_rules! try_from_upper_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; - /// Try to create a target number type from a - /// source type that has `source::MAX > dest::MAX`. - /// Will return an error if `source` is greater than - /// `dest::MAX`. + /// Try to create the target number type from a source + /// number type. If the source type has a larger range + /// than the target, or their ranges are disjoint (such + /// as converting a signed to unsigned number or vice + /// versa), this will return `None` if the source value + /// doesn't fit into the range of the destination value. + /// If the conversion can never fail, this is still + /// implemented for completeness's sake. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { if u > (<$target>::max_value() as $source) { @@ -4608,11 +4621,14 @@ macro_rules! try_from_both_bounded { impl TryFrom<$source> for $target { type Error = TryFromIntError; - /// Try to "narrow" a number from the source type - /// to the target type. Will return an error if - /// the source value is either larger than the - /// `MAX` value for the target type or smaller - /// than the `MIN` value for it. + /// Try to create the target number type from a source + /// number type. If the source type has a larger range + /// than the target, or their ranges are disjoint (such + /// as converting a signed to unsigned number or vice + /// versa), this will return `None` if the source value + /// doesn't fit into the range of the destination value. + /// If the conversion can never fail, this is still + /// implemented for completeness's sake. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { let min = <$target>::min_value() as $source; From 5dce719520a49b305b668a00ad25cb4731048670 Mon Sep 17 00:00:00 2001 From: Simon Heath Date: Wed, 27 Feb 2019 09:54:37 -0500 Subject: [PATCH 7/8] Vastly simplify TryFrom docs. --- src/libcore/num/mod.rs | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 4a2f958b93fe7..d08aa079dbd11 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4545,13 +4545,8 @@ macro_rules! try_from_unbounded { type Error = TryFromIntError; /// Try to create the target number type from a source - /// number type. If the source type has a larger range - /// than the target, or their ranges are disjoint (such - /// as converting a signed to unsigned number or vice - /// versa), this will return `None` if the source value - /// doesn't fit into the range of the destination value. - /// If the conversion can never fail, this is still - /// implemented for completeness's sake. + /// number type. This returns an error if the source value + /// is outside of the range of the target type. #[inline] fn try_from(value: $source) -> Result { Ok(value as $target) @@ -4568,13 +4563,8 @@ macro_rules! try_from_lower_bounded { type Error = TryFromIntError; /// Try to create the target number type from a source - /// number type. If the source type has a larger range - /// than the target, or their ranges are disjoint (such - /// as converting a signed to unsigned number or vice - /// versa), this will return `None` if the source value - /// doesn't fit into the range of the destination value. - /// If the conversion can never fail, this is still - /// implemented for completeness's sake. + /// number type. This returns an error if the source value + /// is outside of the range of the target type. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { if u >= 0 { @@ -4595,13 +4585,8 @@ macro_rules! try_from_upper_bounded { type Error = TryFromIntError; /// Try to create the target number type from a source - /// number type. If the source type has a larger range - /// than the target, or their ranges are disjoint (such - /// as converting a signed to unsigned number or vice - /// versa), this will return `None` if the source value - /// doesn't fit into the range of the destination value. - /// If the conversion can never fail, this is still - /// implemented for completeness's sake. + /// number type. This returns an error if the source value + /// is outside of the range of the target type. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { if u > (<$target>::max_value() as $source) { @@ -4622,13 +4607,8 @@ macro_rules! try_from_both_bounded { type Error = TryFromIntError; /// Try to create the target number type from a source - /// number type. If the source type has a larger range - /// than the target, or their ranges are disjoint (such - /// as converting a signed to unsigned number or vice - /// versa), this will return `None` if the source value - /// doesn't fit into the range of the destination value. - /// If the conversion can never fail, this is still - /// implemented for completeness's sake. + /// number type. This returns an error if the source value + /// is outside of the range of the target type. #[inline] fn try_from(u: $source) -> Result<$target, TryFromIntError> { let min = <$target>::min_value() as $source; From db99a3bccdc21e80d832b061defe1002527c1c46 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 12 Mar 2019 17:42:42 +0100 Subject: [PATCH 8/8] Remove stabilized feature gate in doctest --- src/libcore/convert.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 0fc182348c6c2..774d648558b48 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -415,7 +415,6 @@ pub trait TryInto: Sized { /// As described, [`i32`] implements `TryFrom`: /// /// ``` -/// #![feature(try_from)] /// use std::convert::TryFrom; /// /// let big_number = 1_000_000_000_000i64;