From 5008a317ce8e508c390ed12bff281f307313376e Mon Sep 17 00:00:00 2001 From: Joy <51241057+maniwani@users.noreply.github.com> Date: Wed, 26 Oct 2022 11:43:18 -0700 Subject: [PATCH] Fix non-associativity of `Instant` math on `aarch64-apple-darwin` targets --- library/std/src/sys/unix/time.rs | 18 +++++++++++++++--- library/std/src/time/tests.rs | 8 ++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index cca9c676701..b65566740b5 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -149,7 +149,11 @@ impl From for Timespec { } } -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] +#[cfg(any( + all(target_os = "macos", not(target_arch = "aarch64")), + target_os = "ios", + target_os = "watchos" +))] mod inner { use crate::sync::atomic::{AtomicU64, Ordering}; use crate::sys::cvt; @@ -265,7 +269,11 @@ mod inner { } } -#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))] +#[cfg(not(any( + all(target_os = "macos", not(target_arch = "aarch64")), + target_os = "ios", + target_os = "watchos" +)))] mod inner { use crate::fmt; use crate::mem::MaybeUninit; @@ -281,7 +289,11 @@ mod inner { impl Instant { pub fn now() -> Instant { - Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) } + #[cfg(target_os = "macos")] + const clock_id: clock_t = libc::CLOCK_UPTIME_RAW; + #[cfg(not(target_os = "macos"))] + const clock_id: clock_t = libc::CLOCK_MONOTONIC; + Instant { t: Timespec::now(clock_id) } } pub fn checked_sub_instant(&self, other: &Instant) -> Option { diff --git a/library/std/src/time/tests.rs b/library/std/src/time/tests.rs index 6229556c85f..2e64ae59aff 100644 --- a/library/std/src/time/tests.rs +++ b/library/std/src/time/tests.rs @@ -88,6 +88,14 @@ fn instant_math_is_associative() { // Changing the order of instant math shouldn't change the results, // especially when the expression reduces to X + identity. assert_eq!((now + offset) - now, (now - now) + offset); + + // On any platform, `Instant` should have the same resolution as `Duration` (e.g. 1 nanosecond) + // or better. Otherwise, math will be non-associative (see #91417). + let now = Instant::now(); + let provided_offset = Duration::from_nanos(1); + let later = now + provided_offset; + let measured_offset = later - now; + assert_eq!(measured_offset, provided_offset); } #[test]