about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-19 16:26:37 +0000
committerbors <bors@rust-lang.org>2024-01-19 16:26:37 +0000
commit32ec40c68533f325a3c8fe787b77ef5c9e209b23 (patch)
tree5b1767592d36a88a9a2bc595eb2fbd06e2a9694e
parent92d727796be7c882d2efbc06e08bbf4743cf29dc (diff)
parentb4616f5f65b11d37eb2d60bcd5d995d13a30c756 (diff)
downloadrust-32ec40c68533f325a3c8fe787b77ef5c9e209b23.tar.gz
rust-32ec40c68533f325a3c8fe787b77ef5c9e209b23.zip
Auto merge of #120121 - matthiaskrgr:rollup-razammh, r=matthiaskrgr
Rollup of 10 pull requests

Successful merges:

 - #118665 (Consolidate all associated items on the NonZero integer types into a single impl block per type)
 - #118798 (Use AtomicU8 instead of AtomicUsize in backtrace.rs)
 - #119062 (Deny braced macro invocations in let-else)
 - #119138 (Docs: Use non-SeqCst in module example of atomics)
 - #119907 (Update `fn()` trait implementation docs)
 - #120083 (Warn when not having a profiler runtime means that coverage tests won't be run/blessed)
 - #120107 (dead_code treats #[repr(transparent)] the same as #[repr(C)])
 - #120110 (Update documentation for Vec::into_boxed_slice to be more clear about excess capacity)
 - #120113 (Remove myself from review rotation)
 - #120118 (Fix typo in documentation in base.rs)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast/src/util/classify.rs10
-rw-r--r--compiler/rustc_expand/src/base.rs6
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs37
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs15
-rw-r--r--compiler/rustc_passes/src/dead.rs18
-rw-r--r--library/alloc/src/boxed/thin.rs1
-rw-r--r--library/alloc/src/vec/mod.rs19
-rw-r--r--library/core/src/num/nonzero.rs2476
-rw-r--r--library/core/src/primitive_docs.rs10
-rw-r--r--library/core/src/sync/atomic.rs13
-rw-r--r--library/std/src/backtrace.rs6
-rw-r--r--src/tools/compiletest/src/main.rs9
-rw-r--r--src/tools/miri/tests/fail/issue-miri-1112.rs2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs2
-rw-r--r--tests/ui/consts/transmute-const.rs2
-rw-r--r--tests/ui/layout/unsafe-cell-hides-niche.rs2
-rw-r--r--tests/ui/lint/dead-code/type-in-transparent.rs14
-rw-r--r--tests/ui/packed/packed-struct-drop-aligned.rs2
-rw-r--r--tests/ui/parser/bad-let-else-statement.rs25
-rw-r--r--tests/ui/parser/bad-let-else-statement.stderr28
-rw-r--r--triagebot.toml1
23 files changed, 1376 insertions, 1326 deletions
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index 65036bcdc36..098b8f2d6d0 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -2,7 +2,7 @@
 
 // Predicates on exprs and stmts that the pretty-printer and parser use
 
-use crate::ast;
+use crate::{ast, token::Delimiter};
 
 /// Does this expression require a semicolon to be treated
 /// as a statement? The negation of this: 'can this expression
@@ -59,8 +59,12 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
             | While(..)
             | ConstBlock(_) => break Some(expr),
 
-            // FIXME: These can end in `}`, but changing these would break stable code.
-            InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
+            MacCall(mac) => {
+                break (mac.args.delim == Delimiter::Brace).then_some(expr);
+            }
+
+            InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
+                // These should have been denied pre-expansion.
                 break None;
             }
 
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index edc9c5a9130..29b70f33a6c 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -666,8 +666,8 @@ pub enum SyntaxExtensionKind {
     /// A token-based attribute macro.
     Attr(
         /// An expander with signature (TokenStream, TokenStream) -> TokenStream.
-        /// The first TokenSteam is the attribute itself, the second is the annotated item.
-        /// The produced TokenSteam replaces the input TokenSteam.
+        /// The first TokenStream is the attribute itself, the second is the annotated item.
+        /// The produced TokenStream replaces the input TokenStream.
         Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
     ),
 
@@ -687,7 +687,7 @@ pub enum SyntaxExtensionKind {
     /// A token-based derive macro.
     Derive(
         /// An expander with signature TokenStream -> TokenStream.
-        /// The produced TokenSteam is appended to the input TokenSteam.
+        /// The produced TokenStream is appended to the input TokenStream.
         ///
         /// FIXME: The text above describes how this should work. Currently it
         /// is handled identically to `LegacyDerive`. It should be migrated to
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index fb19bb996f9..f904e0c44ea 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -724,6 +724,8 @@ parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifeti
 
 parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
 
+parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro
+
 parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
 
 parse_switch_mut_let_order =
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 7dc711d9610..40852048293 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -722,19 +722,32 @@ pub(crate) struct LabeledLoopInBreak {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub sub: WrapExpressionInParentheses,
+    pub sub: WrapInParentheses,
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(
-    parse_sugg_wrap_expression_in_parentheses,
-    applicability = "machine-applicable"
-)]
-pub(crate) struct WrapExpressionInParentheses {
-    #[suggestion_part(code = "(")]
-    pub left: Span,
-    #[suggestion_part(code = ")")]
-    pub right: Span,
+
+pub(crate) enum WrapInParentheses {
+    #[multipart_suggestion(
+        parse_sugg_wrap_expression_in_parentheses,
+        applicability = "machine-applicable"
+    )]
+    Expression {
+        #[suggestion_part(code = "(")]
+        left: Span,
+        #[suggestion_part(code = ")")]
+        right: Span,
+    },
+    #[multipart_suggestion(
+        parse_sugg_wrap_macro_in_parentheses,
+        applicability = "machine-applicable"
+    )]
+    MacroArgs {
+        #[suggestion_part(code = "(")]
+        left: Span,
+        #[suggestion_part(code = ")")]
+        right: Span,
+    },
 }
 
 #[derive(Diagnostic)]
@@ -936,7 +949,7 @@ pub(crate) struct InvalidExpressionInLetElse {
     pub span: Span,
     pub operator: &'static str,
     #[subdiagnostic]
-    pub sugg: WrapExpressionInParentheses,
+    pub sugg: WrapInParentheses,
 }
 
 #[derive(Diagnostic)]
@@ -945,7 +958,7 @@ pub(crate) struct InvalidCurlyInLetElse {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub sugg: WrapExpressionInParentheses,
+    pub sugg: WrapInParentheses,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 8ca02452342..f858706805d 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1844,7 +1844,7 @@ impl<'a> Parser<'a> {
             let lexpr = self.parse_expr_labeled(label, true)?;
             self.dcx().emit_err(errors::LabeledLoopInBreak {
                 span: lexpr.span,
-                sub: errors::WrapExpressionInParentheses {
+                sub: errors::WrapInParentheses::Expression {
                     left: lexpr.span.shrink_to_lo(),
                     right: lexpr.span.shrink_to_hi(),
                 },
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 1a8bbf0a157..1bae5b32240 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -389,7 +389,7 @@ impl<'a> Parser<'a> {
                 self.dcx().emit_err(errors::InvalidExpressionInLetElse {
                     span: init.span,
                     operator: op.node.as_str(),
-                    sugg: errors::WrapExpressionInParentheses {
+                    sugg: errors::WrapInParentheses::Expression {
                         left: init.span.shrink_to_lo(),
                         right: init.span.shrink_to_hi(),
                     },
@@ -400,12 +400,19 @@ impl<'a> Parser<'a> {
 
     fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
         if let Some(trailing) = classify::expr_trailing_brace(init) {
-            self.dcx().emit_err(errors::InvalidCurlyInLetElse {
-                span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
-                sugg: errors::WrapExpressionInParentheses {
+            let sugg = match &trailing.kind {
+                ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs {
+                    left: mac.args.dspan.open,
+                    right: mac.args.dspan.close,
+                },
+                _ => errors::WrapInParentheses::Expression {
                     left: trailing.span.shrink_to_lo(),
                     right: trailing.span.shrink_to_hi(),
                 },
+            };
+            self.dcx().emit_err(errors::InvalidCurlyInLetElse {
+                span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
+                sugg,
             });
         }
     }
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 9422a594488..d7f17ac4547 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -57,7 +57,7 @@ struct MarkSymbolVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
     live_symbols: LocalDefIdSet,
-    repr_has_repr_c: bool,
+    repr_unconditionally_treats_fields_as_live: bool,
     repr_has_repr_simd: bool,
     in_pat: bool,
     ignore_variant_stack: Vec<DefId>,
@@ -365,15 +365,17 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             return;
         }
 
-        let had_repr_c = self.repr_has_repr_c;
+        let unconditionally_treated_fields_as_live =
+            self.repr_unconditionally_treats_fields_as_live;
         let had_repr_simd = self.repr_has_repr_simd;
-        self.repr_has_repr_c = false;
+        self.repr_unconditionally_treats_fields_as_live = false;
         self.repr_has_repr_simd = false;
         match node {
             Node::Item(item) => match item.kind {
                 hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
                     let def = self.tcx.adt_def(item.owner_id);
-                    self.repr_has_repr_c = def.repr().c();
+                    self.repr_unconditionally_treats_fields_as_live =
+                        def.repr().c() || def.repr().transparent();
                     self.repr_has_repr_simd = def.repr().simd();
 
                     intravisit::walk_item(self, item)
@@ -411,7 +413,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             _ => {}
         }
         self.repr_has_repr_simd = had_repr_simd;
-        self.repr_has_repr_c = had_repr_c;
+        self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;
     }
 
     fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
@@ -435,11 +437,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
 
     fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) {
         let tcx = self.tcx;
-        let has_repr_c = self.repr_has_repr_c;
+        let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live;
         let has_repr_simd = self.repr_has_repr_simd;
         let live_fields = def.fields().iter().filter_map(|f| {
             let def_id = f.def_id;
-            if has_repr_c || (f.is_positional() && has_repr_simd) {
+            if unconditionally_treat_fields_as_live || (f.is_positional() && has_repr_simd) {
                 return Some(def_id);
             }
             if !tcx.visibility(f.hir_id.owner.def_id).is_public() {
@@ -741,7 +743,7 @@ fn live_symbols_and_ignored_derived_traits(
         tcx,
         maybe_typeck_results: None,
         live_symbols: Default::default(),
-        repr_has_repr_c: false,
+        repr_unconditionally_treats_fields_as_live: false,
         repr_has_repr_simd: false,
         in_pat: false,
         ignore_variant_stack: vec![],
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index 9463b73b574..f83c8f83cc9 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -171,7 +171,6 @@ struct WithHeader<H>(NonNull<u8>, PhantomData<H>);
 /// An opaque representation of `WithHeader<H>` to avoid the
 /// projection invariance of `<T as Pointee>::Metadata`.
 #[repr(transparent)]
-#[allow(dead_code)] // Field only used through `WithHeader` type above.
 struct WithOpaqueHeader(NonNull<u8>);
 
 impl WithOpaqueHeader {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 8aa0c6e7ed6..35ea97bfe60 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -358,7 +358,7 @@ mod spec_extend;
 ///
 /// `vec![x; n]`, `vec![a, b, c, d]`, and
 /// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec`
-/// with exactly the requested capacity. If <code>[len] == [capacity]</code>,
+/// with at least the requested capacity. If <code>[len] == [capacity]</code>,
 /// (as is the case for the [`vec!`] macro), then a `Vec<T>` can be converted to
 /// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements.
 ///
@@ -1023,8 +1023,11 @@ impl<T, A: Allocator> Vec<T, A> {
 
     /// Shrinks the capacity of the vector as much as possible.
     ///
-    /// It will drop down as close as possible to the length but the allocator
-    /// may still inform the vector that there is space for a few more elements.
+    /// The behavior of this method depends on the allocator, which may either shrink the vector
+    /// in-place or reallocate. The resulting vector might still have some excess capacity, just as
+    /// is the case for [`with_capacity`]. See [`Allocator::shrink`] for more details.
+    ///
+    /// [`with_capacity`]: Vec::with_capacity
     ///
     /// # Examples
     ///
@@ -1074,10 +1077,10 @@ impl<T, A: Allocator> Vec<T, A> {
 
     /// Converts the vector into [`Box<[T]>`][owned slice].
     ///
-    /// If the vector has excess capacity, its items will be moved into a
-    /// newly-allocated buffer with exactly the right capacity.
+    /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`].
     ///
     /// [owned slice]: Box
+    /// [`shrink_to_fit`]: Vec::shrink_to_fit
     ///
     /// # Examples
     ///
@@ -3290,8 +3293,10 @@ impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> {
 impl<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> {
     /// Convert a vector into a boxed slice.
     ///
-    /// If `v` has excess capacity, its items will be moved into a
-    /// newly-allocated buffer with exactly the right capacity.
+    /// Before doing the conversion, this method discards excess capacity like [`Vec::shrink_to_fit`].
+    ///
+    /// [owned slice]: Box
+    /// [`Vec::shrink_to_fit`]: Vec::shrink_to_fit
     ///
     /// # Examples
     ///
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 715c3a0b8ac..7d60686597a 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -85,193 +85,450 @@ macro_rules! impl_nonzero_fmt {
     }
 }
 
-macro_rules! nonzero_integers {
-    ( $( #[$stability: meta] #[$const_new_unchecked_stability: meta] $Ty: ident($Int: ty); )+ ) => {
-        $(
-            /// An integer that is known not to equal zero.
+macro_rules! nonzero_integer {
+    (
+        #[$stability:meta]
+        #[$const_new_unchecked_stability:meta]
+        Self = $Ty:ident,
+        Primitive = $signedness:ident $Int:ident,
+        $(UnsignedNonZero = $UnsignedNonZero:ident,)?
+        UnsignedPrimitive = $UnsignedPrimitive:ty,
+
+        // Used in doc comments.
+        leading_zeros_test = $leading_zeros_test:expr,
+    ) => {
+        /// An integer that is known not to equal zero.
+        ///
+        /// This enables some memory layout optimization.
+        #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")]
+        ///
+        /// ```rust
+        /// use std::mem::size_of;
+        #[doc = concat!("assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int), ">());")]
+        /// ```
+        ///
+        /// # Layout
+        ///
+        #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")]
+        /// with the exception that `0` is not a valid instance.
+        #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")]
+        /// including in FFI.
+        ///
+        /// Thanks to the [null pointer optimization],
+        #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")]
+        /// are guaranteed to have the same size and alignment:
+        ///
+        /// ```
+        /// # use std::mem::{size_of, align_of};
+        #[doc = concat!("use std::num::", stringify!($Ty), ";")]
+        ///
+        #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::<Option<", stringify!($Ty), ">>());")]
+        #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::<Option<", stringify!($Ty), ">>());")]
+        /// ```
+        ///
+        /// [null pointer optimization]: crate::option#representation
+        #[$stability]
+        #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+        #[repr(transparent)]
+        #[rustc_layout_scalar_valid_range_start(1)]
+        #[rustc_nonnull_optimization_guaranteed]
+        #[rustc_diagnostic_item = stringify!($Ty)]
+        pub struct $Ty($Int);
+
+        impl $Ty {
+            /// Creates a non-zero without checking whether the value is non-zero.
+            /// This results in undefined behaviour if the value is zero.
+            ///
+            /// # Safety
+            ///
+            /// The value must not be zero.
+            #[$stability]
+            #[$const_new_unchecked_stability]
+            #[must_use]
+            #[inline]
+            pub const unsafe fn new_unchecked(n: $Int) -> Self {
+                crate::panic::debug_assert_nounwind!(
+                    n != 0,
+                    concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument")
+                );
+                // SAFETY: this is guaranteed to be safe by the caller.
+                unsafe {
+                    Self(n)
+                }
+            }
+
+            /// Creates a non-zero if the given value is not zero.
+            #[$stability]
+            #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")]
+            #[must_use]
+            #[inline]
+            pub const fn new(n: $Int) -> Option<Self> {
+                if n != 0 {
+                    // SAFETY: we just checked that there's no `0`
+                    Some(unsafe { Self(n) })
+                } else {
+                    None
+                }
+            }
+
+            /// Returns the value as a primitive type.
+            #[$stability]
+            #[inline]
+            #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")]
+            pub const fn get(self) -> $Int {
+                // FIXME: Remove this after LLVM supports `!range` metadata for function
+                // arguments https://github.com/llvm/llvm-project/issues/76628
+                //
+                // Rustc can set range metadata only if it loads `self` from
+                // memory somewhere. If the value of `self` was from by-value argument
+                // of some not-inlined function, LLVM don't have range metadata
+                // to understand that the value cannot be zero.
+
+                // SAFETY: It is an invariant of this type.
+                unsafe {
+                    intrinsics::assume(self.0 != 0);
+                }
+                self.0
+            }
+
+            /// The size of this non-zero integer type in bits.
+            ///
+            #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")]
             ///
-            /// This enables some memory layout optimization.
-            #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")]
+            /// # Examples
             ///
-            /// ```rust
-            /// use std::mem::size_of;
-            #[doc = concat!("assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int), ">());")]
             /// ```
+            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
             ///
-            /// # Layout
+            #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")]
+            /// ```
+            #[stable(feature = "nonzero_bits", since = "1.67.0")]
+            pub const BITS: u32 = <$Int>::BITS;
+
+            /// Returns the number of leading zeros in the binary representation of `self`.
+            ///
+            /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided.
             ///
-            #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")]
-            /// with the exception that `0` is not a valid instance.
-            #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")]
-            /// including in FFI.
+            /// # Examples
             ///
-            /// Thanks to the [null pointer optimization],
-            #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")]
-            /// are guaranteed to have the same size and alignment:
+            /// Basic usage:
             ///
             /// ```
-            /// # use std::mem::{size_of, align_of};
-            #[doc = concat!("use std::num::", stringify!($Ty), ";")]
+            #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", $leading_zeros_test, ").unwrap();")]
             ///
-            #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::<Option<", stringify!($Ty), ">>());")]
-            #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::<Option<", stringify!($Ty), ">>());")]
+            /// assert_eq!(n.leading_zeros(), 0);
             /// ```
+            #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
+            #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
+            #[must_use = "this returns the result of the operation, \
+                          without modifying the original"]
+            #[inline]
+            pub const fn leading_zeros(self) -> u32 {
+                // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`.
+                unsafe { intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
+            }
+
+            /// Returns the number of trailing zeros in the binary representation
+            /// of `self`.
             ///
-            /// [null pointer optimization]: crate::option#representation
-            #[$stability]
-            #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-            #[repr(transparent)]
-            #[rustc_layout_scalar_valid_range_start(1)]
-            #[rustc_nonnull_optimization_guaranteed]
-            #[rustc_diagnostic_item = stringify!($Ty)]
-            pub struct $Ty($Int);
-
-            impl $Ty {
-                /// Creates a non-zero without checking whether the value is non-zero.
-                /// This results in undefined behaviour if the value is zero.
-                ///
-                /// # Safety
-                ///
-                /// The value must not be zero.
-                #[$stability]
-                #[$const_new_unchecked_stability]
-                #[must_use]
-                #[inline]
-                pub const unsafe fn new_unchecked(n: $Int) -> Self {
-                    crate::panic::debug_assert_nounwind!(
-                        n != 0,
-                        concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument")
-                    );
-                    // SAFETY: this is guaranteed to be safe by the caller.
-                    unsafe {
-                        Self(n)
-                    }
-                }
+            /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")]
+            ///
+            /// assert_eq!(n.trailing_zeros(), 3);
+            /// ```
+            #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
+            #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
+            #[must_use = "this returns the result of the operation, \
+                          without modifying the original"]
+            #[inline]
+            pub const fn trailing_zeros(self) -> u32 {
+                // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`.
+                unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
+            }
 
-                /// Creates a non-zero if the given value is not zero.
-                #[$stability]
-                #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")]
-                #[must_use]
-                #[inline]
-                pub const fn new(n: $Int) -> Option<Self> {
-                    if n != 0 {
-                        // SAFETY: we just checked that there's no `0`
-                        Some(unsafe { Self(n) })
-                    } else {
-                        None
-                    }
-                }
+            nonzero_integer_signedness_dependent_methods! {
+                Self = $Ty,
+                Primitive = $signedness $Int,
+                $(UnsignedNonZero = $UnsignedNonZero,)?
+                UnsignedPrimitive = $UnsignedPrimitive,
+            }
 
-                /// Returns the value as a primitive type.
-                #[$stability]
-                #[inline]
-                #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")]
-                pub const fn get(self) -> $Int {
-                    // FIXME: Remove this after LLVM supports `!range` metadata for function
-                    // arguments https://github.com/llvm/llvm-project/issues/76628
+            /// Multiplies two non-zero integers together.
+            /// Checks for overflow and returns [`None`] on overflow.
+            /// As a consequence, the result cannot wrap to zero.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # fn main() { test().unwrap(); }
+            /// # fn test() -> Option<()> {
+            #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+            #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+            #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                            stringify!($Int), "::MAX)?;")]
+            ///
+            /// assert_eq!(Some(four), two.checked_mul(two));
+            /// assert_eq!(None, max.checked_mul(two));
+            /// # Some(())
+            /// # }
+            /// ```
+            #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+            #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+            #[must_use = "this returns the result of the operation, \
+                          without modifying the original"]
+            #[inline]
+            pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> {
+                if let Some(result) = self.get().checked_mul(other.get()) {
+                    // SAFETY:
+                    // - `checked_mul` returns `None` on overflow
+                    // - `self` and `other` are non-zero
+                    // - the only way to get zero from a multiplication without overflow is for one
+                    //   of the sides to be zero
                     //
-                    // Rustc can set range metadata only if it loads `self` from
-                    // memory somewhere. If the value of `self` was from by-value argument
-                    // of some not-inlined function, LLVM don't have range metadata
-                    // to understand that the value cannot be zero.
-
-                    // SAFETY: It is an invariant of this type.
-                    unsafe {
-                        intrinsics::assume(self.0 != 0);
-                    }
-                    self.0
+                    // So the result cannot be zero.
+                    Some(unsafe { $Ty::new_unchecked(result) })
+                } else {
+                    None
                 }
+            }
 
+            /// Multiplies two non-zero integers together.
+            #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # fn main() { test().unwrap(); }
+            /// # fn test() -> Option<()> {
+            #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+            #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+            #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                            stringify!($Int), "::MAX)?;")]
+            ///
+            /// assert_eq!(four, two.saturating_mul(two));
+            /// assert_eq!(max, four.saturating_mul(max));
+            /// # Some(())
+            /// # }
+            /// ```
+            #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+            #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+            #[must_use = "this returns the result of the operation, \
+                          without modifying the original"]
+            #[inline]
+            pub const fn saturating_mul(self, other: $Ty) -> $Ty {
+                // SAFETY:
+                // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow,
+                //   all of which are non-zero
+                // - `self` and `other` are non-zero
+                // - the only way to get zero from a multiplication without overflow is for one
+                //   of the sides to be zero
+                //
+                // So the result cannot be zero.
+                unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) }
             }
 
-            #[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()
+            /// Multiplies two non-zero integers together,
+            /// assuming overflow cannot occur.
+            /// Overflow is unchecked, and it is undefined behaviour to overflow
+            /// *even if the result would wrap to a non-zero value*.
+            /// The behaviour is undefined as soon as
+            #[doc = sign_dependent_expr!{
+                $signedness ?
+                if signed {
+                    concat!("`self * rhs > ", stringify!($Int), "::MAX`, ",
+                            "or `self * rhs < ", stringify!($Int), "::MIN`.")
                 }
+                if unsigned {
+                    concat!("`self * rhs > ", stringify!($Int), "::MAX`.")
+                }
+            }]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// #![feature(nonzero_ops)]
+            ///
+            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # fn main() { test().unwrap(); }
+            /// # fn test() -> Option<()> {
+            #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+            #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+            ///
+            /// assert_eq!(four, unsafe { two.unchecked_mul(two) });
+            /// # Some(())
+            /// # }
+            /// ```
+            #[unstable(feature = "nonzero_ops", issue = "84186")]
+            #[must_use = "this returns the result of the operation, \
+                          without modifying the original"]
+            #[inline]
+            pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty {
+                // SAFETY: The caller ensures there is no overflow.
+                unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.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 { $Ty::new_unchecked(self.get() | rhs.get()) }
+            /// Raises non-zero value to an integer power.
+            /// Checks for overflow and returns [`None`] on overflow.
+            /// As a consequence, the result cannot wrap to zero.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # fn main() { test().unwrap(); }
+            /// # fn test() -> Option<()> {
+            #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
+            #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")]
+            #[doc = concat!("let half_max = ", stringify!($Ty), "::new(",
+                            stringify!($Int), "::MAX / 2)?;")]
+            ///
+            /// assert_eq!(Some(twenty_seven), three.checked_pow(3));
+            /// assert_eq!(None, half_max.checked_pow(3));
+            /// # Some(())
+            /// # }
+            /// ```
+            #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+            #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+            #[must_use = "this returns the result of the operation, \
+                          without modifying the original"]
+            #[inline]
+            pub const fn checked_pow(self, other: u32) -> Option<$Ty> {
+                if let Some(result) = self.get().checked_pow(other) {
+                    // SAFETY:
+                    // - `checked_pow` returns `None` on overflow/underflow
+                    // - `self` is non-zero
+                    // - the only way to get zero from an exponentiation without overflow is
+                    //   for base to be zero
+                    //
+                    // So the result cannot be zero.
+                    Some(unsafe { $Ty::new_unchecked(result) })
+                } else {
+                    None
                 }
             }
 
-            #[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 { $Ty::new_unchecked(self.get() | rhs) }
+            /// Raise non-zero value to an integer power.
+            #[doc = sign_dependent_expr!{
+                $signedness ?
+                if signed {
+                    concat!("Return [`", stringify!($Ty), "::MIN`] ",
+                                "or [`", stringify!($Ty), "::MAX`] on overflow.")
                 }
+                if unsigned {
+                    concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")
+                }
+            }]
+            ///
+            /// # Examples
+            ///
+            /// ```
+            #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+            /// # fn main() { test().unwrap(); }
+            /// # fn test() -> Option<()> {
+            #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
+            #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")]
+            #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                            stringify!($Int), "::MAX)?;")]
+            ///
+            /// assert_eq!(twenty_seven, three.saturating_pow(3));
+            /// assert_eq!(max, max.saturating_pow(3));
+            /// # Some(())
+            /// # }
+            /// ```
+            #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+            #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+            #[must_use = "this returns the result of the operation, \
+                          without modifying the original"]
+            #[inline]
+            pub const fn saturating_pow(self, other: u32) -> $Ty {
+                // SAFETY:
+                // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow,
+                //   all of which are non-zero
+                // - `self` is non-zero
+                // - the only way to get zero from an exponentiation without overflow is
+                //   for base to be zero
+                //
+                // So the result cannot be zero.
+                unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) }
             }
+        }
 
-            #[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 = "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 { $Ty::new_unchecked(self.get() | 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 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 { $Ty::new_unchecked(self.get() | 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;
-                }
+        #[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()) }
             }
+        }
 
-            impl_nonzero_fmt! {
-                #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
+        #[stable(feature = "nonzero_bitor", since = "1.45.0")]
+        impl BitOrAssign for $Ty {
+            #[inline]
+            fn bitor_assign(&mut self, rhs: Self) {
+                *self = *self | rhs;
             }
-        )+
-    }
-}
+        }
 
-nonzero_integers! {
-    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
-    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
-    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
-    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
-    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
-    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
-}
+        #[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
+        }
 
-macro_rules! from_str_radix_nzint_impl {
-    ($($t:ty)*) => {$(
         #[stable(feature = "nonzero_parse", since = "1.35.0")]
-        impl FromStr for $t {
+        impl FromStr for $Ty {
             type Err = ParseIntError;
             fn from_str(src: &str) -> Result<Self, Self::Err> {
                 Self::new(from_str_radix(src, 10)?)
@@ -280,989 +537,791 @@ macro_rules! from_str_radix_nzint_impl {
                     })
             }
         }
-    )*}
-}
-
-from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
-NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
 
-macro_rules! nonzero_leading_trailing_zeros {
-    ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => {
-        $(
-            impl $Ty {
-                /// Returns the number of leading zeros in the binary representation of `self`.
-                ///
-                /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided.
-                ///
-                /// # Examples
-                ///
-                /// Basic usage:
-                ///
-                /// ```
-                #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")]
-                ///
-                /// assert_eq!(n.leading_zeros(), 0);
-                /// ```
-                #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
-                #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn leading_zeros(self) -> u32 {
-                    // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`.
-                    unsafe { intrinsics::ctlz_nonzero(self.get() as $Uint) as u32 }
-                }
-
-                /// Returns the number of trailing zeros in the binary representation
-                /// of `self`.
-                ///
-                /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided.
-                ///
-                /// # Examples
-                ///
-                /// Basic usage:
-                ///
-                /// ```
-                #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")]
-                ///
-                /// assert_eq!(n.trailing_zeros(), 3);
-                /// ```
-                #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
-                #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn trailing_zeros(self) -> u32 {
-                    // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`.
-                    unsafe { intrinsics::cttz_nonzero(self.get() as $Uint) as u32 }
-                }
+        nonzero_integer_signedness_dependent_impls!($Ty $signedness $Int);
+    };
 
-            }
-        )+
-    }
-}
+    (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => {
+        nonzero_integer! {
+            #[stable(feature = "nonzero", since = "1.28.0")]
+            #[rustc_const_stable(feature = "nonzero", since = "1.28.0")]
+            Self = $Ty,
+            Primitive = unsigned $Int,
+            UnsignedPrimitive = $Int,
+            leading_zeros_test = concat!(stringify!($Int), "::MAX"),
+        }
+    };
 
-nonzero_leading_trailing_zeros! {
-    NonZeroU8(u8), u8::MAX;
-    NonZeroU16(u16), u16::MAX;
-    NonZeroU32(u32), u32::MAX;
-    NonZeroU64(u64), u64::MAX;
-    NonZeroU128(u128), u128::MAX;
-    NonZeroUsize(usize), usize::MAX;
-    NonZeroI8(u8), -1i8;
-    NonZeroI16(u16), -1i16;
-    NonZeroI32(u32), -1i32;
-    NonZeroI64(u64), -1i64;
-    NonZeroI128(u128), -1i128;
-    NonZeroIsize(usize), -1isize;
+    (Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => {
+        nonzero_integer! {
+            #[stable(feature = "signed_nonzero", since = "1.34.0")]
+            #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")]
+            Self = $Ty,
+            Primitive = signed $Int,
+            $($rest)*
+            leading_zeros_test = concat!("-1", stringify!($Int)),
+        }
+    };
 }
 
-macro_rules! nonzero_integers_div {
-    ( $( $Ty: ident($Int: ty); )+ ) => {
-        $(
-            #[stable(feature = "nonzero_div", since = "1.51.0")]
-            impl Div<$Ty> for $Int {
-                type Output = $Int;
-                /// This operation rounds towards zero,
-                /// truncating any fractional part of the exact result, and cannot panic.
-                #[inline]
-                fn div(self, other: $Ty) -> $Int {
-                    // SAFETY: div by zero is checked because `other` is a nonzero,
-                    // and MIN/-1 is checked because `self` is an unsigned int.
-                    unsafe { crate::intrinsics::unchecked_div(self, other.get()) }
-                }
+macro_rules! nonzero_integer_signedness_dependent_impls {
+    // Impls for unsigned nonzero types only.
+    ($Ty:ident unsigned $Int:ty) => {
+        #[stable(feature = "nonzero_div", since = "1.51.0")]
+        impl Div<$Ty> for $Int {
+            type Output = $Int;
+            /// This operation rounds towards zero,
+            /// truncating any fractional part of the exact result, and cannot panic.
+            #[inline]
+            fn div(self, other: $Ty) -> $Int {
+                // SAFETY: div by zero is checked because `other` is a nonzero,
+                // and MIN/-1 is checked because `self` is an unsigned int.
+                unsafe { crate::intrinsics::unchecked_div(self, other.get()) }
             }
+        }
 
-            #[stable(feature = "nonzero_div", since = "1.51.0")]
-            impl Rem<$Ty> for $Int {
-                type Output = $Int;
-                /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
-                #[inline]
-                fn rem(self, other: $Ty) -> $Int {
-                    // SAFETY: rem by zero is checked because `other` is a nonzero,
-                    // and MIN/-1 is checked because `self` is an unsigned int.
-                    unsafe { crate::intrinsics::unchecked_rem(self, other.get()) }
-                }
+        #[stable(feature = "nonzero_div", since = "1.51.0")]
+        impl Rem<$Ty> for $Int {
+            type Output = $Int;
+            /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
+            #[inline]
+            fn rem(self, other: $Ty) -> $Int {
+                // SAFETY: rem by zero is checked because `other` is a nonzero,
+                // and MIN/-1 is checked because `self` is an unsigned int.
+                unsafe { crate::intrinsics::unchecked_rem(self, other.get()) }
             }
-        )+
-    }
-}
-
-nonzero_integers_div! {
-    NonZeroU8(u8);
-    NonZeroU16(u16);
-    NonZeroU32(u32);
-    NonZeroU64(u64);
-    NonZeroU128(u128);
-    NonZeroUsize(usize);
-}
-
-// A bunch of methods for unsigned nonzero types only.
-macro_rules! nonzero_unsigned_operations {
-    ( $( $Ty: ident($Int: ident); )+ ) => {
-        $(
-            impl $Ty {
-                /// Adds an unsigned integer to a non-zero value.
-                /// Checks for overflow and returns [`None`] on overflow.
-                /// As a consequence, the result cannot wrap to zero.
-                ///
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(Some(two), one.checked_add(1));
-                /// assert_eq!(None, max.checked_add(1));
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn checked_add(self, other: $Int) -> Option<$Ty> {
-                    if let Some(result) = self.get().checked_add(other) {
-                        // SAFETY:
-                        // - `checked_add` returns `None` on overflow
-                        // - `self` is non-zero
-                        // - the only way to get zero from an addition without overflow is for both
-                        //   sides to be zero
-                        //
-                        // So the result cannot be zero.
-                        Some(unsafe { $Ty::new_unchecked(result) })
-                    } else {
-                        None
-                    }
-                }
-
-                /// Adds an unsigned integer to a non-zero value.
-                #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")]
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(two, one.saturating_add(1));
-                /// assert_eq!(max, max.saturating_add(1));
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn saturating_add(self, other: $Int) -> $Ty {
-                    // SAFETY:
-                    // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero
-                    // - `self` is non-zero
-                    // - the only way to get zero from an addition without overflow is for both
-                    //   sides to be zero
-                    //
-                    // So the result cannot be zero.
-                    unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) }
-                }
-
-                /// Adds an unsigned integer to a non-zero value,
-                /// assuming overflow cannot occur.
-                /// Overflow is unchecked, and it is undefined behaviour to overflow
-                /// *even if the result would wrap to a non-zero value*.
-                /// The behaviour is undefined as soon as
-                #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")]
-                ///
-                /// # Examples
-                ///
-                /// ```
-                /// #![feature(nonzero_ops)]
-                ///
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-                ///
-                /// assert_eq!(two, unsafe { one.unchecked_add(1) });
-                /// # Some(())
-                /// # }
-                /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty {
-                    // SAFETY: The caller ensures there is no overflow.
-                    unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) }
-                }
-
-                /// Returns the smallest power of two greater than or equal to n.
-                /// Checks for overflow and returns [`None`]
-                /// if the next power of two is greater than the type’s maximum value.
-                /// As a consequence, the result cannot wrap to zero.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-                #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
-                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
-                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(Some(two), two.checked_next_power_of_two() );
-                /// assert_eq!(Some(four), three.checked_next_power_of_two() );
-                /// assert_eq!(None, max.checked_next_power_of_two() );
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn checked_next_power_of_two(self) -> Option<$Ty> {
-                    if let Some(nz) = self.get().checked_next_power_of_two() {
-                        // SAFETY: The next power of two is positive
-                        // and overflow is checked.
-                        Some(unsafe { $Ty::new_unchecked(nz) })
-                    } else {
-                        None
-                    }
-                }
-
-                /// Returns the base 2 logarithm of the number, rounded down.
-                ///
-                /// This is the same operation as
-                #[doc = concat!("[`", stringify!($Int), "::ilog2`],")]
-                /// except that it has no failure cases to worry about
-                /// since this value can never be zero.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")]
-                /// ```
-                #[stable(feature = "int_log", since = "1.67.0")]
-                #[rustc_const_stable(feature = "int_log", since = "1.67.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn ilog2(self) -> u32 {
-                    Self::BITS - 1 - self.leading_zeros()
-                }
+        }
+    };
 
-                /// Returns the base 10 logarithm of the number, rounded down.
-                ///
-                /// This is the same operation as
-                #[doc = concat!("[`", stringify!($Int), "::ilog10`],")]
-                /// except that it has no failure cases to worry about
-                /// since this value can never be zero.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")]
-                /// ```
-                #[stable(feature = "int_log", since = "1.67.0")]
-                #[rustc_const_stable(feature = "int_log", since = "1.67.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn ilog10(self) -> u32 {
-                    super::int_log10::$Int(self.get())
-                }
+    // Impls for signed nonzero types only.
+    ($Ty:ident signed $Int:ty) => {
+        #[stable(feature = "signed_nonzero_neg", since = "1.71.0")]
+        impl Neg for $Ty {
+            type Output = $Ty;
 
-                /// Calculates the middle point of `self` and `rhs`.
-                ///
-                /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
-                /// sufficiently-large signed integral type. This implies that the result is
-                /// always rounded towards negative infinity and that no overflow will ever occur.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                /// #![feature(num_midpoint)]
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                ///
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
-                ///
-                /// assert_eq!(one.midpoint(four), two);
-                /// assert_eq!(four.midpoint(one), two);
-                /// # Some(())
-                /// # }
-                /// ```
-                #[unstable(feature = "num_midpoint", issue = "110840")]
-                #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
-                #[rustc_allow_const_fn_unstable(const_num_midpoint)]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn midpoint(self, rhs: Self) -> Self {
-                    // SAFETY: The only way to get `0` with midpoint is to have two opposite or
-                    // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because
-                    // of the unsignedness of this number and also because $Ty is guaranteed to
-                    // never being 0.
-                    unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) }
-                }
+            #[inline]
+            fn neg(self) -> $Ty {
+                // SAFETY: negation of nonzero cannot yield zero values.
+                unsafe { $Ty::new_unchecked(self.get().neg()) }
             }
-        )+
-    }
-}
+        }
 
-nonzero_unsigned_operations! {
-    NonZeroU8(u8);
-    NonZeroU16(u16);
-    NonZeroU32(u32);
-    NonZeroU64(u64);
-    NonZeroU128(u128);
-    NonZeroUsize(usize);
+        forward_ref_unop! { impl Neg, neg for $Ty,
+        #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] }
+    };
 }
 
-// A bunch of methods for signed nonzero types only.
-macro_rules! nonzero_signed_operations {
-    ( $( $Ty: ident($Int: ty) -> $Uty: ident($Uint: ty); )+ ) => {
-        $(
-            impl $Ty {
-                /// Computes the absolute value of self.
-                #[doc = concat!("See [`", stringify!($Int), "::abs`]")]
-                /// for documentation on overflow behaviour.
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-                ///
-                /// assert_eq!(pos, pos.abs());
-                /// assert_eq!(pos, neg.abs());
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn abs(self) -> $Ty {
-                    // SAFETY: This cannot overflow to zero.
-                    unsafe { $Ty::new_unchecked(self.get().abs()) }
-                }
-
-                /// Checked absolute value.
-                /// Checks for overflow and returns [`None`] if
-                #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")]
-                /// The result cannot be zero.
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                ///
-                /// assert_eq!(Some(pos), neg.checked_abs());
-                /// assert_eq!(None, min.checked_abs());
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn checked_abs(self) -> Option<$Ty> {
-                    if let Some(nz) = self.get().checked_abs() {
-                        // SAFETY: absolute value of nonzero cannot yield zero values.
-                        Some(unsafe { $Ty::new_unchecked(nz) })
-                    } else {
-                        None
-                    }
-                }
-
-                /// Computes the absolute value of self,
-                /// with overflow information, see
-                #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")]
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                ///
-                /// assert_eq!((pos, false), pos.overflowing_abs());
-                /// assert_eq!((pos, false), neg.overflowing_abs());
-                /// assert_eq!((min, true), min.overflowing_abs());
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn overflowing_abs(self) -> ($Ty, bool) {
-                    let (nz, flag) = self.get().overflowing_abs();
-                    (
-                        // SAFETY: absolute value of nonzero cannot yield zero values.
-                        unsafe { $Ty::new_unchecked(nz) },
-                        flag,
-                    )
-                }
+#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5974
+macro_rules! nonzero_integer_signedness_dependent_methods {
+    // Associated items for unsigned nonzero types only.
+    (
+        Self = $Ty:ident,
+        Primitive = unsigned $Int:ident,
+        UnsignedPrimitive = $Uint:ty,
+    ) => {
+        /// The smallest value that can be represented by this non-zero
+        /// integer type, 1.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")]
+        /// ```
+        #[stable(feature = "nonzero_min_max", since = "1.70.0")]
+        pub const MIN: Self = Self::new(1).unwrap();
+
+        /// The largest value that can be represented by this non-zero
+        /// integer type,
+        #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")]
+        /// ```
+        #[stable(feature = "nonzero_min_max", since = "1.70.0")]
+        pub const MAX: Self = Self::new(<$Int>::MAX).unwrap();
+
+        /// Adds an unsigned integer to a non-zero value.
+        /// Checks for overflow and returns [`None`] on overflow.
+        /// As a consequence, the result cannot wrap to zero.
+        ///
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MAX)?;")]
+        ///
+        /// assert_eq!(Some(two), one.checked_add(1));
+        /// assert_eq!(None, max.checked_add(1));
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_add(self, other: $Int) -> Option<$Ty> {
+            if let Some(result) = self.get().checked_add(other) {
+                // SAFETY:
+                // - `checked_add` returns `None` on overflow
+                // - `self` is non-zero
+                // - the only way to get zero from an addition without overflow is for both
+                //   sides to be zero
+                //
+                // So the result cannot be zero.
+                Some(unsafe { $Ty::new_unchecked(result) })
+            } else {
+                None
+            }
+        }
 
-                /// Saturating absolute value, see
-                #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")]
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN + 1)?;")]
-                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(pos, pos.saturating_abs());
-                /// assert_eq!(pos, neg.saturating_abs());
-                /// assert_eq!(max, min.saturating_abs());
-                /// assert_eq!(max, min_plus.saturating_abs());
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn saturating_abs(self) -> $Ty {
-                    // SAFETY: absolute value of nonzero cannot yield zero values.
-                    unsafe { $Ty::new_unchecked(self.get().saturating_abs()) }
-                }
+        /// Adds an unsigned integer to a non-zero value.
+        #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MAX)?;")]
+        ///
+        /// assert_eq!(two, one.saturating_add(1));
+        /// assert_eq!(max, max.saturating_add(1));
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_add(self, other: $Int) -> $Ty {
+            // SAFETY:
+            // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero
+            // - `self` is non-zero
+            // - the only way to get zero from an addition without overflow is for both
+            //   sides to be zero
+            //
+            // So the result cannot be zero.
+            unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) }
+        }
 
-                /// Wrapping absolute value, see
-                #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")]
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
-                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                #[doc = concat!("# let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(pos, pos.wrapping_abs());
-                /// assert_eq!(pos, neg.wrapping_abs());
-                /// assert_eq!(min, min.wrapping_abs());
-                /// assert_eq!(max, (-max).wrapping_abs());
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn wrapping_abs(self) -> $Ty {
-                    // SAFETY: absolute value of nonzero cannot yield zero values.
-                    unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) }
-                }
+        /// Adds an unsigned integer to a non-zero value,
+        /// assuming overflow cannot occur.
+        /// Overflow is unchecked, and it is undefined behaviour to overflow
+        /// *even if the result would wrap to a non-zero value*.
+        /// The behaviour is undefined as soon as
+        #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")]
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(nonzero_ops)]
+        ///
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+        ///
+        /// assert_eq!(two, unsafe { one.unchecked_add(1) });
+        /// # Some(())
+        /// # }
+        /// ```
+        #[unstable(feature = "nonzero_ops", issue = "84186")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty {
+            // SAFETY: The caller ensures there is no overflow.
+            unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) }
+        }
 
-                /// Computes the absolute value of self
-                /// without any wrapping or panicking.
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                #[doc = concat!("# use std::num::", stringify!($Uty), ";")]
-                ///
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")]
-                #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")]
-                #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")]
-                #[doc = concat!("let i_min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                #[doc = concat!("let u_max = ", stringify!($Uty), "::new(",
-                                stringify!($Uint), "::MAX / 2 + 1)?;")]
-                ///
-                /// assert_eq!(u_pos, i_pos.unsigned_abs());
-                /// assert_eq!(u_pos, i_neg.unsigned_abs());
-                /// assert_eq!(u_max, i_min.unsigned_abs());
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn unsigned_abs(self) -> $Uty {
-                    // SAFETY: absolute value of nonzero cannot yield zero values.
-                    unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
-                }
+        /// Returns the smallest power of two greater than or equal to n.
+        /// Checks for overflow and returns [`None`]
+        /// if the next power of two is greater than the type’s maximum value.
+        /// As a consequence, the result cannot wrap to zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+        #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
+        #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MAX)?;")]
+        ///
+        /// assert_eq!(Some(two), two.checked_next_power_of_two() );
+        /// assert_eq!(Some(four), three.checked_next_power_of_two() );
+        /// assert_eq!(None, max.checked_next_power_of_two() );
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_next_power_of_two(self) -> Option<$Ty> {
+            if let Some(nz) = self.get().checked_next_power_of_two() {
+                // SAFETY: The next power of two is positive
+                // and overflow is checked.
+                Some(unsafe { $Ty::new_unchecked(nz) })
+            } else {
+                None
+            }
+        }
 
-                /// Returns `true` if `self` is positive and `false` if the
-                /// number is negative.
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-                ///
-                /// assert!(pos_five.is_positive());
-                /// assert!(!neg_five.is_positive());
-                /// # Some(())
-                /// # }
-                /// ```
-                #[must_use]
-                #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                pub const fn is_positive(self) -> bool {
-                    self.get().is_positive()
-                }
+        /// Returns the base 2 logarithm of the number, rounded down.
+        ///
+        /// This is the same operation as
+        #[doc = concat!("[`", stringify!($Int), "::ilog2`],")]
+        /// except that it has no failure cases to worry about
+        /// since this value can never be zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")]
+        /// ```
+        #[stable(feature = "int_log", since = "1.67.0")]
+        #[rustc_const_stable(feature = "int_log", since = "1.67.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn ilog2(self) -> u32 {
+            Self::BITS - 1 - self.leading_zeros()
+        }
 
-                /// Returns `true` if `self` is negative and `false` if the
-                /// number is positive.
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-                ///
-                /// assert!(neg_five.is_negative());
-                /// assert!(!pos_five.is_negative());
-                /// # Some(())
-                /// # }
-                /// ```
-                #[must_use]
-                #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                pub const fn is_negative(self) -> bool {
-                    self.get().is_negative()
-                }
+        /// Returns the base 10 logarithm of the number, rounded down.
+        ///
+        /// This is the same operation as
+        #[doc = concat!("[`", stringify!($Int), "::ilog10`],")]
+        /// except that it has no failure cases to worry about
+        /// since this value can never be zero.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")]
+        /// ```
+        #[stable(feature = "int_log", since = "1.67.0")]
+        #[rustc_const_stable(feature = "int_log", since = "1.67.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn ilog10(self) -> u32 {
+            super::int_log10::$Int(self.get())
+        }
 
-                /// Checked negation. Computes `-self`,
-                #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")]
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                ///
-                /// assert_eq!(pos_five.checked_neg(), Some(neg_five));
-                /// assert_eq!(min.checked_neg(), None);
-                /// # Some(())
-                /// # }
-                /// ```
-                #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                pub const fn checked_neg(self) -> Option<$Ty> {
-                    if let Some(result) = self.get().checked_neg() {
-                        // SAFETY: negation of nonzero cannot yield zero values.
-                        return Some(unsafe { $Ty::new_unchecked(result) });
-                    }
-                    None
-                }
+        /// Calculates the middle point of `self` and `rhs`.
+        ///
+        /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+        /// sufficiently-large signed integral type. This implies that the result is
+        /// always rounded towards negative infinity and that no overflow will ever occur.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_midpoint)]
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        ///
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+        #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+        ///
+        /// assert_eq!(one.midpoint(four), two);
+        /// assert_eq!(four.midpoint(one), two);
+        /// # Some(())
+        /// # }
+        /// ```
+        #[unstable(feature = "num_midpoint", issue = "110840")]
+        #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+        #[rustc_allow_const_fn_unstable(const_num_midpoint)]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn midpoint(self, rhs: Self) -> Self {
+            // SAFETY: The only way to get `0` with midpoint is to have two opposite or
+            // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because
+            // of the unsignedness of this number and also because $Ty is guaranteed to
+            // never being 0.
+            unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) }
+        }
 
-                /// Negates self, overflowing if this is equal to the minimum value.
-                ///
-                #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")]
-                /// for documentation on overflow behaviour.
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                ///
-                /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false));
-                /// assert_eq!(min.overflowing_neg(), (min, true));
-                /// # Some(())
-                /// # }
-                /// ```
-                #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                pub const fn overflowing_neg(self) -> ($Ty, bool) {
-                    let (result, overflow) = self.get().overflowing_neg();
-                    // SAFETY: negation of nonzero cannot yield zero values.
-                    ((unsafe { $Ty::new_unchecked(result) }), overflow)
-                }
+        /// Returns `true` if and only if `self == (1 << k)` for some `k`.
+        ///
+        /// On many architectures, this function can perform better than `is_power_of_two()`
+        /// on the underlying integer type, as special handling of zero can be avoided.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")]
+        /// assert!(eight.is_power_of_two());
+        #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")]
+        /// assert!(!ten.is_power_of_two());
+        /// ```
+        #[must_use]
+        #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")]
+        #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")]
+        #[inline]
+        pub const fn is_power_of_two(self) -> bool {
+            // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here.
+            // On the basic x86-64 target, this saves 3 instructions for the zero check.
+            // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction
+            // compared to the `POPCNT` implementation on the underlying integer type.
+
+            intrinsics::ctpop(self.get()) < 2
+        }
+    };
 
-                /// Saturating negation. Computes `-self`,
-                #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")]
-                #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")]
-                /// instead of overflowing.
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN + 1)?;")]
-                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(pos_five.saturating_neg(), neg_five);
-                /// assert_eq!(min.saturating_neg(), max);
-                /// assert_eq!(max.saturating_neg(), min_plus_one);
-                /// # Some(())
-                /// # }
-                /// ```
-                #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                pub const fn saturating_neg(self) -> $Ty {
-                    if let Some(result) = self.checked_neg() {
-                        return result;
-                    }
-                    $Ty::MAX
-                }
+    // Associated items for signed nonzero types only.
+    (
+        Self = $Ty:ident,
+        Primitive = signed $Int:ident,
+        UnsignedNonZero = $Uty:ident,
+        UnsignedPrimitive = $Uint:ty,
+    ) => {
+        /// The smallest value that can be represented by this non-zero
+        /// integer type,
+        #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")]
+        ///
+        /// Note: While most integer types are defined for every whole
+        /// number between `MIN` and `MAX`, signed non-zero integers are
+        /// a special case. They have a "gap" at 0.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")]
+        /// ```
+        #[stable(feature = "nonzero_min_max", since = "1.70.0")]
+        pub const MIN: Self = Self::new(<$Int>::MIN).unwrap();
+
+        /// The largest value that can be represented by this non-zero
+        /// integer type,
+        #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")]
+        ///
+        /// Note: While most integer types are defined for every whole
+        /// number between `MIN` and `MAX`, signed non-zero integers are
+        /// a special case. They have a "gap" at 0.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")]
+        /// ```
+        #[stable(feature = "nonzero_min_max", since = "1.70.0")]
+        pub const MAX: Self = Self::new(<$Int>::MAX).unwrap();
+
+        /// Computes the absolute value of self.
+        #[doc = concat!("See [`", stringify!($Int), "::abs`]")]
+        /// for documentation on overflow behaviour.
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+        ///
+        /// assert_eq!(pos, pos.abs());
+        /// assert_eq!(pos, neg.abs());
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn abs(self) -> $Ty {
+            // SAFETY: This cannot overflow to zero.
+            unsafe { $Ty::new_unchecked(self.get().abs()) }
+        }
 
-                /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
-                /// of the type.
-                ///
-                #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")]
-                /// for documentation on overflow behaviour.
-                ///
-                /// # Example
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
-                #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
-                #[doc = concat!("let min = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MIN)?;")]
-                ///
-                /// assert_eq!(pos_five.wrapping_neg(), neg_five);
-                /// assert_eq!(min.wrapping_neg(), min);
-                /// # Some(())
-                /// # }
-                /// ```
-                #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
-                pub const fn wrapping_neg(self) -> $Ty {
-                    let result = self.get().wrapping_neg();
-                    // SAFETY: negation of nonzero cannot yield zero values.
-                    unsafe { $Ty::new_unchecked(result) }
-                }
+        /// Checked absolute value.
+        /// Checks for overflow and returns [`None`] if
+        #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")]
+        /// The result cannot be zero.
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        ///
+        /// assert_eq!(Some(pos), neg.checked_abs());
+        /// assert_eq!(None, min.checked_abs());
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_abs(self) -> Option<$Ty> {
+            if let Some(nz) = self.get().checked_abs() {
+                // SAFETY: absolute value of nonzero cannot yield zero values.
+                Some(unsafe { $Ty::new_unchecked(nz) })
+            } else {
+                None
             }
+        }
 
-            #[stable(feature = "signed_nonzero_neg", since = "1.71.0")]
-            impl Neg for $Ty {
-                type Output = $Ty;
+        /// Computes the absolute value of self,
+        /// with overflow information, see
+        #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")]
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        ///
+        /// assert_eq!((pos, false), pos.overflowing_abs());
+        /// assert_eq!((pos, false), neg.overflowing_abs());
+        /// assert_eq!((min, true), min.overflowing_abs());
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn overflowing_abs(self) -> ($Ty, bool) {
+            let (nz, flag) = self.get().overflowing_abs();
+            (
+                // SAFETY: absolute value of nonzero cannot yield zero values.
+                unsafe { $Ty::new_unchecked(nz) },
+                flag,
+            )
+        }
 
-                #[inline]
-                fn neg(self) -> $Ty {
-                    // SAFETY: negation of nonzero cannot yield zero values.
-                    unsafe { $Ty::new_unchecked(self.get().neg()) }
-                }
-            }
+        /// Saturating absolute value, see
+        #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")]
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN + 1)?;")]
+        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MAX)?;")]
+        ///
+        /// assert_eq!(pos, pos.saturating_abs());
+        /// assert_eq!(pos, neg.saturating_abs());
+        /// assert_eq!(max, min.saturating_abs());
+        /// assert_eq!(max, min_plus.saturating_abs());
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_abs(self) -> $Ty {
+            // SAFETY: absolute value of nonzero cannot yield zero values.
+            unsafe { $Ty::new_unchecked(self.get().saturating_abs()) }
+        }
 
-            forward_ref_unop! { impl Neg, neg for $Ty,
-                #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] }
-        )+
-    }
-}
+        /// Wrapping absolute value, see
+        #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")]
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")]
+        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("# let max = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MAX)?;")]
+        ///
+        /// assert_eq!(pos, pos.wrapping_abs());
+        /// assert_eq!(pos, neg.wrapping_abs());
+        /// assert_eq!(min, min.wrapping_abs());
+        /// assert_eq!(max, (-max).wrapping_abs());
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn wrapping_abs(self) -> $Ty {
+            // SAFETY: absolute value of nonzero cannot yield zero values.
+            unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) }
+        }
 
-nonzero_signed_operations! {
-    NonZeroI8(i8) -> NonZeroU8(u8);
-    NonZeroI16(i16) -> NonZeroU16(u16);
-    NonZeroI32(i32) -> NonZeroU32(u32);
-    NonZeroI64(i64) -> NonZeroU64(u64);
-    NonZeroI128(i128) -> NonZeroU128(u128);
-    NonZeroIsize(isize) -> NonZeroUsize(usize);
-}
+        /// Computes the absolute value of self
+        /// without any wrapping or panicking.
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        #[doc = concat!("# use std::num::", stringify!($Uty), ";")]
+        ///
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")]
+        #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")]
+        #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")]
+        #[doc = concat!("let i_min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let u_max = ", stringify!($Uty), "::new(",
+                        stringify!($Uint), "::MAX / 2 + 1)?;")]
+        ///
+        /// assert_eq!(u_pos, i_pos.unsigned_abs());
+        /// assert_eq!(u_pos, i_neg.unsigned_abs());
+        /// assert_eq!(u_max, i_min.unsigned_abs());
+        /// # Some(())
+        /// # }
+        /// ```
+        #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
+        #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn unsigned_abs(self) -> $Uty {
+            // SAFETY: absolute value of nonzero cannot yield zero values.
+            unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
+        }
 
-// A bunch of methods for both signed and unsigned nonzero types.
-macro_rules! nonzero_unsigned_signed_operations {
-    ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => {
-        $(
-            impl $Ty {
-                /// Multiplies two non-zero integers together.
-                /// Checks for overflow and returns [`None`] on overflow.
-                /// As a consequence, the result cannot wrap to zero.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
-                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(Some(four), two.checked_mul(two));
-                /// assert_eq!(None, max.checked_mul(two));
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> {
-                    if let Some(result) = self.get().checked_mul(other.get()) {
-                        // SAFETY:
-                        // - `checked_mul` returns `None` on overflow
-                        // - `self` and `other` are non-zero
-                        // - the only way to get zero from a multiplication without overflow is for one
-                        //   of the sides to be zero
-                        //
-                        // So the result cannot be zero.
-                        Some(unsafe { $Ty::new_unchecked(result) })
-                    } else {
-                        None
-                    }
-                }
+        /// Returns `true` if `self` is positive and `false` if the
+        /// number is negative.
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+        ///
+        /// assert!(pos_five.is_positive());
+        /// assert!(!neg_five.is_positive());
+        /// # Some(())
+        /// # }
+        /// ```
+        #[must_use]
+        #[inline]
+        #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        pub const fn is_positive(self) -> bool {
+            self.get().is_positive()
+        }
 
-                /// Multiplies two non-zero integers together.
-                #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")]
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
-                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(four, two.saturating_mul(two));
-                /// assert_eq!(max, four.saturating_mul(max));
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn saturating_mul(self, other: $Ty) -> $Ty {
-                    // SAFETY:
-                    // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow,
-                    //   all of which are non-zero
-                    // - `self` and `other` are non-zero
-                    // - the only way to get zero from a multiplication without overflow is for one
-                    //   of the sides to be zero
-                    //
-                    // So the result cannot be zero.
-                    unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) }
-                }
+        /// Returns `true` if `self` is negative and `false` if the
+        /// number is positive.
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+        ///
+        /// assert!(neg_five.is_negative());
+        /// assert!(!pos_five.is_negative());
+        /// # Some(())
+        /// # }
+        /// ```
+        #[must_use]
+        #[inline]
+        #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        pub const fn is_negative(self) -> bool {
+            self.get().is_negative()
+        }
 
-                /// Multiplies two non-zero integers together,
-                /// assuming overflow cannot occur.
-                /// Overflow is unchecked, and it is undefined behaviour to overflow
-                /// *even if the result would wrap to a non-zero value*.
-                /// The behaviour is undefined as soon as
-                #[doc = sign_dependent_expr!{
-                    $signedness ?
-                    if signed {
-                        concat!("`self * rhs > ", stringify!($Int), "::MAX`, ",
-                                "or `self * rhs < ", stringify!($Int), "::MIN`.")
-                    }
-                    if unsigned {
-                        concat!("`self * rhs > ", stringify!($Int), "::MAX`.")
-                    }
-                }]
-                ///
-                /// # Examples
-                ///
-                /// ```
-                /// #![feature(nonzero_ops)]
-                ///
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
-                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
-                ///
-                /// assert_eq!(four, unsafe { two.unchecked_mul(two) });
-                /// # Some(())
-                /// # }
-                /// ```
-                #[unstable(feature = "nonzero_ops", issue = "84186")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty {
-                    // SAFETY: The caller ensures there is no overflow.
-                    unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) }
-                }
+        /// Checked negation. Computes `-self`,
+        #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")]
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        ///
+        /// assert_eq!(pos_five.checked_neg(), Some(neg_five));
+        /// assert_eq!(min.checked_neg(), None);
+        /// # Some(())
+        /// # }
+        /// ```
+        #[inline]
+        #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        pub const fn checked_neg(self) -> Option<$Ty> {
+            if let Some(result) = self.get().checked_neg() {
+                // SAFETY: negation of nonzero cannot yield zero values.
+                return Some(unsafe { $Ty::new_unchecked(result) });
+            }
+            None
+        }
 
-                /// Raises non-zero value to an integer power.
-                /// Checks for overflow and returns [`None`] on overflow.
-                /// As a consequence, the result cannot wrap to zero.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
-                #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")]
-                #[doc = concat!("let half_max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX / 2)?;")]
-                ///
-                /// assert_eq!(Some(twenty_seven), three.checked_pow(3));
-                /// assert_eq!(None, half_max.checked_pow(3));
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn checked_pow(self, other: u32) -> Option<$Ty> {
-                    if let Some(result) = self.get().checked_pow(other) {
-                        // SAFETY:
-                        // - `checked_pow` returns `None` on overflow/underflow
-                        // - `self` is non-zero
-                        // - the only way to get zero from an exponentiation without overflow is
-                        //   for base to be zero
-                        //
-                        // So the result cannot be zero.
-                        Some(unsafe { $Ty::new_unchecked(result) })
-                    } else {
-                        None
-                    }
-                }
+        /// Negates self, overflowing if this is equal to the minimum value.
+        ///
+        #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")]
+        /// for documentation on overflow behaviour.
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        ///
+        /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false));
+        /// assert_eq!(min.overflowing_neg(), (min, true));
+        /// # Some(())
+        /// # }
+        /// ```
+        #[inline]
+        #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        pub const fn overflowing_neg(self) -> ($Ty, bool) {
+            let (result, overflow) = self.get().overflowing_neg();
+            // SAFETY: negation of nonzero cannot yield zero values.
+            ((unsafe { $Ty::new_unchecked(result) }), overflow)
+        }
 
-                /// Raise non-zero value to an integer power.
-                #[doc = sign_dependent_expr!{
-                    $signedness ?
-                    if signed {
-                        concat!("Return [`", stringify!($Ty), "::MIN`] ",
-                                    "or [`", stringify!($Ty), "::MAX`] on overflow.")
-                    }
-                    if unsigned {
-                        concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")
-                    }
-                }]
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                /// # fn main() { test().unwrap(); }
-                /// # fn test() -> Option<()> {
-                #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")]
-                #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")]
-                #[doc = concat!("let max = ", stringify!($Ty), "::new(",
-                                stringify!($Int), "::MAX)?;")]
-                ///
-                /// assert_eq!(twenty_seven, three.saturating_pow(3));
-                /// assert_eq!(max, max.saturating_pow(3));
-                /// # Some(())
-                /// # }
-                /// ```
-                #[stable(feature = "nonzero_checked_ops", since = "1.64.0")]
-                #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")]
-                #[must_use = "this returns the result of the operation, \
-                              without modifying the original"]
-                #[inline]
-                pub const fn saturating_pow(self, other: u32) -> $Ty {
-                    // SAFETY:
-                    // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow,
-                    //   all of which are non-zero
-                    // - `self` is non-zero
-                    // - the only way to get zero from an exponentiation without overflow is
-                    //   for base to be zero
-                    //
-                    // So the result cannot be zero.
-                    unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) }
-                }
+        /// Saturating negation. Computes `-self`,
+        #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")]
+        #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")]
+        /// instead of overflowing.
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN + 1)?;")]
+        #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MAX)?;")]
+        ///
+        /// assert_eq!(pos_five.saturating_neg(), neg_five);
+        /// assert_eq!(min.saturating_neg(), max);
+        /// assert_eq!(max.saturating_neg(), min_plus_one);
+        /// # Some(())
+        /// # }
+        /// ```
+        #[inline]
+        #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        pub const fn saturating_neg(self) -> $Ty {
+            if let Some(result) = self.checked_neg() {
+                return result;
             }
-        )+
-    }
+            $Ty::MAX
+        }
+
+        /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
+        /// of the type.
+        ///
+        #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")]
+        /// for documentation on overflow behaviour.
+        ///
+        /// # Example
+        ///
+        /// ```
+        #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+        /// # fn main() { test().unwrap(); }
+        /// # fn test() -> Option<()> {
+        #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+        #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+        #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+                        stringify!($Int), "::MIN)?;")]
+        ///
+        /// assert_eq!(pos_five.wrapping_neg(), neg_five);
+        /// assert_eq!(min.wrapping_neg(), min);
+        /// # Some(())
+        /// # }
+        /// ```
+        #[inline]
+        #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+        pub const fn wrapping_neg(self) -> $Ty {
+            let result = self.get().wrapping_neg();
+            // SAFETY: negation of nonzero cannot yield zero values.
+            unsafe { $Ty::new_unchecked(result) }
+        }
+    };
 }
 
 // Use this when the generated code should differ between signed and unsigned types.
@@ -1275,187 +1334,74 @@ macro_rules! sign_dependent_expr {
     };
 }
 
-nonzero_unsigned_signed_operations! {
-    unsigned NonZeroU8(u8);
-    unsigned NonZeroU16(u16);
-    unsigned NonZeroU32(u32);
-    unsigned NonZeroU64(u64);
-    unsigned NonZeroU128(u128);
-    unsigned NonZeroUsize(usize);
-    signed NonZeroI8(i8);
-    signed NonZeroI16(i16);
-    signed NonZeroI32(i32);
-    signed NonZeroI64(i64);
-    signed NonZeroI128(i128);
-    signed NonZeroIsize(isize);
+nonzero_integer! {
+    Self = NonZeroU8,
+    Primitive = unsigned u8,
 }
 
-macro_rules! nonzero_unsigned_is_power_of_two {
-    ( $( $Ty: ident )+ ) => {
-        $(
-            impl $Ty {
-
-                /// Returns `true` if and only if `self == (1 << k)` for some `k`.
-                ///
-                /// On many architectures, this function can perform better than `is_power_of_two()`
-                /// on the underlying integer type, as special handling of zero can be avoided.
-                ///
-                /// # Examples
-                ///
-                /// Basic usage:
-                ///
-                /// ```
-                #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")]
-                /// assert!(eight.is_power_of_two());
-                #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")]
-                /// assert!(!ten.is_power_of_two());
-                /// ```
-                #[must_use]
-                #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")]
-                #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")]
-                #[inline]
-                pub const fn is_power_of_two(self) -> bool {
-                    // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here.
-                    // On the basic x86-64 target, this saves 3 instructions for the zero check.
-                    // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction
-                    // compared to the `POPCNT` implementation on the underlying integer type.
+nonzero_integer! {
+    Self = NonZeroU16,
+    Primitive = unsigned u16,
+}
 
-                    intrinsics::ctpop(self.get()) < 2
-                }
+nonzero_integer! {
+    Self = NonZeroU32,
+    Primitive = unsigned u32,
+}
 
-            }
-        )+
-    }
+nonzero_integer! {
+    Self = NonZeroU64,
+    Primitive = unsigned u64,
 }
 
-nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize }
+nonzero_integer! {
+    Self = NonZeroU128,
+    Primitive = unsigned u128,
+}
 
-macro_rules! nonzero_min_max_unsigned {
-    ( $( $Ty: ident($Int: ident); )+ ) => {
-        $(
-            impl $Ty {
-                /// The smallest value that can be represented by this non-zero
-                /// integer type, 1.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")]
-                /// ```
-                #[stable(feature = "nonzero_min_max", since = "1.70.0")]
-                pub const MIN: Self = Self::new(1).unwrap();
-
-                /// The largest value that can be represented by this non-zero
-                /// integer type,
-                #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")]
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")]
-                /// ```
-                #[stable(feature = "nonzero_min_max", since = "1.70.0")]
-                pub const MAX: Self = Self::new(<$Int>::MAX).unwrap();
-            }
-        )+
-    }
+nonzero_integer! {
+    Self = NonZeroUsize,
+    Primitive = unsigned usize,
 }
 
-macro_rules! nonzero_min_max_signed {
-    ( $( $Ty: ident($Int: ident); )+ ) => {
-        $(
-            impl $Ty {
-                /// The smallest value that can be represented by this non-zero
-                /// integer type,
-                #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")]
-                ///
-                /// Note: While most integer types are defined for every whole
-                /// number between `MIN` and `MAX`, signed non-zero integers are
-                /// a special case. They have a "gap" at 0.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")]
-                /// ```
-                #[stable(feature = "nonzero_min_max", since = "1.70.0")]
-                pub const MIN: Self = Self::new(<$Int>::MIN).unwrap();
-
-                /// The largest value that can be represented by this non-zero
-                /// integer type,
-                #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")]
-                ///
-                /// Note: While most integer types are defined for every whole
-                /// number between `MIN` and `MAX`, signed non-zero integers are
-                /// a special case. They have a "gap" at 0.
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")]
-                /// ```
-                #[stable(feature = "nonzero_min_max", since = "1.70.0")]
-                pub const MAX: Self = Self::new(<$Int>::MAX).unwrap();
-            }
-        )+
-    }
+nonzero_integer! {
+    Self = NonZeroI8,
+    Primitive = signed i8,
+    UnsignedNonZero = NonZeroU8,
+    UnsignedPrimitive = u8,
 }
 
-nonzero_min_max_unsigned! {
-    NonZeroU8(u8);
-    NonZeroU16(u16);
-    NonZeroU32(u32);
-    NonZeroU64(u64);
-    NonZeroU128(u128);
-    NonZeroUsize(usize);
+nonzero_integer! {
+    Self = NonZeroI16,
+    Primitive = signed i16,
+    UnsignedNonZero = NonZeroU16,
+    UnsignedPrimitive = u16,
 }
 
-nonzero_min_max_signed! {
-    NonZeroI8(i8);
-    NonZeroI16(i16);
-    NonZeroI32(i32);
-    NonZeroI64(i64);
-    NonZeroI128(i128);
-    NonZeroIsize(isize);
+nonzero_integer! {
+    Self = NonZeroI32,
+    Primitive = signed i32,
+    UnsignedNonZero = NonZeroU32,
+    UnsignedPrimitive = u32,
 }
 
-macro_rules! nonzero_bits {
-    ( $( $Ty: ident($Int: ty); )+ ) => {
-        $(
-            impl $Ty {
-                /// The size of this non-zero integer type in bits.
-                ///
-                #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")]
-                ///
-                /// # Examples
-                ///
-                /// ```
-                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
-                ///
-                #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")]
-                /// ```
-                #[stable(feature = "nonzero_bits", since = "1.67.0")]
-                pub const BITS: u32 = <$Int>::BITS;
-            }
-        )+
-    }
+nonzero_integer! {
+    Self = NonZeroI64,
+    Primitive = signed i64,
+    UnsignedNonZero = NonZeroU64,
+    UnsignedPrimitive = u64,
+}
+
+nonzero_integer! {
+    Self = NonZeroI128,
+    Primitive = signed i128,
+    UnsignedNonZero = NonZeroU128,
+    UnsignedPrimitive = u128,
 }
 
-nonzero_bits! {
-    NonZeroU8(u8);
-    NonZeroI8(i8);
-    NonZeroU16(u16);
-    NonZeroI16(i16);
-    NonZeroU32(u32);
-    NonZeroI32(i32);
-    NonZeroU64(u64);
-    NonZeroI64(i64);
-    NonZeroU128(u128);
-    NonZeroI128(i128);
-    NonZeroUsize(usize);
-    NonZeroIsize(isize);
+nonzero_integer! {
+    Self = NonZeroIsize,
+    Primitive = signed isize,
+    UnsignedNonZero = NonZeroUsize,
+    UnsignedPrimitive = usize,
 }
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 267d9b44ad7..7dee30585e9 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1634,9 +1634,8 @@ mod prim_ref {}
 /// function pointers of varying length. Note that this is a convenience notation to avoid
 /// repetitive documentation, not valid Rust syntax.
 ///
-/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
-/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
-/// may change:
+/// The following traits are implemented for function pointers with any number of arguments and
+/// any ABI.
 ///
 /// * [`PartialEq`]
 /// * [`Eq`]
@@ -1645,11 +1644,6 @@ mod prim_ref {}
 /// * [`Hash`]
 /// * [`Pointer`]
 /// * [`Debug`]
-///
-/// The following traits are implemented for function pointers with any number of arguments and
-/// any ABI. These traits have implementations that are automatically generated by the compiler,
-/// so are not limited by missing language features:
-///
 /// * [`Clone`]
 /// * [`Copy`]
 /// * [`Send`]
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 5f1f41e6865..ad8c70c6a3c 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -138,7 +138,7 @@
 //!
 //! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting
 //! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only
-//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since
+//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since
 //! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault
 //! on read-only memory.
 //!
@@ -181,12 +181,13 @@
 //!     let spinlock = Arc::new(AtomicUsize::new(1));
 //!
 //!     let spinlock_clone = Arc::clone(&spinlock);
+//!
 //!     let thread = thread::spawn(move|| {
-//!         spinlock_clone.store(0, Ordering::SeqCst);
+//!         spinlock_clone.store(0, Ordering::Release);
 //!     });
 //!
 //!     // Wait for the other thread to release the lock
-//!     while spinlock.load(Ordering::SeqCst) != 0 {
+//!     while spinlock.load(Ordering::Acquire) != 0 {
 //!         hint::spin_loop();
 //!     }
 //!
@@ -203,7 +204,11 @@
 //!
 //! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0);
 //!
-//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
+//! // Note that Relaxed ordering doesn't synchronize anything
+//! // except the global thread counter itself.
+//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::Relaxed);
+//! // Note that this number may not be true at the moment of printing
+//! // because some other thread may have changed static value already.
 //! println!("live threads: {}", old_thread_count + 1);
 //! ```
 
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 9638f491987..835e35eac34 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -93,7 +93,7 @@ use crate::env;
 use crate::ffi::c_void;
 use crate::fmt;
 use crate::panic::UnwindSafe;
-use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+use crate::sync::atomic::{AtomicU8, Ordering::Relaxed};
 use crate::sync::LazyLock;
 use crate::sys_common::backtrace::{lock, output_filename, set_image_base};
 
@@ -254,7 +254,7 @@ impl Backtrace {
         // Cache the result of reading the environment variables to make
         // backtrace captures speedy, because otherwise reading environment
         // variables every time can be somewhat slow.
-        static ENABLED: AtomicUsize = AtomicUsize::new(0);
+        static ENABLED: AtomicU8 = AtomicU8::new(0);
         match ENABLED.load(Relaxed) {
             0 => {}
             1 => return false,
@@ -267,7 +267,7 @@ impl Backtrace {
                 Err(_) => false,
             },
         };
-        ENABLED.store(enabled as usize + 1, Relaxed);
+        ENABLED.store(enabled as u8 + 1, Relaxed);
         enabled
     }
 
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 34d48559c37..42c751bb6be 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -15,6 +15,15 @@ fn main() {
         eprintln!("warning: `tidy` is not installed; diffs will not be generated");
     }
 
+    if !config.profiler_support && config.mode == Mode::CoverageRun {
+        let actioned = if config.bless { "blessed" } else { "checked" };
+        eprintln!(
+            r#"
+WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned}
+help: try setting `profiler = true` in the `[build]` section of `config.toml`"#
+        );
+    }
+
     log_config(&config);
     run_tests(config);
 }
diff --git a/src/tools/miri/tests/fail/issue-miri-1112.rs b/src/tools/miri/tests/fail/issue-miri-1112.rs
index 9542673b0d9..387253a3f98 100644
--- a/src/tools/miri/tests/fail/issue-miri-1112.rs
+++ b/src/tools/miri/tests/fail/issue-miri-1112.rs
@@ -1,7 +1,7 @@
 trait Empty {}
 
 #[repr(transparent)]
-pub struct FunnyPointer(#[allow(dead_code)] dyn Empty);
+pub struct FunnyPointer(dyn Empty);
 
 #[repr(C)]
 pub struct Meta {
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
index 2283231eb01..d71d5954a40 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
@@ -1,7 +1,7 @@
 //@compile-flags: -Cdebug-assertions=no
 
 #[repr(transparent)]
-struct HasDrop(#[allow(dead_code)] u8);
+struct HasDrop(u8);
 
 impl Drop for HasDrop {
     fn drop(&mut self) {}
diff --git a/tests/ui/consts/transmute-const.rs b/tests/ui/consts/transmute-const.rs
index 65e5700d083..5044d99ec51 100644
--- a/tests/ui/consts/transmute-const.rs
+++ b/tests/ui/consts/transmute-const.rs
@@ -3,7 +3,7 @@
 use std::mem;
 
 #[repr(transparent)]
-struct Foo(#[allow(dead_code)] u32);
+struct Foo(u32);
 
 const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
 
diff --git a/tests/ui/layout/unsafe-cell-hides-niche.rs b/tests/ui/layout/unsafe-cell-hides-niche.rs
index 8d6cea10933..e87c402f8f9 100644
--- a/tests/ui/layout/unsafe-cell-hides-niche.rs
+++ b/tests/ui/layout/unsafe-cell-hides-niche.rs
@@ -17,7 +17,7 @@ use std::sync::{Mutex, RwLock};
 struct Wrapper<T>(#[allow(dead_code)] T);
 
 #[repr(transparent)]
-struct Transparent<T>(#[allow(dead_code)] T);
+struct Transparent<T>(T);
 
 struct NoNiche<T>(UnsafeCell<T>);
 
diff --git a/tests/ui/lint/dead-code/type-in-transparent.rs b/tests/ui/lint/dead-code/type-in-transparent.rs
new file mode 100644
index 00000000000..5dd6f93fd03
--- /dev/null
+++ b/tests/ui/lint/dead-code/type-in-transparent.rs
@@ -0,0 +1,14 @@
+// Verify that we do not warn on fields that are part of transparent types.
+// check-pass
+#![deny(dead_code)]
+
+#[repr(transparent)]
+struct NamedStruct { field: u8 }
+
+#[repr(transparent)]
+struct TupleStruct(u8);
+
+fn main() {
+    let _ = NamedStruct { field: 1 };
+    let _ = TupleStruct(1);
+}
diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs
index 6c2907c86e9..ddfc86f74d3 100644
--- a/tests/ui/packed/packed-struct-drop-aligned.rs
+++ b/tests/ui/packed/packed-struct-drop-aligned.rs
@@ -24,7 +24,7 @@ impl<'a> Drop for Aligned<'a> {
 }
 
 #[repr(transparent)]
-struct NotCopy(#[allow(dead_code)] u8);
+struct NotCopy(u8);
 
 #[repr(packed)]
 struct Packed<'a>(NotCopy, Aligned<'a>);
diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs
index 7b927c89ba0..a42e8c41c2e 100644
--- a/tests/ui/parser/bad-let-else-statement.rs
+++ b/tests/ui/parser/bad-let-else-statement.rs
@@ -161,4 +161,29 @@ fn q() {
     };
 }
 
+fn r() {
+    let ok = format_args!("") else { return; };
+
+    let bad = format_args! {""} else { return; };
+    //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+}
+
+fn s() {
+    macro_rules! a {
+        () => { {} }
+    }
+
+    macro_rules! b {
+        (1) => {
+            let x = a!() else { return; };
+        };
+        (2) => {
+            let x = a! {} else { return; };
+            //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        };
+    }
+
+    b!(1); b!(2);
+}
+
 fn main() {}
diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr
index 7cbda25e417..887455913d8 100644
--- a/tests/ui/parser/bad-let-else-statement.stderr
+++ b/tests/ui/parser/bad-let-else-statement.stderr
@@ -228,5 +228,31 @@ LL |         x
 LL ~     }) else {
    |
 
-error: aborting due to 17 previous errors
+error: right curly brace `}` before `else` in a `let...else` statement not allowed
+  --> $DIR/bad-let-else-statement.rs:167:31
+   |
+LL |     let bad = format_args! {""} else { return; };
+   |                               ^
+   |
+help: use parentheses instead of braces for this macro
+   |
+LL |     let bad = format_args! ("") else { return; };
+   |                            ~  ~
+
+error: right curly brace `}` before `else` in a `let...else` statement not allowed
+  --> $DIR/bad-let-else-statement.rs:181:25
+   |
+LL |             let x = a! {} else { return; };
+   |                         ^
+...
+LL |     b!(1); b!(2);
+   |            ----- in this macro invocation
+   |
+   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use parentheses instead of braces for this macro
+   |
+LL |             let x = a! () else { return; };
+   |                        ~~
+
+error: aborting due to 19 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index bd14640e280..b3f3051e177 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -644,7 +644,6 @@ compiler-team = [
 ]
 compiler-team-contributors = [
     "@TaKO8Ki",
-    "@WaffleLapkin",
     "@b-naber",
 ]
 compiler = [