Rollup merge of #78216 - workingjubilee:duration-zero, r=m-ou-se
Duration::zero() -> Duration::ZERO In review for #72790, whether or not a constant or a function should be favored for `#![feature(duration_zero)]` was seen as an open question. In https://github.com/rust-lang/rust/issues/73544#issuecomment-691701670 an invitation was opened to either stabilize the methods or propose a switch to the constant value, supplemented with reasoning. Followup comments suggested community preference leans towards the const ZERO, which would be reason enough. ZERO also "makes sense" beside existing associated consts for Duration. It is ever so slightly awkward to have a series of constants specifying 1 of various units but leave 0 as a method, especially when they are side-by-side in code. It seems unintuitive for the one non-dynamic value (that isn't from Default) to be not-a-const, which could hurt discoverability of the associated constants overall. Elsewhere in `std`, methods for obtaining a constant value were even deprecated, as seen with [std::u32::min_value](https://doc.rust-lang.org/std/primitive.u32.html#method.min_value). Most importantly, ZERO costs less to use. A match supports a const pattern, but const fn can only be used if evaluated through a const context such as an inline `const { const_fn() }` or a `const NAME: T = const_fn()` declaration elsewhere. Likewise, while https://github.com/rust-lang/rust/issues/73544#issuecomment-691949373 notes `Duration::zero()` can optimize to a constant value, "can" is not "will". Only const contexts have a strong promise of such. Even without that in mind, the comment in question still leans in favor of the constant for simplicity. As it costs less for a developer to use, may cost less to optimize, and seems to have more of a community consensus for it, the associated const seems best. r? ```@LukasKalbertodt```
This commit is contained in:
commit
62f0a78056
4 changed files with 75 additions and 95 deletions
|
@ -108,18 +108,20 @@ impl Duration {
|
|||
#[unstable(feature = "duration_constants", issue = "57391")]
|
||||
pub const NANOSECOND: Duration = Duration::from_nanos(1);
|
||||
|
||||
/// The minimum duration.
|
||||
/// A duration of zero time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_constants)]
|
||||
/// #![feature(duration_zero)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// assert_eq!(Duration::MIN, Duration::new(0, 0));
|
||||
/// let duration = Duration::ZERO;
|
||||
/// assert!(duration.is_zero());
|
||||
/// assert_eq!(duration.as_nanos(), 0);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_constants", issue = "57391")]
|
||||
pub const MIN: Duration = Duration::from_nanos(0);
|
||||
#[unstable(feature = "duration_zero", issue = "73544")]
|
||||
pub const ZERO: Duration = Duration::from_nanos(0);
|
||||
|
||||
/// The maximum duration.
|
||||
///
|
||||
|
@ -166,24 +168,6 @@ impl Duration {
|
|||
Duration { secs, nanos }
|
||||
}
|
||||
|
||||
/// Creates a new `Duration` that spans no time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_zero)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let duration = Duration::zero();
|
||||
/// assert!(duration.is_zero());
|
||||
/// assert_eq!(duration.as_nanos(), 0);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_zero", issue = "73544")]
|
||||
#[inline]
|
||||
pub const fn zero() -> Duration {
|
||||
Duration { secs: 0, nanos: 0 }
|
||||
}
|
||||
|
||||
/// Creates a new `Duration` from the specified number of whole seconds.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -277,7 +261,7 @@ impl Duration {
|
|||
/// #![feature(duration_zero)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// assert!(Duration::zero().is_zero());
|
||||
/// assert!(Duration::ZERO.is_zero());
|
||||
/// assert!(Duration::new(0, 0).is_zero());
|
||||
/// assert!(Duration::from_nanos(0).is_zero());
|
||||
/// assert!(Duration::from_secs(0).is_zero());
|
||||
|
@ -536,18 +520,18 @@ impl Duration {
|
|||
}
|
||||
}
|
||||
|
||||
/// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::MIN`]
|
||||
/// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::ZERO`]
|
||||
/// if the result would be negative or if overflow occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_saturating_ops)]
|
||||
/// #![feature(duration_constants)]
|
||||
/// #![feature(duration_zero)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1));
|
||||
/// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::MIN);
|
||||
/// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_saturating_ops", issue = "76416")]
|
||||
#[inline]
|
||||
|
@ -555,7 +539,7 @@ impl Duration {
|
|||
pub const fn saturating_sub(self, rhs: Duration) -> Duration {
|
||||
match self.checked_sub(rhs) {
|
||||
Some(res) => res,
|
||||
None => Duration::MIN,
|
||||
None => Duration::ZERO,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,24 +108,24 @@ fn sub() {
|
|||
|
||||
#[test]
|
||||
fn checked_sub() {
|
||||
let zero = Duration::new(0, 0);
|
||||
let one_nano = Duration::new(0, 1);
|
||||
let one_sec = Duration::new(1, 0);
|
||||
assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1)));
|
||||
assert_eq!(one_sec.checked_sub(one_nano), Some(Duration::new(0, 999_999_999)));
|
||||
assert_eq!(zero.checked_sub(one_nano), None);
|
||||
assert_eq!(zero.checked_sub(one_sec), None);
|
||||
assert_eq!(Duration::NANOSECOND.checked_sub(Duration::ZERO), Some(Duration::NANOSECOND));
|
||||
assert_eq!(
|
||||
Duration::SECOND.checked_sub(Duration::NANOSECOND),
|
||||
Some(Duration::new(0, 999_999_999))
|
||||
);
|
||||
assert_eq!(Duration::ZERO.checked_sub(Duration::NANOSECOND), None);
|
||||
assert_eq!(Duration::ZERO.checked_sub(Duration::SECOND), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn saturating_sub() {
|
||||
let zero = Duration::new(0, 0);
|
||||
let one_nano = Duration::new(0, 1);
|
||||
let one_sec = Duration::new(1, 0);
|
||||
assert_eq!(one_nano.saturating_sub(zero), Duration::new(0, 1));
|
||||
assert_eq!(one_sec.saturating_sub(one_nano), Duration::new(0, 999_999_999));
|
||||
assert_eq!(zero.saturating_sub(one_nano), Duration::MIN);
|
||||
assert_eq!(zero.saturating_sub(one_sec), Duration::MIN);
|
||||
assert_eq!(Duration::NANOSECOND.saturating_sub(Duration::ZERO), Duration::NANOSECOND);
|
||||
assert_eq!(
|
||||
Duration::SECOND.saturating_sub(Duration::NANOSECOND),
|
||||
Duration::new(0, 999_999_999)
|
||||
);
|
||||
assert_eq!(Duration::ZERO.saturating_sub(Duration::NANOSECOND), Duration::ZERO);
|
||||
assert_eq!(Duration::ZERO.saturating_sub(Duration::SECOND), Duration::ZERO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -337,87 +337,82 @@ fn duration_const() {
|
|||
const SUB_SEC_NANOS: u32 = DURATION.subsec_nanos();
|
||||
assert_eq!(SUB_SEC_NANOS, 123_456_789);
|
||||
|
||||
const ZERO: Duration = Duration::zero();
|
||||
assert_eq!(ZERO, Duration::new(0, 0));
|
||||
|
||||
const IS_ZERO: bool = ZERO.is_zero();
|
||||
const IS_ZERO: bool = Duration::ZERO.is_zero();
|
||||
assert!(IS_ZERO);
|
||||
|
||||
const ONE: Duration = Duration::new(1, 0);
|
||||
|
||||
const SECONDS: u64 = ONE.as_secs();
|
||||
const SECONDS: u64 = Duration::SECOND.as_secs();
|
||||
assert_eq!(SECONDS, 1);
|
||||
|
||||
const FROM_SECONDS: Duration = Duration::from_secs(1);
|
||||
assert_eq!(FROM_SECONDS, ONE);
|
||||
assert_eq!(FROM_SECONDS, Duration::SECOND);
|
||||
|
||||
const SECONDS_F32: f32 = ONE.as_secs_f32();
|
||||
const SECONDS_F32: f32 = Duration::SECOND.as_secs_f32();
|
||||
assert_eq!(SECONDS_F32, 1.0);
|
||||
|
||||
const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0);
|
||||
assert_eq!(FROM_SECONDS_F32, ONE);
|
||||
assert_eq!(FROM_SECONDS_F32, Duration::SECOND);
|
||||
|
||||
const SECONDS_F64: f64 = ONE.as_secs_f64();
|
||||
const SECONDS_F64: f64 = Duration::SECOND.as_secs_f64();
|
||||
assert_eq!(SECONDS_F64, 1.0);
|
||||
|
||||
const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0);
|
||||
assert_eq!(FROM_SECONDS_F64, ONE);
|
||||
assert_eq!(FROM_SECONDS_F64, Duration::SECOND);
|
||||
|
||||
const MILLIS: u128 = ONE.as_millis();
|
||||
const MILLIS: u128 = Duration::SECOND.as_millis();
|
||||
assert_eq!(MILLIS, 1_000);
|
||||
|
||||
const FROM_MILLIS: Duration = Duration::from_millis(1_000);
|
||||
assert_eq!(FROM_MILLIS, ONE);
|
||||
assert_eq!(FROM_MILLIS, Duration::SECOND);
|
||||
|
||||
const MICROS: u128 = ONE.as_micros();
|
||||
const MICROS: u128 = Duration::SECOND.as_micros();
|
||||
assert_eq!(MICROS, 1_000_000);
|
||||
|
||||
const FROM_MICROS: Duration = Duration::from_micros(1_000_000);
|
||||
assert_eq!(FROM_MICROS, ONE);
|
||||
assert_eq!(FROM_MICROS, Duration::SECOND);
|
||||
|
||||
const NANOS: u128 = ONE.as_nanos();
|
||||
const NANOS: u128 = Duration::SECOND.as_nanos();
|
||||
assert_eq!(NANOS, 1_000_000_000);
|
||||
|
||||
const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000);
|
||||
assert_eq!(FROM_NANOS, ONE);
|
||||
assert_eq!(FROM_NANOS, Duration::SECOND);
|
||||
|
||||
const MAX: Duration = Duration::new(u64::MAX, 999_999_999);
|
||||
|
||||
const CHECKED_ADD: Option<Duration> = MAX.checked_add(ONE);
|
||||
const CHECKED_ADD: Option<Duration> = MAX.checked_add(Duration::SECOND);
|
||||
assert_eq!(CHECKED_ADD, None);
|
||||
|
||||
const CHECKED_SUB: Option<Duration> = ZERO.checked_sub(ONE);
|
||||
const CHECKED_SUB: Option<Duration> = Duration::ZERO.checked_sub(Duration::SECOND);
|
||||
assert_eq!(CHECKED_SUB, None);
|
||||
|
||||
const CHECKED_MUL: Option<Duration> = ONE.checked_mul(1);
|
||||
assert_eq!(CHECKED_MUL, Some(ONE));
|
||||
const CHECKED_MUL: Option<Duration> = Duration::SECOND.checked_mul(1);
|
||||
assert_eq!(CHECKED_MUL, Some(Duration::SECOND));
|
||||
|
||||
const MUL_F32: Duration = ONE.mul_f32(1.0);
|
||||
assert_eq!(MUL_F32, ONE);
|
||||
const MUL_F32: Duration = Duration::SECOND.mul_f32(1.0);
|
||||
assert_eq!(MUL_F32, Duration::SECOND);
|
||||
|
||||
const MUL_F64: Duration = ONE.mul_f64(1.0);
|
||||
assert_eq!(MUL_F64, ONE);
|
||||
const MUL_F64: Duration = Duration::SECOND.mul_f64(1.0);
|
||||
assert_eq!(MUL_F64, Duration::SECOND);
|
||||
|
||||
const CHECKED_DIV: Option<Duration> = ONE.checked_div(1);
|
||||
assert_eq!(CHECKED_DIV, Some(ONE));
|
||||
const CHECKED_DIV: Option<Duration> = Duration::SECOND.checked_div(1);
|
||||
assert_eq!(CHECKED_DIV, Some(Duration::SECOND));
|
||||
|
||||
const DIV_F32: Duration = ONE.div_f32(1.0);
|
||||
assert_eq!(DIV_F32, ONE);
|
||||
const DIV_F32: Duration = Duration::SECOND.div_f32(1.0);
|
||||
assert_eq!(DIV_F32, Duration::SECOND);
|
||||
|
||||
const DIV_F64: Duration = ONE.div_f64(1.0);
|
||||
assert_eq!(DIV_F64, ONE);
|
||||
const DIV_F64: Duration = Duration::SECOND.div_f64(1.0);
|
||||
assert_eq!(DIV_F64, Duration::SECOND);
|
||||
|
||||
const DIV_DURATION_F32: f32 = ONE.div_duration_f32(ONE);
|
||||
const DIV_DURATION_F32: f32 = Duration::SECOND.div_duration_f32(Duration::SECOND);
|
||||
assert_eq!(DIV_DURATION_F32, 1.0);
|
||||
|
||||
const DIV_DURATION_F64: f64 = ONE.div_duration_f64(ONE);
|
||||
const DIV_DURATION_F64: f64 = Duration::SECOND.div_duration_f64(Duration::SECOND);
|
||||
assert_eq!(DIV_DURATION_F64, 1.0);
|
||||
|
||||
const SATURATING_ADD: Duration = MAX.saturating_add(ONE);
|
||||
const SATURATING_ADD: Duration = MAX.saturating_add(Duration::SECOND);
|
||||
assert_eq!(SATURATING_ADD, MAX);
|
||||
|
||||
const SATURATING_SUB: Duration = ZERO.saturating_sub(ONE);
|
||||
assert_eq!(SATURATING_SUB, ZERO);
|
||||
const SATURATING_SUB: Duration = Duration::ZERO.saturating_sub(Duration::SECOND);
|
||||
assert_eq!(SATURATING_SUB, Duration::ZERO);
|
||||
|
||||
const SATURATING_MUL: Duration = MAX.saturating_mul(2);
|
||||
assert_eq!(SATURATING_MUL, MAX);
|
||||
|
|
|
@ -257,6 +257,7 @@
|
|||
#![feature(doc_spotlight)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(duration_constants)]
|
||||
#![feature(duration_zero)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(extend_one)]
|
||||
|
|
|
@ -5,7 +5,7 @@ macro_rules! assert_almost_eq {
|
|||
let (a, b) = ($a, $b);
|
||||
if a != b {
|
||||
let (a, b) = if a > b { (a, b) } else { (b, a) };
|
||||
assert!(a - Duration::new(0, 1000) <= b, "{:?} is not almost equal to {:?}", a, b);
|
||||
assert!(a - Duration::from_micros(1) <= b, "{:?} is not almost equal to {:?}", a, b);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ fn instant_math() {
|
|||
assert_almost_eq!(b - dur, a);
|
||||
assert_almost_eq!(a + dur, b);
|
||||
|
||||
let second = Duration::new(1, 0);
|
||||
let second = Duration::SECOND;
|
||||
assert_almost_eq!(a - second + second, a);
|
||||
assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
|
||||
|
||||
|
@ -65,24 +65,24 @@ fn instant_math_is_associative() {
|
|||
#[should_panic]
|
||||
fn instant_duration_since_panic() {
|
||||
let a = Instant::now();
|
||||
(a - Duration::new(1, 0)).duration_since(a);
|
||||
(a - Duration::SECOND).duration_since(a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instant_checked_duration_since_nopanic() {
|
||||
let now = Instant::now();
|
||||
let earlier = now - Duration::new(1, 0);
|
||||
let later = now + Duration::new(1, 0);
|
||||
let earlier = now - Duration::SECOND;
|
||||
let later = now + Duration::SECOND;
|
||||
assert_eq!(earlier.checked_duration_since(now), None);
|
||||
assert_eq!(later.checked_duration_since(now), Some(Duration::new(1, 0)));
|
||||
assert_eq!(now.checked_duration_since(now), Some(Duration::new(0, 0)));
|
||||
assert_eq!(later.checked_duration_since(now), Some(Duration::SECOND));
|
||||
assert_eq!(now.checked_duration_since(now), Some(Duration::ZERO));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instant_saturating_duration_since_nopanic() {
|
||||
let a = Instant::now();
|
||||
let ret = (a - Duration::new(1, 0)).saturating_duration_since(a);
|
||||
assert_eq!(ret, Duration::new(0, 0));
|
||||
let ret = (a - Duration::SECOND).saturating_duration_since(a);
|
||||
assert_eq!(ret, Duration::ZERO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -90,7 +90,7 @@ fn system_time_math() {
|
|||
let a = SystemTime::now();
|
||||
let b = SystemTime::now();
|
||||
match b.duration_since(a) {
|
||||
Ok(dur) if dur == Duration::new(0, 0) => {
|
||||
Ok(Duration::ZERO) => {
|
||||
assert_almost_eq!(a, b);
|
||||
}
|
||||
Ok(dur) => {
|
||||
|
@ -106,16 +106,16 @@ fn system_time_math() {
|
|||
}
|
||||
}
|
||||
|
||||
let second = Duration::new(1, 0);
|
||||
let second = Duration::SECOND;
|
||||
assert_almost_eq!(a.duration_since(a - second).unwrap(), second);
|
||||
assert_almost_eq!(a.duration_since(a + second).unwrap_err().duration(), second);
|
||||
|
||||
assert_almost_eq!(a - second + second, a);
|
||||
assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
|
||||
|
||||
let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0);
|
||||
let one_second_from_epoch = UNIX_EPOCH + Duration::SECOND;
|
||||
let one_second_from_epoch2 =
|
||||
UNIX_EPOCH + Duration::new(0, 500_000_000) + Duration::new(0, 500_000_000);
|
||||
UNIX_EPOCH + Duration::from_millis(500) + Duration::from_millis(500);
|
||||
assert_eq!(one_second_from_epoch, one_second_from_epoch2);
|
||||
|
||||
// checked_add_duration will not panic on overflow
|
||||
|
@ -141,12 +141,12 @@ fn system_time_elapsed() {
|
|||
#[test]
|
||||
fn since_epoch() {
|
||||
let ts = SystemTime::now();
|
||||
let a = ts.duration_since(UNIX_EPOCH + Duration::new(1, 0)).unwrap();
|
||||
let a = ts.duration_since(UNIX_EPOCH + Duration::SECOND).unwrap();
|
||||
let b = ts.duration_since(UNIX_EPOCH).unwrap();
|
||||
assert!(b > a);
|
||||
assert_eq!(b - a, Duration::new(1, 0));
|
||||
assert_eq!(b - a, Duration::SECOND);
|
||||
|
||||
let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
|
||||
let thirty_years = Duration::SECOND * 60 * 60 * 24 * 365 * 30;
|
||||
|
||||
// Right now for CI this test is run in an emulator, and apparently the
|
||||
// aarch64 emulator's sense of time is that we're still living in the
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue