From 7527409298ad88ae2fa6c5d517ed1730494ff2c0 Mon Sep 17 00:00:00 2001 From: marmeladema Date: Thu, 21 May 2020 20:22:47 +0100 Subject: [PATCH] Constify most non-trait `Duration` methods as described in #72440 --- src/libcore/lib.rs | 1 + src/libcore/time.rs | 47 ++++++++++++-------- src/test/ui/consts/duration-consts-2.rs | 58 +++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/consts/duration-consts-2.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 7d21f9a9a66d0..0524a3028c07b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -94,6 +94,7 @@ #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] +#![feature(duration_consts_2)] #![feature(extern_types)] #![feature(fundamental)] #![feature(intrinsics)] diff --git a/src/libcore/time.rs b/src/libcore/time.rs index ed1d5d46db5c4..7813d55dcaf51 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -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 } } @@ -393,7 +395,8 @@ impl Duration { /// ``` #[stable(feature = "duration_checked_ops", since = "1.16.0")] #[inline] - pub fn checked_add(self, rhs: Duration) -> Option { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn checked_add(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_add(rhs.secs) { let mut nanos = self.nanos + rhs.nanos; if nanos >= NANOS_PER_SEC { @@ -428,7 +431,8 @@ impl Duration { /// ``` #[stable(feature = "duration_checked_ops", since = "1.16.0")] #[inline] - pub fn checked_sub(self, rhs: Duration) -> Option { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn checked_sub(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { let nanos = if self.nanos >= rhs.nanos { self.nanos - rhs.nanos @@ -464,19 +468,19 @@ impl Duration { /// ``` #[stable(feature = "duration_checked_ops", since = "1.16.0")] #[inline] - pub fn checked_mul(self, rhs: u32) -> Option { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn checked_mul(self, rhs: u32) -> Option { // 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`] @@ -497,7 +501,8 @@ impl Duration { /// ``` #[stable(feature = "duration_checked_ops", since = "1.16.0")] #[inline] - pub fn checked_div(self, rhs: u32) -> Option { + #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + pub const fn checked_div(self, rhs: u32) -> Option { if rhs != 0 { let secs = self.secs / (rhs as u64); let carry = self.secs - secs * (rhs as u64); @@ -523,7 +528,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) } @@ -540,7 +546,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) } @@ -707,7 +714,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() } @@ -724,7 +732,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() } } diff --git a/src/test/ui/consts/duration-consts-2.rs b/src/test/ui/consts/duration-consts-2.rs new file mode 100644 index 0000000000000..e111cf1582bb6 --- /dev/null +++ b/src/test/ui/consts/duration-consts-2.rs @@ -0,0 +1,58 @@ +// run-pass + +#![feature(const_panic)] +#![feature(const_if_match)] +#![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 = MAX.checked_add(ZERO); + assert_eq!(MAX_ADD_ZERO, Some(MAX)); + + const MAX_ADD_ONE : Option = MAX.checked_add(ONE); + assert_eq!(MAX_ADD_ONE, None); + + const ONE_SUB_ONE : Option = ONE.checked_sub(ONE); + assert_eq!(ONE_SUB_ONE, Some(ZERO)); + + const ZERO_SUB_ONE : Option = ZERO.checked_sub(ONE); + assert_eq!(ZERO_SUB_ONE, None); + + const ONE_MUL_ONE : Option = ONE.checked_mul(1); + assert_eq!(ONE_MUL_ONE, Some(ONE)); + + const MAX_MUL_TWO : Option = MAX.checked_mul(2); + assert_eq!(MAX_MUL_TWO, None); + + const ONE_DIV_ONE : Option = ONE.checked_div(1); + assert_eq!(ONE_DIV_ONE, Some(ONE)); + + const ONE_DIV_ZERO : Option = ONE.checked_div(0); + assert_eq!(ONE_DIV_ZERO, None); + + const MAX_AS_F32 : f32 = MAX.as_secs_f32(); + assert_eq!(MAX_AS_F32, u64::MAX as f32 + 0.000_000_000_1); + + const MAX_AS_F64 : f64 = MAX.as_secs_f64(); + assert_eq!(MAX_AS_F64, u64::MAX as f64 + 0.000_000_000_1); + + 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(); +}