Skip to content

Commit c1f9d98

Browse files
author
Yuki Okushi
authored
Rollup merge of #102271 - lopopolo:lopopolo/stabilize-duration-try-from-secs-float, r=dtolnay
Stabilize `duration_checked_float` ## Stabilization Report This stabilization report is for a stabilization of `duration_checked_float`, tracking issue: #83400. ### Implementation History - #82179 - #90247 - #96051 - Changed error type to `FromFloatSecsError` in #90247 - #96051 changes the rounding mode to round-to-nearest instead of truncate. ## API Summary This stabilization report proposes the following API to be stabilized in `core`, along with their re-exports in `std`: ```rust // core::time impl Duration { pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, TryFromFloatSecsError>; pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, TryFromFloatSecsError>; } #[derive(Debug, Clone, PartialEq, Eq)] pub struct TryFromFloatSecsError { ... } impl core::fmt::Display for TryFromFloatSecsError { ... } impl core::error::Error for TryFromFloatSecsError { ... } ``` These functions are made const unstable under `duration_consts_float`, tracking issue #72440. There is an open question in the tracking issue around what the error type should be called which I was hoping to resolve in the context of an FCP. In this stabilization PR, I have altered the name of the error type to `TryFromFloatSecsError`. In my opinion, the error type shares the name of the method (adjusted to accommodate both types of floats), which is consistent with other error types in `core`, `alloc` and `std` like `TryReserveError` and `TryFromIntError`. ## Experience Report Code such as this is ready to be converted to a checked API to ensure it is panic free: ```rust impl Time { pub fn checked_add_f64(&self, seconds: f64) -> Result<Self, TimeError> { // Fail safely during `f64` conversion to duration if seconds.is_nan() || seconds.is_infinite() { return Err(TzOutOfRangeError::new().into()); } if seconds.is_sign_positive() { self.checked_add(Duration::from_secs_f64(seconds)) } else { self.checked_sub(Duration::from_secs_f64(-seconds)) } } } ``` See: artichoke/artichoke#2194. `@rustbot` label +T-libs-api -T-libs cc `@mbartlett21`
2 parents 779418d + 95040a7 commit c1f9d98

File tree

5 files changed

+21
-26
lines changed

5 files changed

+21
-26
lines changed

library/core/src/error.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -493,8 +493,8 @@ impl Error for crate::char::ParseCharError {
493493
}
494494
}
495495

496-
#[unstable(feature = "duration_checked_float", issue = "83400")]
497-
impl Error for crate::time::FromFloatSecsError {}
496+
#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
497+
impl Error for crate::time::TryFromFloatSecsError {}
498498

499499
#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
500500
impl Error for crate::ffi::FromBytesWithNulError {

library/core/src/time.rs

+17-20
Original file line numberDiff line numberDiff line change
@@ -1225,41 +1225,40 @@ impl fmt::Debug for Duration {
12251225
/// # Example
12261226
///
12271227
/// ```
1228-
/// #![feature(duration_checked_float)]
12291228
/// use std::time::Duration;
12301229
///
12311230
/// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
12321231
/// println!("Failed conversion to Duration: {e}");
12331232
/// }
12341233
/// ```
12351234
#[derive(Debug, Clone, PartialEq, Eq)]
1236-
#[unstable(feature = "duration_checked_float", issue = "83400")]
1237-
pub struct FromFloatSecsError {
1238-
kind: FromFloatSecsErrorKind,
1235+
#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
1236+
pub struct TryFromFloatSecsError {
1237+
kind: TryFromFloatSecsErrorKind,
12391238
}
12401239

1241-
impl FromFloatSecsError {
1240+
impl TryFromFloatSecsError {
12421241
const fn description(&self) -> &'static str {
12431242
match self.kind {
1244-
FromFloatSecsErrorKind::Negative => {
1243+
TryFromFloatSecsErrorKind::Negative => {
12451244
"can not convert float seconds to Duration: value is negative"
12461245
}
1247-
FromFloatSecsErrorKind::OverflowOrNan => {
1246+
TryFromFloatSecsErrorKind::OverflowOrNan => {
12481247
"can not convert float seconds to Duration: value is either too big or NaN"
12491248
}
12501249
}
12511250
}
12521251
}
12531252

1254-
#[unstable(feature = "duration_checked_float", issue = "83400")]
1255-
impl fmt::Display for FromFloatSecsError {
1253+
#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
1254+
impl fmt::Display for TryFromFloatSecsError {
12561255
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12571256
self.description().fmt(f)
12581257
}
12591258
}
12601259

12611260
#[derive(Debug, Clone, PartialEq, Eq)]
1262-
enum FromFloatSecsErrorKind {
1261+
enum TryFromFloatSecsErrorKind {
12631262
// Value is negative.
12641263
Negative,
12651264
// Value is either too big to be represented as `Duration` or `NaN`.
@@ -1280,7 +1279,7 @@ macro_rules! try_from_secs {
12801279
const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1;
12811280

12821281
if $secs < 0.0 {
1283-
return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::Negative });
1282+
return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::Negative });
12841283
}
12851284

12861285
let bits = $secs.to_bits();
@@ -1339,7 +1338,7 @@ macro_rules! try_from_secs {
13391338
let secs = u64::from(mant) << (exp - $mant_bits);
13401339
(secs, 0)
13411340
} else {
1342-
return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::OverflowOrNan });
1341+
return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::OverflowOrNan });
13431342
};
13441343

13451344
Ok(Duration::new(secs, nanos))
@@ -1355,8 +1354,6 @@ impl Duration {
13551354
///
13561355
/// # Examples
13571356
/// ```
1358-
/// #![feature(duration_checked_float)]
1359-
///
13601357
/// use std::time::Duration;
13611358
///
13621359
/// let res = Duration::try_from_secs_f32(0.0);
@@ -1404,9 +1401,10 @@ impl Duration {
14041401
/// let res = Duration::try_from_secs_f32(val);
14051402
/// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
14061403
/// ```
1407-
#[unstable(feature = "duration_checked_float", issue = "83400")]
1404+
#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
1405+
#[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
14081406
#[inline]
1409-
pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, FromFloatSecsError> {
1407+
pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, TryFromFloatSecsError> {
14101408
try_from_secs!(
14111409
secs = secs,
14121410
mantissa_bits = 23,
@@ -1425,8 +1423,6 @@ impl Duration {
14251423
///
14261424
/// # Examples
14271425
/// ```
1428-
/// #![feature(duration_checked_float)]
1429-
///
14301426
/// use std::time::Duration;
14311427
///
14321428
/// let res = Duration::try_from_secs_f64(0.0);
@@ -1482,9 +1478,10 @@ impl Duration {
14821478
/// let res = Duration::try_from_secs_f64(val);
14831479
/// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
14841480
/// ```
1485-
#[unstable(feature = "duration_checked_float", issue = "83400")]
1481+
#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
1482+
#[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
14861483
#[inline]
1487-
pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, FromFloatSecsError> {
1484+
pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, TryFromFloatSecsError> {
14881485
try_from_secs!(
14891486
secs = secs,
14901487
mantissa_bits = 52,

library/core/tests/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@
103103
#![feature(provide_any)]
104104
#![feature(utf8_chunks)]
105105
#![feature(is_ascii_octdigit)]
106-
#![feature(duration_checked_float)]
107106
#![deny(unsafe_op_in_unsafe_fn)]
108107

109108
extern crate test;

library/std/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@
280280
#![feature(core_intrinsics)]
281281
#![feature(cstr_from_bytes_until_nul)]
282282
#![feature(cstr_internals)]
283-
#![feature(duration_checked_float)]
284283
#![feature(duration_constants)]
285284
#![feature(error_generic_member_access)]
286285
#![feature(error_in_core)]

library/std/src/time.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ use crate::sys_common::{FromInner, IntoInner};
4343
#[stable(feature = "time", since = "1.3.0")]
4444
pub use core::time::Duration;
4545

46-
#[unstable(feature = "duration_checked_float", issue = "83400")]
47-
pub use core::time::FromFloatSecsError;
46+
#[stable(feature = "duration_checked_float", since = "CURRENT_RUSTC_VERSION")]
47+
pub use core::time::TryFromFloatSecsError;
4848

4949
/// A measurement of a monotonically nondecreasing clock.
5050
/// Opaque and useful only with [`Duration`].

0 commit comments

Comments
 (0)