Auto merge of #72481 - marmeladema:duration-consts-2, r=oli-obk

Constify most non-trait `Duration` methods as described in #72440

The remaining methods could probably be made const once https://github.com/rust-lang/rust/pull/72449 lands with support for `f<32|64>::is_finite()`.
This commit is contained in:
bors 2020-07-16 13:35:09 +00:00
commit 6ee1b62c81
3 changed files with 86 additions and 19 deletions

View File

@ -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)]

View File

@ -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 }
}
@ -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 {
@ -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
@ -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`]
@ -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);
@ -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)
}
@ -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)
}
@ -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()
}
@ -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()
}
}

View File

@ -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();
}