about summary refs log tree commit diff
path: root/library/core
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-07-07 03:31:23 +0000
committerbors <bors@rust-lang.org>2021-07-07 03:31:23 +0000
commitc5e344f7747dbd7e7d4b209e3c480deb5979a56f (patch)
tree0390ebc50ec6f445460fefd566a67be3be79a088 /library/core
parentc0bd5a584da4f26a1391163a0bdc21b34cf1ba54 (diff)
parent51968854f4c3bd9cc54cf35c3e84047adfc6cf21 (diff)
downloadrust-c5e344f7747dbd7e7d4b209e3c480deb5979a56f.tar.gz
rust-c5e344f7747dbd7e7d4b209e3c480deb5979a56f.zip
Auto merge of #86920 - JohnTitor:rollup-buvzpkr, r=JohnTitor
Rollup of 8 pull requests

Successful merges:

 - #80918 (Add Integer::log variants)
 - #86717 (Rename some Rust 2021 lints to better names )
 - #86819 (Clean up rustdoc IDs)
 - #86880 (Test ManuallyDrop::clone_from.)
 - #86906 (Replace deprecated compare_and_swap and fix typo in core::sync::atomic::{fence, compiler_fence} docs)
 - #86907 (Migrate `cpu-usage-over-time.py` to Python 3)
 - #86916 (rewrote documentation for thread::yield_now())
 - #86919 (Update books)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'library/core')
-rw-r--r--library/core/src/lib.rs3
-rw-r--r--library/core/src/num/int_macros.rs188
-rw-r--r--library/core/src/num/uint_macros.rs188
-rw-r--r--library/core/src/sync/atomic.rs8
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/manually_drop.rs8
-rw-r--r--library/core/tests/num/int_log.rs99
-rw-r--r--library/core/tests/num/mod.rs1
8 files changed, 493 insertions, 3 deletions
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 866cd5ec535..3557dbad90c 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -164,7 +164,8 @@
 #![feature(no_niche)] // rust-lang/rust#68303
 #![feature(no_coverage)] // rust-lang/rust#84605
 #![deny(unsafe_op_in_unsafe_fn)]
-#![deny(or_patterns_back_compat)]
+#![cfg_attr(bootstrap, deny(or_patterns_back_compat))]
+#![cfg_attr(not(bootstrap), deny(rust_2021_incompatible_or_patterns))]
 
 // allow using `core::` in intra-doc links
 #[allow(unused_extern_crates)]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 2e466106fe5..a9461649d4a 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1744,6 +1744,194 @@ macro_rules! int_impl {
             }
         }
 
+        /// Returns the logarithm of the number with respect to an arbitrary base.
+        ///
+        /// This method may not be optimized owing to implementation details;
+        /// `log2` can produce results more efficiently for base 2, and `log10`
+        /// can produce results more efficiently for base 10.
+        ///
+        /// # Panics
+        ///
+        /// When the number is zero, or if the base is not at least 2; it
+        /// panics in debug mode and the return value is wrapped to 0 in release
+        /// mode (the only situation in which the method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log(self, base: Self) -> Self {
+            match self.checked_log(base) {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the base 2 logarithm of the number.
+        ///
+        /// # Panics
+        ///
+        /// When the number is zero it panics in debug mode and the return value
+        /// is wrapped to 0 in release mode (the only situation in which the
+        /// method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log2(self) -> Self {
+            match self.checked_log2() {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the base 10 logarithm of the number.
+        ///
+        /// # Panics
+        ///
+        /// When the number is zero it panics in debug mode and the return value
+        /// is wrapped to 0 in release mode (the only situation in which the
+        /// method can return 0).
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log10(self) -> Self {
+            match self.checked_log10() {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the logarithm of the number with respect to an arbitrary base.
+        ///
+        /// Returns `None` if the number is negative or zero, or if the base is not at least 2.
+        ///
+        /// This method may not be optimized owing to implementation details;
+        /// `checked_log2` can produce results more efficiently for base 2, and
+        /// `checked_log10` can produce results more efficiently for base 10.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log(self, base: Self) -> Option<Self> {
+            if self <= 0 || base <= 1 {
+                None
+            } else {
+                let mut n = 0;
+                let mut r = self;
+
+                // Optimization for 128 bit wide integers.
+                if Self::BITS == 128 {
+                    let b = Self::log2(self) / (Self::log2(base) + 1);
+                    n += b;
+                    r /= base.pow(b as u32);
+                }
+
+                while r >= base {
+                    r /= base;
+                    n += 1;
+                }
+                Some(n)
+            }
+        }
+
+        /// Returns the base 2 logarithm of the number.
+        ///
+        /// Returns `None` if the number is negative or zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log2(self) -> Option<Self> {
+            if self <= 0 {
+                None
+            } else {
+                // SAFETY: We just checked that this number is positive
+                let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+                Some(log)
+            }
+        }
+
+        /// Returns the base 10 logarithm of the number.
+        ///
+        /// Returns `None` if the number is negative or zero.
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log10(self) -> Option<Self> {
+            self.checked_log(10)
+        }
+
         /// Computes the absolute value of `self`.
         ///
         /// # Overflow behavior
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index e512d90ef37..bf4d2e7433e 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -634,6 +634,194 @@ macro_rules! uint_impl {
             }
         }
 
+        /// Returns the logarithm of the number with respect to an arbitrary base.
+        ///
+        /// This method may not be optimized owing to implementation details;
+        /// `log2` can produce results more efficiently for base 2, and `log10`
+        /// can produce results more efficiently for base 10.
+        ///
+        /// # Panics
+        ///
+        /// When the number is negative, zero, or if the base is not at least 2;
+        /// it panics in debug mode and the return value is wrapped to 0 in
+        /// release mode (the only situation in which the method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log(self, base: Self) -> Self {
+            match self.checked_log(base) {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the base 2 logarithm of the number.
+        ///
+        /// # Panics
+        ///
+        /// When the number is negative or zero it panics in debug mode and
+        /// the return value is wrapped to 0 in release mode (the only situation in
+        /// which the method can return 0).
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log2(self) -> Self {
+            match self.checked_log2() {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the base 10 logarithm of the number.
+        ///
+        /// # Panics
+        ///
+        /// When the number is negative or zero it panics in debug mode and the
+        /// return value is wrapped to 0 in release mode (the only situation in
+        /// which the method can return 0).
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        #[track_caller]
+        #[rustc_inherit_overflow_checks]
+        #[allow(arithmetic_overflow)]
+        pub const fn log10(self) -> Self {
+            match self.checked_log10() {
+                Some(n) => n,
+                None => {
+                    // In debug builds, trigger a panic on None.
+                    // This should optimize completely out in release builds.
+                    let _ = Self::MAX + 1;
+
+                    0
+                },
+            }
+        }
+
+        /// Returns the logarithm of the number with respect to an arbitrary base.
+        ///
+        /// Returns `None` if the number is zero, or if the base is not at least 2.
+        ///
+        /// This method may not be optimized owing to implementation details;
+        /// `checked_log2` can produce results more efficiently for base 2, and
+        /// `checked_log10` can produce results more efficiently for base 10.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log(self, base: Self) -> Option<Self> {
+            if self <= 0 || base <= 1 {
+                None
+            } else {
+                let mut n = 0;
+                let mut r = self;
+
+                // Optimization for 128 bit wide integers.
+                if Self::BITS == 128 {
+                    let b = Self::log2(self) / (Self::log2(base) + 1);
+                    n += b;
+                    r /= base.pow(b as u32);
+                }
+
+                while r >= base {
+                    r /= base;
+                    n += 1;
+                }
+                Some(n)
+            }
+        }
+
+        /// Returns the base 2 logarithm of the number.
+        ///
+        /// Returns `None` if the number is zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log2(self) -> Option<Self> {
+            if self <= 0 {
+                None
+            } else {
+                // SAFETY: We just checked that this number is positive
+                let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+                Some(log)
+            }
+        }
+
+        /// Returns the base 10 logarithm of the number.
+        ///
+        /// Returns `None` if the number is zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_log)]
+        #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")]
+        /// ```
+        #[unstable(feature = "int_log", issue = "70887")]
+        #[must_use = "this returns the result of the operation, \
+                        without modifying the original"]
+        #[inline]
+        pub const fn checked_log10(self) -> Option<Self> {
+            self.checked_log(10)
+        }
+
         /// Checked negation. Computes `-self`, returning `None` unless `self ==
         /// 0`.
         ///
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index f1a115563fd..b673b36c102 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2648,7 +2648,11 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 ///
 ///     pub fn lock(&self) {
 ///         // Wait until the old value is `false`.
-///         while self.flag.compare_and_swap(false, true, Ordering::Relaxed) != false {}
+///         while self
+///             .flag
+///             .compare_exchange_weak(false, true, Ordering::Relaxed, Ordering::Relaxed)
+///             .is_err()
+///         {}
 ///         // This fence synchronizes-with store in `unlock`.
 ///         fence(Ordering::Acquire);
 ///     }
@@ -2710,7 +2714,7 @@ pub fn fence(order: Ordering) {
 /// Without `compiler_fence`, the `assert_eq!` in following code
 /// is *not* guaranteed to succeed, despite everything happening in a single thread.
 /// To see why, remember that the compiler is free to swap the stores to
-/// `IMPORTANT_VARIABLE` and `IS_READ` since they are both
+/// `IMPORTANT_VARIABLE` and `IS_READY` since they are both
 /// `Ordering::Relaxed`. If it does, and the signal handler is invoked right
 /// after `IS_READY` is updated, then the signal handler will see
 /// `IS_READY=1`, but `IMPORTANT_VARIABLE=0`.
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index f9d331063f4..cc4ff1be563 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -44,6 +44,7 @@
 #![feature(try_trait_v2)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
+#![feature(int_log)]
 #![feature(iter_advance_by)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_intersperse)]
diff --git a/library/core/tests/manually_drop.rs b/library/core/tests/manually_drop.rs
index 77a338daf7d..9eac279733a 100644
--- a/library/core/tests/manually_drop.rs
+++ b/library/core/tests/manually_drop.rs
@@ -2,6 +2,7 @@ use core::mem::ManuallyDrop;
 
 #[test]
 fn smoke() {
+    #[derive(Clone)]
     struct TypeWithDrop;
     impl Drop for TypeWithDrop {
         fn drop(&mut self) {
@@ -16,4 +17,11 @@ fn smoke() {
     let x: Box<ManuallyDrop<[TypeWithDrop]>> =
         Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop]));
     drop(x);
+
+    // test clone and clone_from implementations
+    let mut x = ManuallyDrop::new(TypeWithDrop);
+    let y = x.clone();
+    x.clone_from(&y);
+    drop(x);
+    drop(y);
 }
diff --git a/library/core/tests/num/int_log.rs b/library/core/tests/num/int_log.rs
new file mode 100644
index 00000000000..99a9b17ab11
--- /dev/null
+++ b/library/core/tests/num/int_log.rs
@@ -0,0 +1,99 @@
+//! This tests the `Integer::{log,log2,log10}` methods. These tests are in a
+//! separate file because there's both a large number of them, and not all tests
+//! can be run on Android. This is because in Android `log2` uses an imprecise
+//! approximation:https://github.com/rust-lang/rust/blob/4825e12fc9c79954aa0fe18f5521efa6c19c7539/src/libstd/sys/unix/android.rs#L27-L53
+
+#[test]
+fn checked_log() {
+    assert_eq!(999u32.checked_log(10), Some(2));
+    assert_eq!(1000u32.checked_log(10), Some(3));
+    assert_eq!(555u32.checked_log(13), Some(2));
+    assert_eq!(63u32.checked_log(4), Some(2));
+    assert_eq!(64u32.checked_log(4), Some(3));
+    assert_eq!(10460353203u64.checked_log(3), Some(21));
+    assert_eq!(10460353202u64.checked_log(3), Some(20));
+    assert_eq!(147808829414345923316083210206383297601u128.checked_log(3), Some(80));
+    assert_eq!(147808829414345923316083210206383297600u128.checked_log(3), Some(79));
+    assert_eq!(22528399544939174411840147874772641u128.checked_log(19683), Some(8));
+    assert_eq!(22528399544939174411840147874772631i128.checked_log(19683), Some(7));
+
+    assert_eq!(0u8.checked_log(4), None);
+    assert_eq!(0u16.checked_log(4), None);
+    assert_eq!(0i8.checked_log(4), None);
+    assert_eq!(0i16.checked_log(4), None);
+
+    for i in i16::MIN..=0 {
+        assert_eq!(i.checked_log(4), None);
+    }
+    for i in 1..=i16::MAX {
+        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16));
+    }
+    for i in 1..=u16::MAX {
+        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16));
+    }
+}
+
+#[test]
+fn checked_log2() {
+    assert_eq!(5u32.checked_log2(), Some(2));
+    assert_eq!(0u64.checked_log2(), None);
+    assert_eq!(128i32.checked_log2(), Some(7));
+    assert_eq!((-55i16).checked_log2(), None);
+
+    assert_eq!(0u8.checked_log2(), None);
+    assert_eq!(0u16.checked_log2(), None);
+    assert_eq!(0i8.checked_log2(), None);
+    assert_eq!(0i16.checked_log2(), None);
+
+    for i in 1..=u8::MAX {
+        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8));
+    }
+    for i in 1..=u16::MAX {
+        // Guard against Android's imprecise f32::log2 implementation.
+        if i != 8192 && i != 32768 {
+            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16));
+        }
+    }
+    for i in i8::MIN..=0 {
+        assert_eq!(i.checked_log2(), None);
+    }
+    for i in 1..=i8::MAX {
+        assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8));
+    }
+    for i in i16::MIN..=0 {
+        assert_eq!(i.checked_log2(), None);
+    }
+    for i in 1..=i16::MAX {
+        // Guard against Android's imprecise f32::log2 implementation.
+        if i != 8192 {
+            assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16));
+        }
+    }
+}
+
+// Validate cases that fail on Android's imprecise float log2 implementation.
+#[test]
+#[cfg(not(target_os = "android"))]
+fn checked_log2_not_android() {
+    assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16));
+    assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16));
+    assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16));
+}
+
+#[test]
+fn checked_log10() {
+    assert_eq!(0u8.checked_log10(), None);
+    assert_eq!(0u16.checked_log10(), None);
+    assert_eq!(0i8.checked_log10(), None);
+    assert_eq!(0i16.checked_log10(), None);
+
+    for i in i16::MIN..=0 {
+        assert_eq!(i.checked_log10(), None);
+    }
+    for i in 1..=i16::MAX {
+        assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16));
+    }
+    for i in 1..=u16::MAX {
+        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16));
+    }
+}
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index bbb67667dfc..76e838cf6bf 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -29,6 +29,7 @@ mod u8;
 mod bignum;
 mod dec2flt;
 mod flt2dec;
+mod int_log;
 mod ops;
 mod wrapping;