From 1491c6f3117749cbefd6d0dc9c425a64ecff4f8d Mon Sep 17 00:00:00 2001
From: Peter Kehl <peter.kehl@gmail.com>
Date: Sat, 25 Mar 2023 06:19:52 -0700
Subject: [PATCH 1/7] Rustdoc Book refer to rustdoc::missing_doc_code_examples.
 Fixes #109592.

---
 src/doc/rustdoc/src/write-documentation/what-to-include.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustdoc/src/write-documentation/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md
index e1e09aa4a8a..cf1e6a8d3ca 100644
--- a/src/doc/rustdoc/src/write-documentation/what-to-include.md
+++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md
@@ -39,7 +39,7 @@ warning: 1 warning emitted
 As a library author, adding the lint `#![deny(missing_docs)]` is a great way to
 ensure the project does not drift away from being documented well, and
 `#![warn(missing_docs)]` is a good way to move towards comprehensive
-documentation.  In addition to docs, `#![deny(missing_doc_code_examples)]`
+documentation.  In addition to docs, `#![deny(rustdoc::missing_doc_code_examples)]`
 ensures each function contains a usage example.  In our example above, the
 warning is resolved by adding crate level documentation.
 

From 16bb7196a8d354feebcee986a73dd465d1caa6d8 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Sat, 25 Mar 2023 15:28:18 +0100
Subject: [PATCH 2/7] Improve "Auto-hide trait implementation documentation"
 GUI test

---
 .../auto-hide-trait-implementations.goml      | 13 -----
 ...tting-auto-hide-trait-implementations.goml | 47 +++++++++++++++++++
 2 files changed, 47 insertions(+), 13 deletions(-)
 delete mode 100644 tests/rustdoc-gui/auto-hide-trait-implementations.goml
 create mode 100644 tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml

diff --git a/tests/rustdoc-gui/auto-hide-trait-implementations.goml b/tests/rustdoc-gui/auto-hide-trait-implementations.goml
deleted file mode 100644
index 0a619c3524a..00000000000
--- a/tests/rustdoc-gui/auto-hide-trait-implementations.goml
+++ /dev/null
@@ -1,13 +0,0 @@
-// Checks that the setting "auto hide trait implementations" is working as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-
-// By default, the trait implementations are not collapsed.
-assert-attribute: ("#trait-implementations-list > details", {"open": ""}, ALL)
-
-// We now set the setting to auto hide all trait implementations.
-local-storage: {"rustdoc-auto-hide-trait-implementations": "true" }
-// We reload to ensure the trait implementations are collapsed as expected.
-reload:
-
-// We now check that all matching elements don't have the open attributes.
-assert-attribute-false: ("#trait-implementations-list > details", {"open": ""}, ALL)
diff --git a/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml b/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml
new file mode 100644
index 00000000000..7355dddd39d
--- /dev/null
+++ b/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml
@@ -0,0 +1,47 @@
+// Checks that the setting "auto hide trait implementations" is working as expected.
+
+define-function: (
+    "check-setting",
+    (storage_value, setting_attribute_value, toggle_attribute_value),
+    block {
+        assert-local-storage: {"rustdoc-auto-hide-trait-implementations": |storage_value|}
+        click: "#settings-menu"
+        wait-for: "#settings"
+        assert-property: ("#auto-hide-trait-implementations", {"checked": |setting_attribute_value|})
+        assert-attribute: ("#trait-implementations-list > details", {"open": |toggle_attribute_value|}, ALL)
+    }
+)
+
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+
+// By default, the trait implementations are not collapsed.
+call-function: ("check-setting", {
+    "storage_value": null,
+    "setting_attribute_value": "false",
+    "toggle_attribute_value": "",
+})
+
+// Now we change its value.
+click: "#auto-hide-trait-implementations"
+assert-local-storage: {"rustdoc-auto-hide-trait-implementations": "true"}
+
+// We check that the changes were applied as expected.
+reload:
+
+call-function: ("check-setting", {
+    "storage_value": "true",
+    "setting_attribute_value": "true",
+    "toggle_attribute_value": null,
+})
+
+// And now we re-disable the setting.
+click: "#auto-hide-trait-implementations"
+assert-local-storage: {"rustdoc-auto-hide-trait-implementations": "false"}
+
+// And we check everything is back the way it was before.
+reload:
+call-function: ("check-setting", {
+    "storage_value": "false",
+    "setting_attribute_value": "false",
+    "toggle_attribute_value": "",
+})

From 20679b11662908315bc2600b5103f60103a4b0ae Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sat, 25 Mar 2023 23:34:49 +0000
Subject: [PATCH 3/7] Still-further-specializable projections are ambiguous

---
 .../src/solve/project_goals.rs                |  2 +-
 .../specialization-unconstrained.rs           | 22 ++++++++++++++++
 .../specialization-unconstrained.stderr       | 25 +++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletion(-)
 create mode 100644 tests/ui/traits/new-solver/specialization-unconstrained.rs
 create mode 100644 tests/ui/traits/new-solver/specialization-unconstrained.stderr

diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 525b3105538..14c5b83c6ca 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -174,7 +174,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 goal.predicate.def_id(),
                 impl_def_id
             )? else {
-                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
             };
 
             if !assoc_def.item.defaultness(tcx).has_value() {
diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.rs b/tests/ui/traits/new-solver/specialization-unconstrained.rs
new file mode 100644
index 00000000000..02150689ee5
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-unconstrained.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Ztrait-solver=next
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+// Do not treat the RHS of a projection-goal as an unconstrained `Certainty::Yes` response
+// if the impl is still further specializable.
+
+trait Default {
+   type Id;
+}
+
+impl<T> Default for T {
+   default type Id = T;
+}
+
+fn test<T: Default<Id = U>, U>() {}
+
+fn main() {
+    test::<u32, ()>();
+    //~^ ERROR cannot satisfy `<u32 as Default>::Id == ()`
+}
diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr
new file mode 100644
index 00000000000..910925cbaeb
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-unconstrained.stderr
@@ -0,0 +1,25 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-unconstrained.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id == ()`
+  --> $DIR/specialization-unconstrained.rs:20:5
+   |
+LL |     test::<u32, ()>();
+   |     ^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id == ()`
+   |
+note: required by a bound in `test`
+  --> $DIR/specialization-unconstrained.rs:17:20
+   |
+LL | fn test<T: Default<Id = U>, U>() {}
+   |                    ^^^^^^ required by this bound in `test`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0284`.

From 323551abb1e4a34a9e9e81ebcc49e5224af8a5cb Mon Sep 17 00:00:00 2001
From: Evie M <14899090+eievui5@users.noreply.github.com>
Date: Sat, 25 Mar 2023 19:57:46 -0400
Subject: [PATCH 4/7] Correct typo (`back_box` -> `black_box`)

---
 library/core/src/hint.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index ee13dae60b1..a205565773a 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -228,7 +228,7 @@ pub fn spin_loop() {
 /// This _immediately_ precludes any direct use of this function for cryptographic or security
 /// purposes.
 ///
-/// While not suitable in those mission-critical cases, `back_box`'s functionality can generally be
+/// While not suitable in those mission-critical cases, `black_box`'s functionality can generally be
 /// relied upon for benchmarking, and should be used there. It will try to ensure that the
 /// compiler doesn't optimize away part of the intended test code based on context. For
 /// example:

From 3310f72db9205d23f7900d85055c5cd0eec17814 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 26 Mar 2023 00:02:24 +0000
Subject: [PATCH 5/7] transmute test

---
 compiler/rustc_middle/src/ty/mod.rs           |  4 +--
 .../new-solver/specialization-transmute.rs    | 30 ++++++++++++++++++
 .../specialization-transmute.stderr           | 31 +++++++++++++++++++
 3 files changed, 63 insertions(+), 2 deletions(-)
 create mode 100644 tests/ui/traits/new-solver/specialization-transmute.rs
 create mode 100644 tests/ui/traits/new-solver/specialization-transmute.stderr

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index e3cd5cca785..c6a56df5a5e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -653,8 +653,8 @@ pub enum AliasRelationDirection {
 impl std::fmt::Display for AliasRelationDirection {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
-            AliasRelationDirection::Equate => write!(f, " == "),
-            AliasRelationDirection::Subtype => write!(f, " <: "),
+            AliasRelationDirection::Equate => write!(f, "=="),
+            AliasRelationDirection::Subtype => write!(f, "<:"),
         }
     }
 }
diff --git a/tests/ui/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs
new file mode 100644
index 00000000000..a54701df4ef
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-transmute.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Ztrait-solver=next
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Default {
+   type Id;
+
+   fn intu(&self) -> &Self::Id;
+}
+
+impl<T> Default for T {
+   default type Id = T;
+
+   fn intu(&self) -> &Self::Id {
+        self
+        //~^ ERROR cannot satisfy `T <: <T as Default>::Id`
+   }
+}
+
+fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
+    *t.intu()
+}
+
+use std::num::NonZeroU8;
+fn main() {
+    let s = transmute::<u8, Option<NonZeroU8>>(0);
+    //~^ ERROR cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>
+    assert_eq!(s, None);
+}
diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr
new file mode 100644
index 00000000000..e67c56afc0d
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-transmute.stderr
@@ -0,0 +1,31 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-transmute.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0284]: type annotations needed: cannot satisfy `T <: <T as Default>::Id`
+  --> $DIR/specialization-transmute.rs:16:9
+   |
+LL |         self
+   |         ^^^^ cannot satisfy `T <: <T as Default>::Id`
+
+error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>`
+  --> $DIR/specialization-transmute.rs:27:13
+   |
+LL |     let s = transmute::<u8, Option<NonZeroU8>>(0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>`
+   |
+note: required by a bound in `transmute`
+  --> $DIR/specialization-transmute.rs:21:25
+   |
+LL | fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
+   |                         ^^^^^^ required by this bound in `transmute`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0284`.

From 0439d131768081174fe4ed53a6f09d41a9e5629f Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Sat, 25 Mar 2023 18:43:03 -0700
Subject: [PATCH 6/7] Refactor: `VariantIdx::from_u32(0)` -> `FIRST_VARIANT`

Since structs are always `VariantIdx(0)`, there's a bunch of files where the only reason they had `VariantIdx` or `vec::Idx` imported at all was to get the first variant.

So this uses a constant for that, and adds some doc-comments to `VariantIdx` while I'm there, since it doesn't have any today.
---
 compiler/rustc_abi/src/layout.rs               | 18 +++++++++---------
 compiler/rustc_abi/src/lib.rs                  | 17 +++++++++++++++--
 compiler/rustc_borrowck/src/type_check/mod.rs  |  6 +++---
 compiler/rustc_codegen_cranelift/src/base.rs   |  2 +-
 compiler/rustc_codegen_cranelift/src/lib.rs    |  2 +-
 compiler/rustc_codegen_cranelift/src/unsize.rs |  2 +-
 compiler/rustc_codegen_ssa/src/base.rs         |  5 ++---
 compiler/rustc_codegen_ssa/src/mir/rvalue.rs   |  4 ++--
 .../src/const_eval/valtrees.rs                 |  4 ++--
 .../rustc_const_eval/src/interpret/place.rs    |  4 ++--
 .../rustc_const_eval/src/transform/validate.rs |  4 ++--
 .../rustc_hir_typeck/src/expr_use_visitor.rs   |  5 ++---
 .../rustc_hir_typeck/src/mem_categorization.rs |  9 ++++-----
 compiler/rustc_hir_typeck/src/upvar.rs         |  5 ++---
 compiler/rustc_lint/src/builtin.rs             |  5 ++---
 compiler/rustc_middle/src/ty/adt.rs            | 10 +++++-----
 compiler/rustc_middle/src/ty/sty.rs            |  5 ++---
 .../rustc_mir_build/src/build/expr/as_place.rs |  6 ++----
 compiler/rustc_mir_build/src/thir/cx/expr.rs   |  8 ++++----
 .../src/thir/pattern/deconstruct_pat.rs        |  4 ++--
 .../rustc_mir_dataflow/src/elaborate_drops.rs  |  6 +++---
 compiler/rustc_mir_transform/src/inline.rs     |  4 ++--
 compiler/rustc_mir_transform/src/shim.rs       |  9 +++------
 compiler/rustc_ty_utils/src/consts.rs          |  4 ++--
 compiler/rustc_ty_utils/src/layout.rs          | 10 +++++-----
 25 files changed, 80 insertions(+), 78 deletions(-)

diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 54858b52008..343f27326ad 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -43,7 +43,7 @@ pub trait LayoutCalculator {
             .max_by_key(|niche| niche.available(dl));
 
         LayoutS {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: FIRST_VARIANT },
             fields: FieldsShape::Arbitrary {
                 offsets: vec![Size::ZERO, b_offset],
                 memory_index: vec![0, 1],
@@ -264,7 +264,7 @@ pub trait LayoutCalculator {
             abi = Abi::Uninhabited;
         }
         Some(LayoutS {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: FIRST_VARIANT },
             fields: FieldsShape::Arbitrary { offsets, memory_index },
             abi,
             largest_niche,
@@ -277,7 +277,7 @@ pub trait LayoutCalculator {
         let dl = self.current_data_layout();
         let dl = dl.borrow();
         LayoutS {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: FIRST_VARIANT },
             fields: FieldsShape::Primitive,
             abi: Abi::Uninhabited,
             largest_niche: None,
@@ -331,7 +331,7 @@ pub trait LayoutCalculator {
             }
             // If it's a struct, still compute a layout so that we can still compute the
             // field offsets.
-            None => VariantIdx::new(0),
+            None => FIRST_VARIANT,
         };
 
         let is_struct = !is_enum ||
@@ -467,7 +467,7 @@ pub trait LayoutCalculator {
                 .max_by_key(|(_i, layout)| layout.size.bytes())
                 .map(|(i, _layout)| i)?;
 
-            let all_indices = (0..=variants.len() - 1).map(VariantIdx::new);
+            let all_indices = variants.indices();
             let needs_disc =
                 |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
             let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
@@ -896,8 +896,8 @@ pub trait LayoutCalculator {
         let optimize = !repr.inhibit_union_abi_opt();
         let mut size = Size::ZERO;
         let mut abi = Abi::Aggregate { sized: true };
-        let index = VariantIdx::new(0);
-        for field in &variants[index] {
+        let only_variant = &variants[FIRST_VARIANT];
+        for field in only_variant {
             assert!(field.0.is_sized());
             align = align.max(field.align());
 
@@ -930,8 +930,8 @@ pub trait LayoutCalculator {
         }
 
         Some(LayoutS {
-            variants: Variants::Single { index },
-            fields: FieldsShape::Union(NonZeroUsize::new(variants[index].len())?),
+            variants: Variants::Single { index: FIRST_VARIANT },
+            fields: FieldsShape::Union(NonZeroUsize::new(only_variant.len())?),
             abi,
             largest_niche: None,
             align,
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 39574ca558f..6740001c38b 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1380,8 +1380,21 @@ impl Niche {
 }
 
 rustc_index::newtype_index! {
+    /// The *source-order* index of a variant in a type.
+    ///
+    /// For enums, these are always `0..variant_count`, regardless of any
+    /// custom discriminants that may have been defined, and including any
+    /// variants that may end up uninhabited due to field types.  (Some of the
+    /// variants may not be present in a monomorphized ABI [`Variants`], but
+    /// those skipped variants are always counted when determining the *index*.)
+    ///
+    /// `struct`s, `tuples`, and `unions`s are considered to have a single variant
+    /// with variant index zero, aka [`FIRST_VARIANT`].
     #[derive(HashStable_Generic)]
-    pub struct VariantIdx {}
+    pub struct VariantIdx {
+        /// Equivalent to `VariantIdx(0)`.
+        const FIRST_VARIANT = 0;
+    }
 }
 
 #[derive(PartialEq, Eq, Hash, Clone)]
@@ -1422,7 +1435,7 @@ impl LayoutS {
         let size = scalar.size(cx);
         let align = scalar.align(cx);
         LayoutS {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: FIRST_VARIANT },
             fields: FieldsShape::Primitive,
             abi: Abi::Scalar(scalar),
             largest_niche,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index c2a426bea09..4b27d240985 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -14,7 +14,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::region_constraints::RegionConstraintData;
@@ -36,7 +36,7 @@ use rustc_middle::ty::{
 };
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::FIRST_VARIANT;
 use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -812,7 +812,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             },
             PlaceTy { ty, variant_index: None } => match *ty.kind() {
                 ty::Adt(adt_def, substs) if !adt_def.is_enum() => {
-                    (adt_def.variant(VariantIdx::new(0)), substs)
+                    (adt_def.variant(FIRST_VARIANT), substs)
                 }
                 ty::Closure(_, substs) => {
                     return match substs
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 2107ae147e9..1825fb8cb22 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -785,7 +785,7 @@ fn codegen_stmt<'tcx>(
                             let variant_dest = lval.downcast_variant(fx, variant_index);
                             (variant_index, variant_dest, active_field_index)
                         }
-                        _ => (VariantIdx::from_u32(0), lval, None),
+                        _ => (FIRST_VARIANT, lval, None),
                     };
                     if active_field_index.is_some() {
                         assert_eq!(operands.len(), 1);
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index bed79859f51..1bd03403f24 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -86,7 +86,7 @@ mod prelude {
         self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
         TypeFoldable, TypeVisitableExt, UintTy,
     };
-    pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx};
+    pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx, FIRST_VARIANT};
 
     pub(crate) use rustc_data_structures::fx::FxHashMap;
 
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index ecf187a0b0f..93eefd92342 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -146,7 +146,7 @@ pub(crate) fn coerce_unsized_into<'tcx>(
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
-            for i in 0..def_a.variant(VariantIdx::new(0)).fields.len() {
+            for i in 0..def_a.variant(FIRST_VARIANT).fields.len() {
                 let src_f = src.value_field(fx, mir::Field::new(i));
                 let dst_f = dst.place_field(fx, mir::Field::new(i));
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index c3c8649dbff..6c4ca8f7fb1 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -24,7 +24,6 @@ use rustc_data_structures::sync::ParallelIterator;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
-use rustc_index::vec::Idx;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::exported_symbols;
@@ -40,7 +39,7 @@ use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Symbol;
 use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
-use rustc_target::abi::{Align, VariantIdx};
+use rustc_target::abi::{Align, FIRST_VARIANT};
 
 use std::collections::BTreeSet;
 use std::time::{Duration, Instant};
@@ -307,7 +306,7 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
-            for i in 0..def_a.variant(VariantIdx::new(0)).fields.len() {
+            for i in 0..def_a.variant(FIRST_VARIANT).fields.len() {
                 let src_f = src.project_field(bx, i);
                 let dst_f = dst.project_field(bx, i);
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 14f57b63e97..4bc4fdab59e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -13,7 +13,7 @@ use rustc_middle::ty::cast::{CastTy, IntTy};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
 use rustc_span::source_map::{Span, DUMMY_SP};
-use rustc_target::abi::{self, VariantIdx};
+use rustc_target::abi::{self, FIRST_VARIANT};
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     #[instrument(level = "trace", skip(self, bx))]
@@ -118,7 +118,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         let variant_dest = dest.project_downcast(bx, variant_index);
                         (variant_index, variant_dest, active_field_index)
                     }
-                    _ => (VariantIdx::from_u32(0), dest, None),
+                    _ => (FIRST_VARIANT, dest, None),
                 };
                 if active_field_index.is_some() {
                     assert_eq!(operands.len(), 1);
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index a73f778d4db..8e4454d7cec 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -8,7 +8,7 @@ use crate::interpret::{
 use crate::interpret::{MPlaceTy, Value};
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
-use rustc_target::abi::{Align, VariantIdx};
+use rustc_target::abi::{Align, VariantIdx, FIRST_VARIANT};
 
 #[instrument(skip(ecx), level = "debug")]
 fn branches<'tcx>(
@@ -412,7 +412,7 @@ fn valtree_into_mplace<'tcx>(
 
                         let inner_ty = match ty.kind() {
                             ty::Adt(def, substs) => {
-                                def.variant(VariantIdx::from_u32(0)).fields[i].ty(tcx, substs)
+                                def.variant(FIRST_VARIANT).fields[i].ty(tcx, substs)
                             }
                             ty::Tuple(inner_tys) => inner_tys[i],
                             _ => bug!("unexpected unsized type {:?}", ty),
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index ff6db143ddf..a95bcaa3f99 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -8,7 +8,7 @@ use rustc_ast::Mutability;
 use rustc_middle::mir;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
-use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, VariantIdx};
+use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, FIRST_VARIANT};
 
 use super::{
     alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
@@ -796,7 +796,7 @@ where
                 let variant_dest = self.place_downcast(&dest, variant_index)?;
                 (variant_index, variant_dest, active_field_index)
             }
-            _ => (VariantIdx::from_u32(0), dest.clone(), None),
+            _ => (FIRST_VARIANT, dest.clone(), None),
         };
         if active_field_index.is_some() {
             assert_eq!(operands.len(), 1);
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 66fc1c07e20..2be385d551e 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt
 use rustc_mir_dataflow::impls::MaybeStorageLive;
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
-use rustc_target::abi::{Size, VariantIdx};
+use rustc_target::abi::{Size, FIRST_VARIANT};
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum EdgeKind {
@@ -359,7 +359,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         check_equal(self, location, *f_ty);
                     }
                     ty::Adt(adt_def, substs) => {
-                        let var = parent_ty.variant_index.unwrap_or(VariantIdx::from_u32(0));
+                        let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
                         let Some(field) = adt_def.variant(var).fields.get(f.as_usize()) else {
                             fail_out_of_bounds(self, location);
                             return;
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index c62c1553d6f..5ca4087cdd3 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -14,12 +14,11 @@ use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::PatKind;
-use rustc_index::vec::Idx;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{self, adjustment, AdtKind, Ty, TyCtxt};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::FIRST_VARIANT;
 use ty::BorrowKind::ImmBorrow;
 
 use crate::mem_categorization as mc;
@@ -549,7 +548,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                             &*with_expr,
                             with_place.clone(),
                             with_field.ty(self.tcx(), substs),
-                            ProjectionKind::Field(f_index as u32, VariantIdx::new(0)),
+                            ProjectionKind::Field(f_index as u32, FIRST_VARIANT),
                         );
                         self.delegate_consume(&field_place, field_place.hir_id);
                     }
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 95e5483abf3..19c4146de89 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -59,10 +59,9 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::PatKind;
-use rustc_index::vec::Idx;
 use rustc_infer::infer::InferCtxt;
 use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
 use rustc_trait_selection::infer::InferCtxtExt;
 
 pub(crate) trait HirNode {
@@ -331,7 +330,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
                     expr,
                     base,
                     expr_ty,
-                    ProjectionKind::Field(field_idx as u32, VariantIdx::new(0)),
+                    ProjectionKind::Field(field_idx as u32, FIRST_VARIANT),
                 ))
             }
 
@@ -561,7 +560,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
             | Res::SelfTyParam { .. }
             | Res::SelfTyAlias { .. } => {
                 // Structs and Unions have only have one variant.
-                Ok(VariantIdx::new(0))
+                Ok(FIRST_VARIANT)
             }
             _ => bug!("expected ADT path, found={:?}", res),
         }
@@ -675,7 +674,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
 
                 for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) {
                     let subpat_ty = self.pat_ty_adjusted(subpat)?;
-                    let projection_kind = ProjectionKind::Field(i as u32, VariantIdx::new(0));
+                    let projection_kind = ProjectionKind::Field(i as u32, FIRST_VARIANT);
                     let sub_place =
                         self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind);
                     self.cat_pattern_(sub_place, subpat, op)?;
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index eadc30a799b..8fe5a3cc789 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -49,8 +49,7 @@ use rustc_span::{BytePos, Pos, Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_index::vec::Idx;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::FIRST_VARIANT;
 
 use std::iter;
 
@@ -1406,7 +1405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ProjectionKind::Field(..)
                     ))
                 );
-                def.variants().get(VariantIdx::new(0)).unwrap().fields.iter().enumerate().any(
+                def.variants().get(FIRST_VARIANT).unwrap().fields.iter().enumerate().any(
                     |(i, field)| {
                         let paths_using_field = captured_by_move_projs
                             .iter()
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 64c3ef45137..c1b247e3d61 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -58,7 +58,6 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
 use rustc_hir::intravisit::FnKind as HirFnKind;
 use rustc_hir::{Body, FnDecl, ForeignItemKind, GenericParamKind, Node, PatKind, PredicateOrigin};
-use rustc_index::vec::Idx;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf};
 use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -69,7 +68,7 @@ use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, InnerSpan, Span};
-use rustc_target::abi::{Abi, VariantIdx};
+use rustc_target::abi::{Abi, FIRST_VARIANT};
 use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
 use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy};
 
@@ -2788,7 +2787,7 @@ impl ClashingExternDeclarations {
                         );
                         if is_transparent && !is_non_null {
                             debug_assert_eq!(def.variants().len(), 1);
-                            let v = &def.variant(VariantIdx::new(0));
+                            let v = &def.variant(FIRST_VARIANT);
                             // continue with `ty`'s non-ZST field,
                             // otherwise `ty` is a ZST and we can return
                             if let Some(field) = transparent_newtype_field(tcx, v) {
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index ec21030b302..50d7fb1813a 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -10,11 +10,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::DataTypeKind;
 use rustc_span::symbol::sym;
-use rustc_target::abi::{ReprOptions, VariantIdx};
+use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT};
 
 use std::cell::RefCell;
 use std::cmp::Ordering;
@@ -228,7 +228,7 @@ impl AdtDefData {
             AdtKind::Struct => AdtFlags::IS_STRUCT,
         };
 
-        if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor.is_some() {
+        if kind == AdtKind::Struct && variants[FIRST_VARIANT].ctor.is_some() {
             flags |= AdtFlags::HAS_CTOR;
         }
 
@@ -357,7 +357,7 @@ impl<'tcx> AdtDef<'tcx> {
     /// Asserts this is a struct or union and returns its unique variant.
     pub fn non_enum_variant(self) -> &'tcx VariantDef {
         assert!(self.is_struct() || self.is_union());
-        &self.variant(VariantIdx::new(0))
+        &self.variant(FIRST_VARIANT)
     }
 
     #[inline]
@@ -493,7 +493,7 @@ impl<'tcx> AdtDef<'tcx> {
 
     #[inline]
     pub fn variant_range(self) -> Range<VariantIdx> {
-        VariantIdx::new(0)..VariantIdx::new(self.variants().len())
+        FIRST_VARIANT..self.variants().next_index()
     }
 
     /// Computes the discriminant value used by a specific variant.
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 35a581d314c..d03cc324e51 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -22,7 +22,7 @@ use rustc_index::vec::Idx;
 use rustc_macros::HashStable;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
 use rustc_target::spec::abi::{self, Abi};
 use std::borrow::Cow;
 use std::cmp::Ordering;
@@ -517,8 +517,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
     #[inline]
     pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
         // FIXME requires optimized MIR
-        let num_variants = tcx.generator_layout(def_id).unwrap().variant_fields.len();
-        VariantIdx::new(0)..VariantIdx::new(num_variants)
+        FIRST_VARIANT..tcx.generator_layout(def_id).unwrap().variant_fields.next_index()
     }
 
     /// The discriminant for the given variant. Panics if the `variant_index` is
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 33200b80a57..e112bf9829b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -13,9 +13,7 @@ use rustc_middle::thir::*;
 use rustc_middle::ty::AdtDef;
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance};
 use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
-
-use rustc_index::vec::Idx;
+use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
 
 use std::assert_matches::assert_matches;
 use std::iter;
@@ -91,7 +89,7 @@ fn convert_to_hir_projections_and_truncate_for_capture(
         let hir_projection = match mir_projection {
             ProjectionElem::Deref => HirProjectionKind::Deref,
             ProjectionElem::Field(field, _) => {
-                let variant = variant.unwrap_or(VariantIdx::new(0));
+                let variant = variant.unwrap_or(FIRST_VARIANT);
                 HirProjectionKind::Field(field.index() as u32, variant)
             }
             ProjectionElem::Downcast(.., idx) => {
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 6fd9b9dbb57..04e9273fc46 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -20,7 +20,7 @@ use rustc_middle::ty::{
     self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType,
 };
 use rustc_span::{sym, Span};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::FIRST_VARIANT;
 
 impl<'tcx> Cx<'tcx> {
     pub(crate) fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId {
@@ -357,7 +357,7 @@ impl<'tcx> Cx<'tcx> {
                                 Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => {
                                     Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
                                 }
-                                Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
+                                Res::SelfCtor(..) => Some((adt_def, FIRST_VARIANT)),
                                 _ => None,
                             })
                         } else {
@@ -510,7 +510,7 @@ impl<'tcx> Cx<'tcx> {
                         debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
                         ExprKind::Adt(Box::new(AdtExpr {
                             adt_def: *adt,
-                            variant_index: VariantIdx::new(0),
+                            variant_index: FIRST_VARIANT,
                             substs,
                             user_ty,
                             fields: self.field_refs(fields),
@@ -732,7 +732,7 @@ impl<'tcx> Cx<'tcx> {
             }
             hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
                 lhs: self.mirror_expr(source),
-                variant_index: VariantIdx::new(0),
+                variant_index: FIRST_VARIANT,
                 name: Field::new(self.typeck_results.field_index(expr.hir_id)),
             },
             hir::ExprKind::Cast(ref source, ref cast_ty) => {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index e5b7d685c49..8a7b1fce51d 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -60,7 +60,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
 use rustc_middle::{middle::stability::EvalResult, mir::interpret::ConstValue};
 use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::{Integer, Size, VariantIdx};
+use rustc_target::abi::{Integer, Size, VariantIdx, FIRST_VARIANT};
 
 use self::Constructor::*;
 use self::SliceKind::*;
@@ -706,7 +706,7 @@ impl<'tcx> Constructor<'tcx> {
             Variant(idx) => idx,
             Single => {
                 assert!(!adt.is_enum());
-                VariantIdx::new(0)
+                FIRST_VARIANT
             }
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt),
         }
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 486275570bd..fe6728fc76e 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -7,7 +7,7 @@ use rustc_middle::traits::Reveal;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
 use std::{fmt, iter};
 
 /// The value of an inserted drop flag.
@@ -468,7 +468,7 @@ where
             let fields = self.move_paths_for_fields(
                 self.place,
                 self.path,
-                &adt.variant(VariantIdx::new(0)),
+                &adt.variant(FIRST_VARIANT),
                 substs,
             );
             self.drop_ladder(fields, succ, unwind)
@@ -894,7 +894,7 @@ where
         let unit_temp = Place::from(self.new_temp(tcx.mk_unit()));
         let free_func = tcx.require_lang_item(LangItem::BoxFree, Some(self.source_info.span));
         let args = adt
-            .variant(VariantIdx::new(0))
+            .variant(FIRST_VARIANT)
             .fields
             .iter()
             .enumerate()
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 9cba8870f23..7136e42189a 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
 use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::FIRST_VARIANT;
 use rustc_target::spec::abi::Abi;
 
 use crate::simplify::{remove_dead_blocks, CfgSimplifier};
@@ -911,7 +911,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                     check_equal(self, *f_ty);
                 }
                 ty::Adt(adt_def, substs) => {
-                    let var = parent_ty.variant_index.unwrap_or(VariantIdx::from_u32(0));
+                    let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
                     let Some(field) = adt_def.variant(var).fields.get(f.as_usize()) else {
                         self.validation = Err("malformed MIR");
                         return;
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index ebe63d6cb7e..970a0a8d4bf 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -5,7 +5,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
 
 use rustc_index::vec::{Idx, IndexVec};
 
@@ -816,11 +816,8 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
 
     let source_info = SourceInfo::outermost(span);
 
-    let variant_index = if adt_def.is_enum() {
-        adt_def.variant_index_with_ctor_id(ctor_id)
-    } else {
-        VariantIdx::new(0)
-    };
+    let variant_index =
+        if adt_def.is_enum() { adt_def.variant_index_with_ctor_id(ctor_id) } else { FIRST_VARIANT };
 
     // Generate the following MIR:
     //
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 4d0fd260de2..b67607a4db6 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::abstract_const::CastKind;
 use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt};
 use rustc_middle::{mir, thir};
 use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
 
 use std::iter;
 
@@ -44,7 +44,7 @@ pub(crate) fn destructure_const<'tcx>(
                 let (head, rest) = branches.split_first().unwrap();
                 (VariantIdx::from_u32(head.unwrap_leaf().try_to_u32().unwrap()), rest)
             } else {
-                (VariantIdx::from_u32(0), branches)
+                (FIRST_VARIANT, branches)
             };
             let fields = &def.variant(variant_idx).fields;
             let mut field_consts = Vec::with_capacity(fields.len());
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 1788f544a7f..380931742e3 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1,7 +1,7 @@
 use hir::def_id::DefId;
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal};
 use rustc_middle::ty::layout::{
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
@@ -227,7 +227,7 @@ fn layout_of_uncached<'tcx>(
             let largest_niche = if count != 0 { element.largest_niche } else { None };
 
             tcx.mk_layout(LayoutS {
-                variants: Variants::Single { index: VariantIdx::new(0) },
+                variants: Variants::Single { index: FIRST_VARIANT },
                 fields: FieldsShape::Array { stride: element.size, count },
                 abi,
                 largest_niche,
@@ -238,7 +238,7 @@ fn layout_of_uncached<'tcx>(
         ty::Slice(element) => {
             let element = cx.layout_of(element)?;
             tcx.mk_layout(LayoutS {
-                variants: Variants::Single { index: VariantIdx::new(0) },
+                variants: Variants::Single { index: FIRST_VARIANT },
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
                 abi: Abi::Aggregate { sized: false },
                 largest_niche: None,
@@ -247,7 +247,7 @@ fn layout_of_uncached<'tcx>(
             })
         }
         ty::Str => tcx.mk_layout(LayoutS {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: FIRST_VARIANT },
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
             abi: Abi::Aggregate { sized: false },
             largest_niche: None,
@@ -399,7 +399,7 @@ fn layout_of_uncached<'tcx>(
             };
 
             tcx.mk_layout(LayoutS {
-                variants: Variants::Single { index: VariantIdx::new(0) },
+                variants: Variants::Single { index: FIRST_VARIANT },
                 fields,
                 abi: Abi::Vector { element: e_abi, count: e_len },
                 largest_niche: e_ly.largest_niche,

From e0ec9c0b9c08677b967fb2f50978bcb4466152cd Mon Sep 17 00:00:00 2001
From: Ezra Shaw <ezrasure@outlook.com>
Date: Sat, 11 Mar 2023 21:22:42 +1300
Subject: [PATCH 7/7] rustdoc: tweak `some variants omitted`

Don't display `// some variants omitted` if enum is marked
`#[non_exhaustive]`
---
 src/librustdoc/html/render/print_item.rs |  2 +-
 tests/rustdoc/issue-108925.rs            | 11 +++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)
 create mode 100644 tests/rustdoc/issue-108925.rs

diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 579b5a9c723..674cd0d62d4 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1234,7 +1234,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                 w.write_str(",\n");
             }
 
-            if variants_stripped {
+            if variants_stripped && !it.is_non_exhaustive() {
                 w.write_str("    // some variants omitted\n");
             }
             if toggle {
diff --git a/tests/rustdoc/issue-108925.rs b/tests/rustdoc/issue-108925.rs
new file mode 100644
index 00000000000..88aeb3c7f75
--- /dev/null
+++ b/tests/rustdoc/issue-108925.rs
@@ -0,0 +1,11 @@
+// @has issue_108925/enum.MyThing.html
+// @has - '//code' 'Shown'
+// @!has - '//code' 'NotShown'
+// @!has - '//code' '// some variants omitted'
+#[non_exhaustive]
+pub enum MyThing {
+    Shown,
+    #[doc(hidden)]
+    NotShown,
+}
+