about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-03-09 16:41:51 +0100
committerGitHub <noreply@github.com>2025-03-09 16:41:51 +0100
commit2460fc68b9d307ccb5eefe1e70cc83055fe5b927 (patch)
tree25640b19028ecac66c0508702f5b50f8337d291c
parent3bc41aa3e61318c48e51d12ffe74943d32577489 (diff)
parent8d37f38873fb374371bcd582f9ab29f223ce5d5a (diff)
downloadrust-2460fc68b9d307ccb5eefe1e70cc83055fe5b927.tar.gz
rust-2460fc68b9d307ccb5eefe1e70cc83055fe5b927.zip
Rollup merge of #138228 - TDecking:master, r=jhpratt
Use `disjoint_bitor` inside `borrowing_sub`

This makes the definition of `borrowing_sub` consistent with that of `carrying_add`.
-rw-r--r--library/core/src/num/uint_macros.rs11
1 files changed, 8 insertions, 3 deletions
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index d8709d51ccc..58689275839 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2533,15 +2533,20 @@ macro_rules! uint_impl {
         #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")]
         /// ```
         #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
         pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
             // note: longer-term this should be done via an intrinsic, but this has been shown
             //   to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
-            let (a, b) = self.overflowing_sub(rhs);
-            let (c, d) = a.overflowing_sub(borrow as $SelfT);
-            (c, b | d)
+            let (a, c1) = self.overflowing_sub(rhs);
+            let (b, c2) = a.overflowing_sub(borrow as $SelfT);
+            // SAFETY: Only one of `c1` and `c2` can be set.
+            // For c1 to be set we need to have underflowed, but if we did then
+            // `a` is nonzero, which means that `c2` cannot possibly
+            // underflow because it's subtracting at most `1` (since it came from `bool`)
+            (b, unsafe { intrinsics::disjoint_bitor(c1, c2) })
         }
 
         /// Calculates `self` - `rhs` with a signed `rhs`