Skip to content

Commit

Permalink
Auto merge of #72481 - marmeladema:duration-consts-2, r=oli-obk
Browse files Browse the repository at this point in the history
Constify most non-trait `Duration` methods as described in #72440

The remaining methods could probably be made const once #72449 lands with support for `f<32|64>::is_finite()`.
  • Loading branch information
bors committed Jul 16, 2020
2 parents 125c58c + 4a96800 commit 6ee1b62
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 19 deletions.
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![feature(duration_consts_2)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
Expand Down
47 changes: 28 additions & 19 deletions src/libcore/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,12 @@ impl Duration {
/// ```
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
#[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
pub fn new(secs: u64, nanos: u32) -> Duration {
let secs =
secs.checked_add((nanos / NANOS_PER_SEC) as u64).expect("overflow in Duration::new");
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn new(secs: u64, nanos: u32) -> Duration {
let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
Some(secs) => secs,
None => panic!("overflow in Duration::new"),
};
let nanos = nanos % NANOS_PER_SEC;
Duration { secs, nanos }
}
Expand Down Expand Up @@ -433,7 +435,8 @@ impl Duration {
/// ```
#[stable(feature = "duration_checked_ops", since = "1.16.0")]
#[inline]
pub fn checked_add(self, rhs: Duration) -> Option<Duration> {
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn checked_add(self, rhs: Duration) -> Option<Duration> {
if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
let mut nanos = self.nanos + rhs.nanos;
if nanos >= NANOS_PER_SEC {
Expand Down Expand Up @@ -468,7 +471,8 @@ impl Duration {
/// ```
#[stable(feature = "duration_checked_ops", since = "1.16.0")]
#[inline]
pub fn checked_sub(self, rhs: Duration) -> Option<Duration> {
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> {
if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
let nanos = if self.nanos >= rhs.nanos {
self.nanos - rhs.nanos
Expand Down Expand Up @@ -504,19 +508,19 @@ impl Duration {
/// ```
#[stable(feature = "duration_checked_ops", since = "1.16.0")]
#[inline]
pub fn checked_mul(self, rhs: u32) -> Option<Duration> {
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn checked_mul(self, rhs: u32) -> Option<Duration> {
// Multiply nanoseconds as u64, because it cannot overflow that way.
let total_nanos = self.nanos as u64 * rhs as u64;
let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
if let Some(secs) =
self.secs.checked_mul(rhs as u64).and_then(|s| s.checked_add(extra_secs))
{
debug_assert!(nanos < NANOS_PER_SEC);
Some(Duration { secs, nanos })
} else {
None
if let Some(s) = self.secs.checked_mul(rhs as u64) {
if let Some(secs) = s.checked_add(extra_secs) {
debug_assert!(nanos < NANOS_PER_SEC);
return Some(Duration { secs, nanos });
}
}
None
}

/// Checked `Duration` division. Computes `self / other`, returning [`None`]
Expand All @@ -537,7 +541,8 @@ impl Duration {
/// ```
#[stable(feature = "duration_checked_ops", since = "1.16.0")]
#[inline]
pub fn checked_div(self, rhs: u32) -> Option<Duration> {
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn checked_div(self, rhs: u32) -> Option<Duration> {
if rhs != 0 {
let secs = self.secs / (rhs as u64);
let carry = self.secs - secs * (rhs as u64);
Expand All @@ -563,7 +568,8 @@ impl Duration {
/// ```
#[stable(feature = "duration_float", since = "1.38.0")]
#[inline]
pub fn as_secs_f64(&self) -> f64 {
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn as_secs_f64(&self) -> f64 {
(self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64)
}

Expand All @@ -580,7 +586,8 @@ impl Duration {
/// ```
#[stable(feature = "duration_float", since = "1.38.0")]
#[inline]
pub fn as_secs_f32(&self) -> f32 {
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn as_secs_f32(&self) -> f32 {
(self.secs as f32) + (self.nanos as f32) / (NANOS_PER_SEC as f32)
}

Expand Down Expand Up @@ -747,7 +754,8 @@ impl Duration {
/// ```
#[unstable(feature = "div_duration", issue = "63139")]
#[inline]
pub fn div_duration_f64(self, rhs: Duration) -> f64 {
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn div_duration_f64(self, rhs: Duration) -> f64 {
self.as_secs_f64() / rhs.as_secs_f64()
}

Expand All @@ -764,7 +772,8 @@ impl Duration {
/// ```
#[unstable(feature = "div_duration", issue = "63139")]
#[inline]
pub fn div_duration_f32(self, rhs: Duration) -> f32 {
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn div_duration_f32(self, rhs: Duration) -> f32 {
self.as_secs_f32() / rhs.as_secs_f32()
}
}
Expand Down
57 changes: 57 additions & 0 deletions src/test/ui/consts/duration-consts-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// run-pass

#![feature(const_panic)]
#![feature(duration_consts_2)]
#![feature(div_duration)]

use std::time::Duration;

fn duration() {
const ZERO : Duration = Duration::new(0, 0);
assert_eq!(ZERO, Duration::from_secs(0));

const ONE : Duration = Duration::new(0, 1);
assert_eq!(ONE, Duration::from_nanos(1));

const MAX : Duration = Duration::new(u64::MAX, 1_000_000_000 - 1);

const MAX_ADD_ZERO : Option<Duration> = MAX.checked_add(ZERO);
assert_eq!(MAX_ADD_ZERO, Some(MAX));

const MAX_ADD_ONE : Option<Duration> = MAX.checked_add(ONE);
assert_eq!(MAX_ADD_ONE, None);

const ONE_SUB_ONE : Option<Duration> = ONE.checked_sub(ONE);
assert_eq!(ONE_SUB_ONE, Some(ZERO));

const ZERO_SUB_ONE : Option<Duration> = ZERO.checked_sub(ONE);
assert_eq!(ZERO_SUB_ONE, None);

const ONE_MUL_ONE : Option<Duration> = ONE.checked_mul(1);
assert_eq!(ONE_MUL_ONE, Some(ONE));

const MAX_MUL_TWO : Option<Duration> = MAX.checked_mul(2);
assert_eq!(MAX_MUL_TWO, None);

const ONE_DIV_ONE : Option<Duration> = ONE.checked_div(1);
assert_eq!(ONE_DIV_ONE, Some(ONE));

const ONE_DIV_ZERO : Option<Duration> = ONE.checked_div(0);
assert_eq!(ONE_DIV_ZERO, None);

const MAX_AS_F32 : f32 = MAX.as_secs_f32();
assert_eq!(MAX_AS_F32, 18446744000000000000.0_f32);

const MAX_AS_F64 : f64 = MAX.as_secs_f64();
assert_eq!(MAX_AS_F64, 18446744073709552000.0_f64);

const ONE_AS_F32 : f32 = ONE.div_duration_f32(ONE);
assert_eq!(ONE_AS_F32, 1.0_f32);

const ONE_AS_F64 : f64 = ONE.div_duration_f64(ONE);
assert_eq!(ONE_AS_F64, 1.0_f64);
}

fn main() {
duration();
}

0 comments on commit 6ee1b62

Please sign in to comment.