time: eliminate panics from Instant arithmetic (#4461)

`Instant::duration_since`, `Instant::elapsed`, and `Instant::sub` may
panic. This is especially dangerous when `Instant::now` travels back in
time. While this isn't supposed to happen, this behavior is highly
platform-dependent (e.g., rust-lang/rust#86470).

This change modifies the behavior of `tokio::time::Instant` to prevent
this class of panic, as proposed for `std::time::Instant` in
rust-lang/rust#89926.
This commit is contained in:
Oliver Gould 2022-02-06 07:20:03 -08:00 committed by GitHub
parent bc474f1d81
commit fc4deaa1d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -67,13 +67,10 @@ impl Instant {
self.std self.std
} }
/// Returns the amount of time elapsed from another instant to this one. /// Returns the amount of time elapsed from another instant to this one, or
/// /// zero duration if that instant is later than this one.
/// # Panics
///
/// This function will panic if `earlier` is later than `self`.
pub fn duration_since(&self, earlier: Instant) -> Duration { pub fn duration_since(&self, earlier: Instant) -> Duration {
self.std.duration_since(earlier.std) self.std.saturating_duration_since(earlier.std)
} }
/// Returns the amount of time elapsed from another instant to this one, or /// Returns the amount of time elapsed from another instant to this one, or
@ -118,13 +115,8 @@ impl Instant {
self.std.saturating_duration_since(earlier.std) self.std.saturating_duration_since(earlier.std)
} }
/// Returns the amount of time elapsed since this instant was created. /// Returns the amount of time elapsed since this instant was created,
/// /// or zero duration if that this instant is in the future.
/// # Panics
///
/// This function may panic if the current time is earlier than this
/// instant, which is something that can happen if an `Instant` is
/// produced synthetically.
/// ///
/// # Examples /// # Examples
/// ///
@ -140,7 +132,7 @@ impl Instant {
/// } /// }
/// ``` /// ```
pub fn elapsed(&self) -> Duration { pub fn elapsed(&self) -> Duration {
Instant::now() - *self Instant::now().saturating_duration_since(*self)
} }
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be
@ -188,7 +180,7 @@ impl ops::Sub for Instant {
type Output = Duration; type Output = Duration;
fn sub(self, rhs: Instant) -> Duration { fn sub(self, rhs: Instant) -> Duration {
self.std - rhs.std self.std.saturating_duration_since(rhs.std)
} }
} }