about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstd/sys/cloudabi/time.rs19
-rw-r--r--src/libstd/sys/redox/time.rs12
-rw-r--r--src/libstd/sys/unix/time.rs36
-rw-r--r--src/libstd/sys/wasm/time.rs8
-rw-r--r--src/libstd/sys/windows/time.rs34
-rw-r--r--src/libstd/time.rs27
6 files changed, 62 insertions, 74 deletions
diff --git a/src/libstd/sys/cloudabi/time.rs b/src/libstd/sys/cloudabi/time.rs
index a442d1e4ad7..fdd172a896c 100644
--- a/src/libstd/sys/cloudabi/time.rs
+++ b/src/libstd/sys/cloudabi/time.rs
@@ -21,8 +21,8 @@ pub struct Instant {
 
 fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
     dur.as_secs()
-        .checked_mul(NSEC_PER_SEC)
-        .and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
+        .checked_mul(NSEC_PER_SEC)?
+        .checked_add(dur.subsec_nanos() as abi::timestamp)
 }
 
 pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
@@ -47,12 +47,10 @@ impl Instant {
         Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
     }
 
-    pub fn add_duration(&self, other: &Duration) -> Instant {
-        Instant {
-            t: self.t
-                .checked_add(dur2intervals(other))
-                .expect("overflow when adding duration to instant"),
-        }
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+        checked_dur2intervals(other)?
+            .checked_add(self.t)
+            .map(|t| Instant {t})
     }
 
     pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -95,11 +93,6 @@ impl SystemTime {
         }
     }
 
-    pub fn add_duration(&self, other: &Duration) -> SystemTime {
-        self.checked_add_duration(other)
-            .expect("overflow when adding duration to instant")
-    }
-
     pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         checked_dur2intervals(other)
             .and_then(|d| self.t.checked_add(d))
diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs
index beff8d287e7..5ba8b780727 100644
--- a/src/libstd/sys/redox/time.rs
+++ b/src/libstd/sys/redox/time.rs
@@ -41,10 +41,6 @@ impl Timespec {
         }
     }
 
-    fn add_duration(&self, other: &Duration) -> Timespec {
-        self.checked_add_duration(other).expect("overflow when adding duration to time")
-    }
-
     fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
         let mut secs = other
             .as_secs()
@@ -150,8 +146,8 @@ impl Instant {
         })
     }
 
-    pub fn add_duration(&self, other: &Duration) -> Instant {
-        Instant { t: self.t.add_duration(other) }
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+        self.t.checked_add_duration(other).map(|t| Instant { t })
     }
 
     pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -178,10 +174,6 @@ impl SystemTime {
         self.t.sub_timespec(&other.t)
     }
 
-    pub fn add_duration(&self, other: &Duration) -> SystemTime {
-        SystemTime { t: self.t.add_duration(other) }
-    }
-
     pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         self.t.checked_add_duration(other).map(|t| SystemTime { t })
     }
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index 1f9539c36e0..81ef0f48833 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -42,10 +42,6 @@ impl Timespec {
         }
     }
 
-    fn add_duration(&self, other: &Duration) -> Timespec {
-        self.checked_add_duration(other).expect("overflow when adding duration to time")
-    }
-
     fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
         let mut secs = other
             .as_secs()
@@ -165,11 +161,8 @@ mod inner {
             Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
         }
 
-        pub fn add_duration(&self, other: &Duration) -> Instant {
-            Instant {
-                t: self.t.checked_add(dur2intervals(other))
-                       .expect("overflow when adding duration to instant"),
-            }
+        pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+            checked_dur2intervals(other)?.checked_add(self.t).map(|t| Instant {t})
         }
 
         pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -199,10 +192,6 @@ mod inner {
             self.t.sub_timespec(&other.t)
         }
 
-        pub fn add_duration(&self, other: &Duration) -> SystemTime {
-            SystemTime { t: self.t.add_duration(other) }
-        }
-
         pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
             self.t.checked_add_duration(other).map(|t| SystemTime { t })
         }
@@ -237,11 +226,16 @@ mod inner {
     }
 
     fn dur2intervals(dur: &Duration) -> u64 {
+        checked_dur2intervals(dur)
+            .expect("overflow converting duration to nanoseconds")
+    }
+
+    fn checked_dur2intervals(dur: &Duration) -> Option<u64> {
+        let nanos = dur.as_secs()
+            .checked_mul(NSEC_PER_SEC)?
+            .checked_add(dur.subsec_nanos() as u64)?;
         let info = info();
-        let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
-            nanos.checked_add(dur.subsec_nanos() as u64)
-        }).expect("overflow converting duration to nanoseconds");
-        mul_div_u64(nanos, info.denom as u64, info.numer as u64)
+        Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64))
     }
 
     fn info() -> &'static libc::mach_timebase_info {
@@ -299,8 +293,8 @@ mod inner {
             })
         }
 
-        pub fn add_duration(&self, other: &Duration) -> Instant {
-            Instant { t: self.t.add_duration(other) }
+        pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+            self.t.checked_add_duration(other).map(|t| Instant { t })
         }
 
         pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -327,10 +321,6 @@ mod inner {
             self.t.sub_timespec(&other.t)
         }
 
-        pub fn add_duration(&self, other: &Duration) -> SystemTime {
-            SystemTime { t: self.t.add_duration(other) }
-        }
-
         pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
             self.t.checked_add_duration(other).map(|t| SystemTime { t })
         }
diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs
index 991e8176edf..20cd870919c 100644
--- a/src/libstd/sys/wasm/time.rs
+++ b/src/libstd/sys/wasm/time.rs
@@ -28,8 +28,8 @@ impl Instant {
         self.0 - other.0
     }
 
-    pub fn add_duration(&self, other: &Duration) -> Instant {
-        Instant(self.0 + *other)
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+        self.0.checked_add(*other).map(|d| Instant(d))
     }
 
     pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -47,10 +47,6 @@ impl SystemTime {
         self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    pub fn add_duration(&self, other: &Duration) -> SystemTime {
-        SystemTime(self.0 + *other)
-    }
-
     pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         self.0.checked_add(*other).map(|d| SystemTime(d))
     }
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index c809a0b98ac..cad36627bf3 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -68,17 +68,15 @@ impl Instant {
         Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32)
     }
 
-    pub fn add_duration(&self, other: &Duration) -> Instant {
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
         let freq = frequency() as u64;
-        let t = other.as_secs().checked_mul(freq).and_then(|i| {
-            (self.t as u64).checked_add(i)
-        }).and_then(|i| {
-            i.checked_add(mul_div_u64(other.subsec_nanos() as u64, freq,
-                                      NANOS_PER_SEC))
-        }).expect("overflow when adding duration to time");
-        Instant {
+        let t = other.as_secs()
+            .checked_mul(freq)?
+            .checked_add(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))?
+            .checked_add(self.t as u64)?;
+        Some(Instant {
             t: t as c::LARGE_INTEGER,
-        }
+        })
     }
 
     pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -86,8 +84,7 @@ impl Instant {
         let t = other.as_secs().checked_mul(freq).and_then(|i| {
             (self.t as u64).checked_sub(i)
         }).and_then(|i| {
-            i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq,
-                                      NANOS_PER_SEC))
+            i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))
         }).expect("overflow when subtracting duration from time");
         Instant {
             t: t as c::LARGE_INTEGER,
@@ -127,10 +124,6 @@ impl SystemTime {
         }
     }
 
-    pub fn add_duration(&self, other: &Duration) -> SystemTime {
-        self.checked_add_duration(other).expect("overflow when adding duration to time")
-    }
-
     pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
         checked_dur2intervals(other)
             .and_then(|d| self.intervals().checked_add(d))
@@ -184,11 +177,12 @@ impl Hash for SystemTime {
     }
 }
 
-fn checked_dur2intervals(d: &Duration) -> Option<i64> {
-    d.as_secs()
-        .checked_mul(INTERVALS_PER_SEC)
-        .and_then(|i| i.checked_add(d.subsec_nanos() as u64 / 100))
-        .and_then(|i| i.try_into().ok())
+fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
+    dur.as_secs()
+        .checked_mul(INTERVALS_PER_SEC)?
+        .checked_add(dur.subsec_nanos() as u64 / 100)?
+        .try_into()
+        .ok()
 }
 
 fn dur2intervals(d: &Duration) -> i64 {
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 667810485ee..a0703fd50d5 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -208,6 +208,14 @@ impl Instant {
     pub fn elapsed(&self) -> Duration {
         Instant::now() - *self
     }
+
+    /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
+    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
+    /// otherwise.
+    #[unstable(feature = "time_checked_add", issue = "55940")]
+    pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
+        self.0.checked_add_duration(&duration).map(|t| Instant(t))
+    }
 }
 
 #[stable(feature = "time2", since = "1.8.0")]
@@ -215,7 +223,8 @@ impl Add<Duration> for Instant {
     type Output = Instant;
 
     fn add(self, other: Duration) -> Instant {
-        Instant(self.0.add_duration(&other))
+        self.checked_add(other)
+            .expect("overflow when adding duration to instant")
     }
 }
 
@@ -372,7 +381,8 @@ impl Add<Duration> for SystemTime {
     type Output = SystemTime;
 
     fn add(self, dur: Duration) -> SystemTime {
-        SystemTime(self.0.add_duration(&dur))
+        self.checked_add(dur)
+            .expect("overflow when adding duration to instant")
     }
 }
 
@@ -521,6 +531,19 @@ mod tests {
 
         let second = Duration::new(1, 0);
         assert_almost_eq!(a - second + second, a);
+
+        // checked_add_duration will not panic on overflow
+        let mut maybe_t = Some(Instant::now());
+        let max_duration = Duration::from_secs(u64::max_value());
+        // in case `Instant` can store `>= now + max_duration`.
+        for _ in 0..2 {
+            maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
+        }
+        assert_eq!(maybe_t, None);
+
+        // checked_add_duration calculates the right time and will work for another year
+        let year = Duration::from_secs(60 * 60 * 24 * 365);
+        assert_eq!(a + year, a.checked_add(year).unwrap());
     }
 
     #[test]