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 1/3] 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<libc::timespec> 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<Duration> {
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]

From 015ab659c2fcdf2f3a3fdaa6dc44455b9d0c2f3e Mon Sep 17 00:00:00 2001
From: Cameron <51241057+maniwani@users.noreply.github.com>
Date: Sun, 13 Nov 2022 12:33:21 -0800
Subject: [PATCH 2/3] just use `libc::clockid_t`

---
 library/std/src/sys/unix/time.rs | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index b65566740b5..c3fac44a42d 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -290,9 +290,9 @@ mod inner {
     impl Instant {
         pub fn now() -> Instant {
             #[cfg(target_os = "macos")]
-            const clock_id: clock_t = libc::CLOCK_UPTIME_RAW;
+            const clock_id: libc::clockid_t = libc::CLOCK_UPTIME_RAW;
             #[cfg(not(target_os = "macos"))]
-            const clock_id: clock_t = libc::CLOCK_MONOTONIC;
+            const clock_id: libc::clockid_t = libc::CLOCK_MONOTONIC;
             Instant { t: Timespec::now(clock_id) }
         }
 
@@ -324,13 +324,8 @@ mod inner {
         }
     }
 
-    #[cfg(not(any(target_os = "dragonfly", target_os = "espidf", target_os = "horizon")))]
-    pub type clock_t = libc::c_int;
-    #[cfg(any(target_os = "dragonfly", target_os = "espidf", target_os = "horizon"))]
-    pub type clock_t = libc::c_ulong;
-
     impl Timespec {
-        pub fn now(clock: clock_t) -> Timespec {
+        pub fn now(clock: libc::clockid_t) -> Timespec {
             // Try to use 64-bit time in preparation for Y2038.
             #[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32"))]
             {

From f4f515973ecc689029b64759ff43dbba0e207be2 Mon Sep 17 00:00:00 2001
From: Cameron <51241057+maniwani@users.noreply.github.com>
Date: Mon, 14 Nov 2022 09:17:21 -0800
Subject: [PATCH 3/3] macos, aarch64, and not(miri)

---
 library/std/src/sys/unix/time.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index c3fac44a42d..ffcc507d2a7 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -150,7 +150,7 @@ impl From<libc::timespec> for Timespec {
 }
 
 #[cfg(any(
-    all(target_os = "macos", not(target_arch = "aarch64")),
+    all(target_os = "macos", any(not(target_arch = "aarch64"), miri)),
     target_os = "ios",
     target_os = "watchos"
 ))]
@@ -270,7 +270,7 @@ mod inner {
 }
 
 #[cfg(not(any(
-    all(target_os = "macos", not(target_arch = "aarch64")),
+    all(target_os = "macos", any(not(target_arch = "aarch64"), miri)),
     target_os = "ios",
     target_os = "watchos"
 )))]