Skip to content

Commit 62f0a78

Browse files
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 #73544 (comment) 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 #73544 (comment) 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```
2 parents 7afc517 + 82f3a23 commit 62f0a78

File tree

4 files changed

+75
-95
lines changed

4 files changed

+75
-95
lines changed

library/core/src/time.rs

+12-28
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,20 @@ impl Duration {
108108
#[unstable(feature = "duration_constants", issue = "57391")]
109109
pub const NANOSECOND: Duration = Duration::from_nanos(1);
110110

111-
/// The minimum duration.
111+
/// A duration of zero time.
112112
///
113113
/// # Examples
114114
///
115115
/// ```
116-
/// #![feature(duration_constants)]
116+
/// #![feature(duration_zero)]
117117
/// use std::time::Duration;
118118
///
119-
/// assert_eq!(Duration::MIN, Duration::new(0, 0));
119+
/// let duration = Duration::ZERO;
120+
/// assert!(duration.is_zero());
121+
/// assert_eq!(duration.as_nanos(), 0);
120122
/// ```
121-
#[unstable(feature = "duration_constants", issue = "57391")]
122-
pub const MIN: Duration = Duration::from_nanos(0);
123+
#[unstable(feature = "duration_zero", issue = "73544")]
124+
pub const ZERO: Duration = Duration::from_nanos(0);
123125

124126
/// The maximum duration.
125127
///
@@ -166,24 +168,6 @@ impl Duration {
166168
Duration { secs, nanos }
167169
}
168170

169-
/// Creates a new `Duration` that spans no time.
170-
///
171-
/// # Examples
172-
///
173-
/// ```
174-
/// #![feature(duration_zero)]
175-
/// use std::time::Duration;
176-
///
177-
/// let duration = Duration::zero();
178-
/// assert!(duration.is_zero());
179-
/// assert_eq!(duration.as_nanos(), 0);
180-
/// ```
181-
#[unstable(feature = "duration_zero", issue = "73544")]
182-
#[inline]
183-
pub const fn zero() -> Duration {
184-
Duration { secs: 0, nanos: 0 }
185-
}
186-
187171
/// Creates a new `Duration` from the specified number of whole seconds.
188172
///
189173
/// # Examples
@@ -277,7 +261,7 @@ impl Duration {
277261
/// #![feature(duration_zero)]
278262
/// use std::time::Duration;
279263
///
280-
/// assert!(Duration::zero().is_zero());
264+
/// assert!(Duration::ZERO.is_zero());
281265
/// assert!(Duration::new(0, 0).is_zero());
282266
/// assert!(Duration::from_nanos(0).is_zero());
283267
/// assert!(Duration::from_secs(0).is_zero());
@@ -536,26 +520,26 @@ impl Duration {
536520
}
537521
}
538522

539-
/// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::MIN`]
523+
/// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::ZERO`]
540524
/// if the result would be negative or if overflow occurred.
541525
///
542526
/// # Examples
543527
///
544528
/// ```
545529
/// #![feature(duration_saturating_ops)]
546-
/// #![feature(duration_constants)]
530+
/// #![feature(duration_zero)]
547531
/// use std::time::Duration;
548532
///
549533
/// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1));
550-
/// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::MIN);
534+
/// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO);
551535
/// ```
552536
#[unstable(feature = "duration_saturating_ops", issue = "76416")]
553537
#[inline]
554538
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
555539
pub const fn saturating_sub(self, rhs: Duration) -> Duration {
556540
match self.checked_sub(rhs) {
557541
Some(res) => res,
558-
None => Duration::MIN,
542+
None => Duration::ZERO,
559543
}
560544
}
561545

library/core/tests/time.rs

+46-51
Original file line numberDiff line numberDiff line change
@@ -108,24 +108,24 @@ fn sub() {
108108

109109
#[test]
110110
fn checked_sub() {
111-
let zero = Duration::new(0, 0);
112-
let one_nano = Duration::new(0, 1);
113-
let one_sec = Duration::new(1, 0);
114-
assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1)));
115-
assert_eq!(one_sec.checked_sub(one_nano), Some(Duration::new(0, 999_999_999)));
116-
assert_eq!(zero.checked_sub(one_nano), None);
117-
assert_eq!(zero.checked_sub(one_sec), None);
111+
assert_eq!(Duration::NANOSECOND.checked_sub(Duration::ZERO), Some(Duration::NANOSECOND));
112+
assert_eq!(
113+
Duration::SECOND.checked_sub(Duration::NANOSECOND),
114+
Some(Duration::new(0, 999_999_999))
115+
);
116+
assert_eq!(Duration::ZERO.checked_sub(Duration::NANOSECOND), None);
117+
assert_eq!(Duration::ZERO.checked_sub(Duration::SECOND), None);
118118
}
119119

120120
#[test]
121121
fn saturating_sub() {
122-
let zero = Duration::new(0, 0);
123-
let one_nano = Duration::new(0, 1);
124-
let one_sec = Duration::new(1, 0);
125-
assert_eq!(one_nano.saturating_sub(zero), Duration::new(0, 1));
126-
assert_eq!(one_sec.saturating_sub(one_nano), Duration::new(0, 999_999_999));
127-
assert_eq!(zero.saturating_sub(one_nano), Duration::MIN);
128-
assert_eq!(zero.saturating_sub(one_sec), Duration::MIN);
122+
assert_eq!(Duration::NANOSECOND.saturating_sub(Duration::ZERO), Duration::NANOSECOND);
123+
assert_eq!(
124+
Duration::SECOND.saturating_sub(Duration::NANOSECOND),
125+
Duration::new(0, 999_999_999)
126+
);
127+
assert_eq!(Duration::ZERO.saturating_sub(Duration::NANOSECOND), Duration::ZERO);
128+
assert_eq!(Duration::ZERO.saturating_sub(Duration::SECOND), Duration::ZERO);
129129
}
130130

131131
#[test]
@@ -337,87 +337,82 @@ fn duration_const() {
337337
const SUB_SEC_NANOS: u32 = DURATION.subsec_nanos();
338338
assert_eq!(SUB_SEC_NANOS, 123_456_789);
339339

340-
const ZERO: Duration = Duration::zero();
341-
assert_eq!(ZERO, Duration::new(0, 0));
342-
343-
const IS_ZERO: bool = ZERO.is_zero();
340+
const IS_ZERO: bool = Duration::ZERO.is_zero();
344341
assert!(IS_ZERO);
345342

346-
const ONE: Duration = Duration::new(1, 0);
347-
348-
const SECONDS: u64 = ONE.as_secs();
343+
const SECONDS: u64 = Duration::SECOND.as_secs();
349344
assert_eq!(SECONDS, 1);
350345

351346
const FROM_SECONDS: Duration = Duration::from_secs(1);
352-
assert_eq!(FROM_SECONDS, ONE);
347+
assert_eq!(FROM_SECONDS, Duration::SECOND);
353348

354-
const SECONDS_F32: f32 = ONE.as_secs_f32();
349+
const SECONDS_F32: f32 = Duration::SECOND.as_secs_f32();
355350
assert_eq!(SECONDS_F32, 1.0);
356351

357352
const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0);
358-
assert_eq!(FROM_SECONDS_F32, ONE);
353+
assert_eq!(FROM_SECONDS_F32, Duration::SECOND);
359354

360-
const SECONDS_F64: f64 = ONE.as_secs_f64();
355+
const SECONDS_F64: f64 = Duration::SECOND.as_secs_f64();
361356
assert_eq!(SECONDS_F64, 1.0);
362357

363358
const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0);
364-
assert_eq!(FROM_SECONDS_F64, ONE);
359+
assert_eq!(FROM_SECONDS_F64, Duration::SECOND);
365360

366-
const MILLIS: u128 = ONE.as_millis();
361+
const MILLIS: u128 = Duration::SECOND.as_millis();
367362
assert_eq!(MILLIS, 1_000);
368363

369364
const FROM_MILLIS: Duration = Duration::from_millis(1_000);
370-
assert_eq!(FROM_MILLIS, ONE);
365+
assert_eq!(FROM_MILLIS, Duration::SECOND);
371366

372-
const MICROS: u128 = ONE.as_micros();
367+
const MICROS: u128 = Duration::SECOND.as_micros();
373368
assert_eq!(MICROS, 1_000_000);
374369

375370
const FROM_MICROS: Duration = Duration::from_micros(1_000_000);
376-
assert_eq!(FROM_MICROS, ONE);
371+
assert_eq!(FROM_MICROS, Duration::SECOND);
377372

378-
const NANOS: u128 = ONE.as_nanos();
373+
const NANOS: u128 = Duration::SECOND.as_nanos();
379374
assert_eq!(NANOS, 1_000_000_000);
380375

381376
const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000);
382-
assert_eq!(FROM_NANOS, ONE);
377+
assert_eq!(FROM_NANOS, Duration::SECOND);
383378

384379
const MAX: Duration = Duration::new(u64::MAX, 999_999_999);
385380

386-
const CHECKED_ADD: Option<Duration> = MAX.checked_add(ONE);
381+
const CHECKED_ADD: Option<Duration> = MAX.checked_add(Duration::SECOND);
387382
assert_eq!(CHECKED_ADD, None);
388383

389-
const CHECKED_SUB: Option<Duration> = ZERO.checked_sub(ONE);
384+
const CHECKED_SUB: Option<Duration> = Duration::ZERO.checked_sub(Duration::SECOND);
390385
assert_eq!(CHECKED_SUB, None);
391386

392-
const CHECKED_MUL: Option<Duration> = ONE.checked_mul(1);
393-
assert_eq!(CHECKED_MUL, Some(ONE));
387+
const CHECKED_MUL: Option<Duration> = Duration::SECOND.checked_mul(1);
388+
assert_eq!(CHECKED_MUL, Some(Duration::SECOND));
394389

395-
const MUL_F32: Duration = ONE.mul_f32(1.0);
396-
assert_eq!(MUL_F32, ONE);
390+
const MUL_F32: Duration = Duration::SECOND.mul_f32(1.0);
391+
assert_eq!(MUL_F32, Duration::SECOND);
397392

398-
const MUL_F64: Duration = ONE.mul_f64(1.0);
399-
assert_eq!(MUL_F64, ONE);
393+
const MUL_F64: Duration = Duration::SECOND.mul_f64(1.0);
394+
assert_eq!(MUL_F64, Duration::SECOND);
400395

401-
const CHECKED_DIV: Option<Duration> = ONE.checked_div(1);
402-
assert_eq!(CHECKED_DIV, Some(ONE));
396+
const CHECKED_DIV: Option<Duration> = Duration::SECOND.checked_div(1);
397+
assert_eq!(CHECKED_DIV, Some(Duration::SECOND));
403398

404-
const DIV_F32: Duration = ONE.div_f32(1.0);
405-
assert_eq!(DIV_F32, ONE);
399+
const DIV_F32: Duration = Duration::SECOND.div_f32(1.0);
400+
assert_eq!(DIV_F32, Duration::SECOND);
406401

407-
const DIV_F64: Duration = ONE.div_f64(1.0);
408-
assert_eq!(DIV_F64, ONE);
402+
const DIV_F64: Duration = Duration::SECOND.div_f64(1.0);
403+
assert_eq!(DIV_F64, Duration::SECOND);
409404

410-
const DIV_DURATION_F32: f32 = ONE.div_duration_f32(ONE);
405+
const DIV_DURATION_F32: f32 = Duration::SECOND.div_duration_f32(Duration::SECOND);
411406
assert_eq!(DIV_DURATION_F32, 1.0);
412407

413-
const DIV_DURATION_F64: f64 = ONE.div_duration_f64(ONE);
408+
const DIV_DURATION_F64: f64 = Duration::SECOND.div_duration_f64(Duration::SECOND);
414409
assert_eq!(DIV_DURATION_F64, 1.0);
415410

416-
const SATURATING_ADD: Duration = MAX.saturating_add(ONE);
411+
const SATURATING_ADD: Duration = MAX.saturating_add(Duration::SECOND);
417412
assert_eq!(SATURATING_ADD, MAX);
418413

419-
const SATURATING_SUB: Duration = ZERO.saturating_sub(ONE);
420-
assert_eq!(SATURATING_SUB, ZERO);
414+
const SATURATING_SUB: Duration = Duration::ZERO.saturating_sub(Duration::SECOND);
415+
assert_eq!(SATURATING_SUB, Duration::ZERO);
421416

422417
const SATURATING_MUL: Duration = MAX.saturating_mul(2);
423418
assert_eq!(SATURATING_MUL, MAX);

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@
257257
#![feature(doc_spotlight)]
258258
#![feature(dropck_eyepatch)]
259259
#![feature(duration_constants)]
260+
#![feature(duration_zero)]
260261
#![feature(exact_size_is_empty)]
261262
#![feature(exhaustive_patterns)]
262263
#![feature(extend_one)]

library/std/src/time/tests.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ macro_rules! assert_almost_eq {
55
let (a, b) = ($a, $b);
66
if a != b {
77
let (a, b) = if a > b { (a, b) } else { (b, a) };
8-
assert!(a - Duration::new(0, 1000) <= b, "{:?} is not almost equal to {:?}", a, b);
8+
assert!(a - Duration::from_micros(1) <= b, "{:?} is not almost equal to {:?}", a, b);
99
}
1010
}};
1111
}
@@ -34,7 +34,7 @@ fn instant_math() {
3434
assert_almost_eq!(b - dur, a);
3535
assert_almost_eq!(a + dur, b);
3636

37-
let second = Duration::new(1, 0);
37+
let second = Duration::SECOND;
3838
assert_almost_eq!(a - second + second, a);
3939
assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
4040

@@ -65,32 +65,32 @@ fn instant_math_is_associative() {
6565
#[should_panic]
6666
fn instant_duration_since_panic() {
6767
let a = Instant::now();
68-
(a - Duration::new(1, 0)).duration_since(a);
68+
(a - Duration::SECOND).duration_since(a);
6969
}
7070

7171
#[test]
7272
fn instant_checked_duration_since_nopanic() {
7373
let now = Instant::now();
74-
let earlier = now - Duration::new(1, 0);
75-
let later = now + Duration::new(1, 0);
74+
let earlier = now - Duration::SECOND;
75+
let later = now + Duration::SECOND;
7676
assert_eq!(earlier.checked_duration_since(now), None);
77-
assert_eq!(later.checked_duration_since(now), Some(Duration::new(1, 0)));
78-
assert_eq!(now.checked_duration_since(now), Some(Duration::new(0, 0)));
77+
assert_eq!(later.checked_duration_since(now), Some(Duration::SECOND));
78+
assert_eq!(now.checked_duration_since(now), Some(Duration::ZERO));
7979
}
8080

8181
#[test]
8282
fn instant_saturating_duration_since_nopanic() {
8383
let a = Instant::now();
84-
let ret = (a - Duration::new(1, 0)).saturating_duration_since(a);
85-
assert_eq!(ret, Duration::new(0, 0));
84+
let ret = (a - Duration::SECOND).saturating_duration_since(a);
85+
assert_eq!(ret, Duration::ZERO);
8686
}
8787

8888
#[test]
8989
fn system_time_math() {
9090
let a = SystemTime::now();
9191
let b = SystemTime::now();
9292
match b.duration_since(a) {
93-
Ok(dur) if dur == Duration::new(0, 0) => {
93+
Ok(Duration::ZERO) => {
9494
assert_almost_eq!(a, b);
9595
}
9696
Ok(dur) => {
@@ -106,16 +106,16 @@ fn system_time_math() {
106106
}
107107
}
108108

109-
let second = Duration::new(1, 0);
109+
let second = Duration::SECOND;
110110
assert_almost_eq!(a.duration_since(a - second).unwrap(), second);
111111
assert_almost_eq!(a.duration_since(a + second).unwrap_err().duration(), second);
112112

113113
assert_almost_eq!(a - second + second, a);
114114
assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
115115

116-
let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0);
116+
let one_second_from_epoch = UNIX_EPOCH + Duration::SECOND;
117117
let one_second_from_epoch2 =
118-
UNIX_EPOCH + Duration::new(0, 500_000_000) + Duration::new(0, 500_000_000);
118+
UNIX_EPOCH + Duration::from_millis(500) + Duration::from_millis(500);
119119
assert_eq!(one_second_from_epoch, one_second_from_epoch2);
120120

121121
// checked_add_duration will not panic on overflow
@@ -141,12 +141,12 @@ fn system_time_elapsed() {
141141
#[test]
142142
fn since_epoch() {
143143
let ts = SystemTime::now();
144-
let a = ts.duration_since(UNIX_EPOCH + Duration::new(1, 0)).unwrap();
144+
let a = ts.duration_since(UNIX_EPOCH + Duration::SECOND).unwrap();
145145
let b = ts.duration_since(UNIX_EPOCH).unwrap();
146146
assert!(b > a);
147-
assert_eq!(b - a, Duration::new(1, 0));
147+
assert_eq!(b - a, Duration::SECOND);
148148

149-
let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
149+
let thirty_years = Duration::SECOND * 60 * 60 * 24 * 365 * 30;
150150

151151
// Right now for CI this test is run in an emulator, and apparently the
152152
// aarch64 emulator's sense of time is that we're still living in the

0 commit comments

Comments
 (0)