about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarkus Reiter <me@reitermark.us>2024-02-17 01:45:15 +0100
committerMarkus Reiter <me@reitermark.us>2024-02-17 21:58:56 +0100
commitf12d248a6abeef2a1f8dc28f09344c8cba13d663 (patch)
tree39ea15af0934a4e1a45dd8728cd9bdb7026140e6
parent12b5498f3bcaa9f7b7641ed829873da0907b21dc (diff)
downloadrust-f12d248a6abeef2a1f8dc28f09344c8cba13d663.tar.gz
rust-f12d248a6abeef2a1f8dc28f09344c8cba13d663.zip
Implement `NonZero` traits generically.
-rw-r--r--library/core/src/num/nonzero.rs390
-rw-r--r--tests/ui/did_you_mean/bad-assoc-ty.stderr9
-rw-r--r--tests/ui/fmt/ifmt-unimpl.stderr2
-rw-r--r--tests/ui/traits/issue-77982.stderr1
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr1
5 files changed, 220 insertions, 183 deletions
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index fe287326175..8943e2f0e2a 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -81,6 +81,217 @@ impl_zeroable_primitive!(isize);
 #[rustc_diagnostic_item = "NonZero"]
 pub struct NonZero<T: ZeroablePrimitive>(T);
 
+macro_rules! impl_nonzero_fmt {
+    ($Trait:ident) => {
+        #[stable(feature = "nonzero", since = "1.28.0")]
+        impl<T> fmt::$Trait for NonZero<T>
+        where
+            T: ZeroablePrimitive + fmt::$Trait,
+        {
+            #[inline]
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                self.get().fmt(f)
+            }
+        }
+    };
+}
+
+impl_nonzero_fmt!(Debug);
+impl_nonzero_fmt!(Display);
+impl_nonzero_fmt!(Binary);
+impl_nonzero_fmt!(Octal);
+impl_nonzero_fmt!(LowerHex);
+impl_nonzero_fmt!(UpperHex);
+
+#[stable(feature = "nonzero", since = "1.28.0")]
+impl<T> Clone for NonZero<T>
+where
+    T: ZeroablePrimitive,
+{
+    #[inline]
+    fn clone(&self) -> Self {
+        // SAFETY: The contained value is non-zero.
+        unsafe { Self(self.0) }
+    }
+}
+
+#[stable(feature = "nonzero", since = "1.28.0")]
+impl<T> Copy for NonZero<T> where T: ZeroablePrimitive {}
+
+#[stable(feature = "nonzero", since = "1.28.0")]
+impl<T> PartialEq for NonZero<T>
+where
+    T: ZeroablePrimitive + PartialEq,
+{
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.get() == other.get()
+    }
+
+    #[inline]
+    fn ne(&self, other: &Self) -> bool {
+        self.get() != other.get()
+    }
+}
+
+#[unstable(feature = "structural_match", issue = "31434")]
+impl<T> StructuralPartialEq for NonZero<T> where T: ZeroablePrimitive + StructuralPartialEq {}
+
+#[stable(feature = "nonzero", since = "1.28.0")]
+impl<T> Eq for NonZero<T> where T: ZeroablePrimitive + Eq {}
+
+#[stable(feature = "nonzero", since = "1.28.0")]
+impl<T> PartialOrd for NonZero<T>
+where
+    T: ZeroablePrimitive + PartialOrd,
+{
+    #[inline]
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.get().partial_cmp(&other.get())
+    }
+
+    #[inline]
+    fn lt(&self, other: &Self) -> bool {
+        self.get() < other.get()
+    }
+
+    #[inline]
+    fn le(&self, other: &Self) -> bool {
+        self.get() <= other.get()
+    }
+
+    #[inline]
+    fn gt(&self, other: &Self) -> bool {
+        self.get() > other.get()
+    }
+
+    #[inline]
+    fn ge(&self, other: &Self) -> bool {
+        self.get() >= other.get()
+    }
+}
+
+#[stable(feature = "nonzero", since = "1.28.0")]
+impl<T> Ord for NonZero<T>
+where
+    T: ZeroablePrimitive + Ord,
+{
+    #[inline]
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.get().cmp(&other.get())
+    }
+
+    #[inline]
+    fn max(self, other: Self) -> Self {
+        // SAFETY: The maximum of two non-zero values is still non-zero.
+        unsafe { Self(self.get().max(other.get())) }
+    }
+
+    #[inline]
+    fn min(self, other: Self) -> Self {
+        // SAFETY: The minimum of two non-zero values is still non-zero.
+        unsafe { Self(self.get().min(other.get())) }
+    }
+
+    #[inline]
+    fn clamp(self, min: Self, max: Self) -> Self {
+        // SAFETY: A non-zero value clamped between two non-zero values is still non-zero.
+        unsafe { Self(self.get().clamp(min.get(), max.get())) }
+    }
+}
+
+#[stable(feature = "nonzero", since = "1.28.0")]
+impl<T> Hash for NonZero<T>
+where
+    T: ZeroablePrimitive + Hash,
+{
+    #[inline]
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        self.get().hash(state)
+    }
+}
+
+#[stable(feature = "from_nonzero", since = "1.31.0")]
+impl<T> From<NonZero<T>> for T
+where
+    T: ZeroablePrimitive,
+{
+    #[inline]
+    fn from(nonzero: NonZero<T>) -> Self {
+        // Call `get` method to keep range information.
+        nonzero.get()
+    }
+}
+
+#[stable(feature = "nonzero_bitor", since = "1.45.0")]
+impl<T> BitOr for NonZero<T>
+where
+    T: ZeroablePrimitive + BitOr<Output = T>,
+{
+    type Output = Self;
+
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self::Output {
+        // SAFETY: Bitwise OR of two non-zero values is still non-zero.
+        unsafe { Self(self.get() | rhs.get()) }
+    }
+}
+
+#[stable(feature = "nonzero_bitor", since = "1.45.0")]
+impl<T> BitOr<T> for NonZero<T>
+where
+    T: ZeroablePrimitive + BitOr<Output = T>,
+{
+    type Output = Self;
+
+    #[inline]
+    fn bitor(self, rhs: T) -> Self::Output {
+        // SAFETY: Bitwise OR of a non-zero value with anything is still non-zero.
+        unsafe { Self(self.get() | rhs) }
+    }
+}
+
+#[stable(feature = "nonzero_bitor", since = "1.45.0")]
+impl<T> BitOr<NonZero<T>> for T
+where
+    T: ZeroablePrimitive + BitOr<Output = T>,
+{
+    type Output = NonZero<T>;
+
+    #[inline]
+    fn bitor(self, rhs: NonZero<T>) -> Self::Output {
+        // SAFETY: Bitwise OR of anything with a non-zero value is still non-zero.
+        unsafe { NonZero(self | rhs.get()) }
+    }
+}
+
+#[stable(feature = "nonzero_bitor", since = "1.45.0")]
+impl<T> BitOrAssign for NonZero<T>
+where
+    T: ZeroablePrimitive,
+    Self: BitOr<Output = Self>,
+{
+    #[inline]
+    fn bitor_assign(&mut self, rhs: Self) {
+        *self = *self | rhs;
+    }
+}
+
+#[stable(feature = "nonzero_bitor", since = "1.45.0")]
+impl<T> BitOrAssign<T> for NonZero<T>
+where
+    T: ZeroablePrimitive,
+    Self: BitOr<T, Output = Self>,
+{
+    #[inline]
+    fn bitor_assign(&mut self, rhs: T) {
+        *self = *self | rhs;
+    }
+}
+
 impl<T> NonZero<T>
 where
     T: ZeroablePrimitive,
@@ -183,20 +394,6 @@ where
     }
 }
 
-macro_rules! impl_nonzero_fmt {
-    ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
-        $(
-            #[$stability]
-            impl fmt::$Trait for $Ty {
-                #[inline]
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    self.get().fmt(f)
-                }
-            }
-        )+
-    }
-}
-
 macro_rules! nonzero_integer {
     (
         #[$stability:meta]
@@ -549,171 +746,6 @@ macro_rules! nonzero_integer {
             }
         }
 
-        #[$stability]
-        impl Clone for $Ty {
-            #[inline]
-            fn clone(&self) -> Self {
-                // SAFETY: The contained value is non-zero.
-                unsafe { Self(self.0) }
-            }
-        }
-
-        #[$stability]
-        impl Copy for $Ty {}
-
-        #[$stability]
-        impl PartialEq for $Ty {
-            #[inline]
-            fn eq(&self, other: &Self) -> bool {
-                self.0 == other.0
-            }
-
-            #[inline]
-            fn ne(&self, other: &Self) -> bool {
-                self.0 != other.0
-            }
-        }
-
-        #[unstable(feature = "structural_match", issue = "31434")]
-        impl StructuralPartialEq for $Ty {}
-
-        #[$stability]
-        impl Eq for $Ty {}
-
-        #[$stability]
-        impl PartialOrd for $Ty {
-            #[inline]
-            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-                self.0.partial_cmp(&other.0)
-            }
-
-            #[inline]
-            fn lt(&self, other: &Self) -> bool {
-                self.0 < other.0
-            }
-
-            #[inline]
-            fn le(&self, other: &Self) -> bool {
-                self.0 <= other.0
-            }
-
-            #[inline]
-            fn gt(&self, other: &Self) -> bool {
-                self.0 > other.0
-            }
-
-            #[inline]
-            fn ge(&self, other: &Self) -> bool {
-                self.0 >= other.0
-            }
-        }
-
-        #[$stability]
-        impl Ord for $Ty {
-            #[inline]
-            fn cmp(&self, other: &Self) -> Ordering {
-                self.0.cmp(&other.0)
-            }
-
-            #[inline]
-            fn max(self, other: Self) -> Self {
-                // SAFETY: The maximum of two non-zero values is still non-zero.
-                unsafe { Self(self.0.max(other.0)) }
-            }
-
-            #[inline]
-            fn min(self, other: Self) -> Self {
-                // SAFETY: The minimum of two non-zero values is still non-zero.
-                unsafe { Self(self.0.min(other.0)) }
-            }
-
-            #[inline]
-            fn clamp(self, min: Self, max: Self) -> Self {
-                // SAFETY: A non-zero value clamped between two non-zero values is still non-zero.
-                unsafe { Self(self.0.clamp(min.0, max.0)) }
-            }
-        }
-
-        #[$stability]
-        impl Hash for $Ty {
-            #[inline]
-            fn hash<H>(&self, state: &mut H)
-            where
-                H: Hasher,
-            {
-                self.0.hash(state)
-            }
-        }
-
-        #[stable(feature = "from_nonzero", since = "1.31.0")]
-        impl From<$Ty> for $Int {
-            #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")]
-            #[inline]
-            fn from(nonzero: $Ty) -> Self {
-                // Call nonzero to keep information range information
-                // from get method.
-                nonzero.get()
-            }
-        }
-
-        #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-        impl BitOr for $Ty {
-            type Output = Self;
-
-            #[inline]
-            fn bitor(self, rhs: Self) -> Self::Output {
-                // SAFETY: since `self` and `rhs` are both nonzero, the
-                // result of the bitwise-or will be nonzero.
-                unsafe { Self::new_unchecked(self.get() | rhs.get()) }
-            }
-        }
-
-        #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-        impl BitOr<$Int> for $Ty {
-            type Output = Self;
-
-            #[inline]
-            fn bitor(self, rhs: $Int) -> Self::Output {
-                // SAFETY: since `self` is nonzero, the result of the
-                // bitwise-or will be nonzero regardless of the value of
-                // `rhs`.
-                unsafe { Self::new_unchecked(self.get() | rhs) }
-            }
-        }
-
-        #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-        impl BitOr<$Ty> for $Int {
-            type Output = $Ty;
-
-            #[inline]
-            fn bitor(self, rhs: $Ty) -> Self::Output {
-                // SAFETY: since `rhs` is nonzero, the result of the
-                // bitwise-or will be nonzero regardless of the value of
-                // `self`.
-                unsafe { $Ty::new_unchecked(self | rhs.get()) }
-            }
-        }
-
-        #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-        impl BitOrAssign for $Ty {
-            #[inline]
-            fn bitor_assign(&mut self, rhs: Self) {
-                *self = *self | rhs;
-            }
-        }
-
-        #[stable(feature = "nonzero_bitor", since = "1.45.0")]
-        impl BitOrAssign<$Int> for $Ty {
-            #[inline]
-            fn bitor_assign(&mut self, rhs: $Int) {
-                *self = *self | rhs;
-            }
-        }
-
-        impl_nonzero_fmt! {
-            #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
-        }
-
         #[stable(feature = "nonzero_parse", since = "1.35.0")]
         impl FromStr for $Ty {
             type Err = ParseIntError;
diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr
index 4a119f673c8..dc93762c9b1 100644
--- a/tests/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr
@@ -191,7 +191,14 @@ error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:33:10
    |
 LL | type H = Fn(u8) -> (u8)::Output;
-   |          ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output`
+   |          ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use fully-qualified syntax
+   |
+LL | type H = <(dyn Fn(u8) -> u8 + 'static) as BitOr>::Output;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | type H = <(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:39:19
diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr
index 58531c61bbe..3c5428e59fb 100644
--- a/tests/ui/fmt/ifmt-unimpl.stderr
+++ b/tests/ui/fmt/ifmt-unimpl.stderr
@@ -15,7 +15,7 @@ LL |     format!("{:X}", "3");
              i128
              usize
              u8
-           and 20 others
+           and 9 others
    = note: required for `&str` to implement `UpperHex`
 note: required by a bound in `core::fmt::rt::Argument::<'a>::new_upper_hex`
   --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr
index bffad037fba..5be8d2f4b32 100644
--- a/tests/ui/traits/issue-77982.stderr
+++ b/tests/ui/traits/issue-77982.stderr
@@ -46,7 +46,6 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    = note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate:
            - impl From<Char> for u32;
            - impl From<Ipv4Addr> for u32;
-           - impl From<NonZero<u32>> for u32;
            - impl From<bool> for u32;
            - impl From<char> for u32;
            - impl From<u16> for u32;
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index 80471c0ab1a..817acc8fc99 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -11,7 +11,6 @@ LL |     Ok(Err(123_i32)?)
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following other types implement trait `From<T>`:
              <u8 as From<bool>>
-             <u8 as From<NonZero<u8>>>
              <u8 as From<Char>>
    = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`