From d03380957bf92412d48daac92966ff5129358d59 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 17 Dec 2024 17:25:19 +0100
Subject: [PATCH 01/14] Fix intra doc links not generated inside footnote
 definitions

---
 src/librustdoc/html/markdown.rs | 66 +++++++++++++++++++++++++--------
 1 file changed, 50 insertions(+), 16 deletions(-)

diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 90c49270566..aa8fdaaee4c 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -344,35 +344,48 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
 }
 
 /// Make headings links with anchor IDs and build up TOC.
-struct LinkReplacer<'a, I: Iterator<Item = Event<'a>>> {
-    inner: I,
+struct LinkReplacerInner<'a> {
     links: &'a [RenderedLink],
     shortcut_link: Option<&'a RenderedLink>,
 }
 
+struct LinkReplacer<'a, I: Iterator<Item = Event<'a>>> {
+    iter: I,
+    inner: LinkReplacerInner<'a>,
+}
+
 impl<'a, I: Iterator<Item = Event<'a>>> LinkReplacer<'a, I> {
     fn new(iter: I, links: &'a [RenderedLink]) -> Self {
-        LinkReplacer { inner: iter, links, shortcut_link: None }
+        LinkReplacer { iter, inner: { LinkReplacerInner { links, shortcut_link: None } } }
     }
 }
 
-impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
-    type Item = Event<'a>;
+// FIXME: Once we have specialized trait impl (for `Iterator` impl on `LinkReplacer`),
+// we can remove this type and move back `LinkReplacerInner` fields into `LinkReplacer`.
+struct SpannedLinkReplacer<'a, I: Iterator<Item = SpannedEvent<'a>>> {
+    iter: I,
+    inner: LinkReplacerInner<'a>,
+}
 
-    fn next(&mut self) -> Option<Self::Item> {
-        let mut event = self.inner.next();
+impl<'a, I: Iterator<Item = SpannedEvent<'a>>> SpannedLinkReplacer<'a, I> {
+    fn new(iter: I, links: &'a [RenderedLink]) -> Self {
+        SpannedLinkReplacer { iter, inner: { LinkReplacerInner { links, shortcut_link: None } } }
+    }
+}
 
+impl<'a> LinkReplacerInner<'a> {
+    fn handle_event(&mut self, event: &mut Event<'a>) {
         // Replace intra-doc links and remove disambiguators from shortcut links (`[fn@f]`).
-        match &mut event {
+        match event {
             // This is a shortcut link that was resolved by the broken_link_callback: `[fn@f]`
             // Remove any disambiguator.
-            Some(Event::Start(Tag::Link {
+            Event::Start(Tag::Link {
                 // [fn@f] or [fn@f][]
                 link_type: LinkType::ShortcutUnknown | LinkType::CollapsedUnknown,
                 dest_url,
                 title,
                 ..
-            })) => {
+            }) => {
                 debug!("saw start of shortcut link to {dest_url} with title {title}");
                 // If this is a shortcut link, it was resolved by the broken_link_callback.
                 // So the URL will already be updated properly.
@@ -389,13 +402,13 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
                 }
             }
             // Now that we're done with the shortcut link, don't replace any more text.
-            Some(Event::End(TagEnd::Link)) if self.shortcut_link.is_some() => {
+            Event::End(TagEnd::Link) if self.shortcut_link.is_some() => {
                 debug!("saw end of shortcut link");
                 self.shortcut_link = None;
             }
             // Handle backticks in inline code blocks, but only if we're in the middle of a shortcut link.
             // [`fn@f`]
-            Some(Event::Code(text)) => {
+            Event::Code(text) => {
                 trace!("saw code {text}");
                 if let Some(link) = self.shortcut_link {
                     // NOTE: this only replaces if the code block is the *entire* text.
@@ -418,7 +431,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
             }
             // Replace plain text in links, but only in the middle of a shortcut link.
             // [fn@f]
-            Some(Event::Text(text)) => {
+            Event::Text(text) => {
                 trace!("saw text {text}");
                 if let Some(link) = self.shortcut_link {
                     // NOTE: same limitations as `Event::Code`
@@ -434,7 +447,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
             }
             // If this is a link, but not a shortcut link,
             // replace the URL, since the broken_link_callback was not called.
-            Some(Event::Start(Tag::Link { dest_url, title, .. })) => {
+            Event::Start(Tag::Link { dest_url, title, .. }) => {
                 if let Some(link) =
                     self.links.iter().find(|&link| *link.original_text == **dest_url)
                 {
@@ -447,12 +460,33 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
             // Anything else couldn't have been a valid Rust path, so no need to replace the text.
             _ => {}
         }
+    }
+}
 
+impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
+    type Item = Event<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let mut event = self.iter.next();
+        if let Some(ref mut event) = event {
+            self.inner.handle_event(event);
+        }
         // Yield the modified event
         event
     }
 }
 
+impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for SpannedLinkReplacer<'a, I> {
+    type Item = SpannedEvent<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let Some((mut event, range)) = self.iter.next() else { return None };
+        self.inner.handle_event(&mut event);
+        // Yield the modified event
+        Some((event, range))
+    }
+}
+
 /// Wrap HTML tables into `<div>` to prevent having the doc blocks width being too big.
 struct TableWrapper<'a, I: Iterator<Item = Event<'a>>> {
     inner: I,
@@ -1339,9 +1373,9 @@ impl<'a> Markdown<'a> {
 
         ids.handle_footnotes(|ids, existing_footnotes| {
             let p = HeadingLinks::new(p, None, ids, heading_offset);
+            let p = SpannedLinkReplacer::new(p, links);
             let p = footnotes::Footnotes::new(p, existing_footnotes);
-            let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
-            let p = TableWrapper::new(p);
+            let p = TableWrapper::new(p.map(|(ev, _)| ev));
             CodeBlocks::new(p, codes, edition, playground)
         })
     }

From a01de760bbcbbdf6935f0cd82107d48529c48138 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 17 Dec 2024 17:32:11 +0100
Subject: [PATCH 02/14] Add regression test for #132208

---
 .../intra-doc/link-in-footnotes-132208.rs     | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 tests/rustdoc/intra-doc/link-in-footnotes-132208.rs

diff --git a/tests/rustdoc/intra-doc/link-in-footnotes-132208.rs b/tests/rustdoc/intra-doc/link-in-footnotes-132208.rs
new file mode 100644
index 00000000000..c9b97eafd2f
--- /dev/null
+++ b/tests/rustdoc/intra-doc/link-in-footnotes-132208.rs
@@ -0,0 +1,24 @@
+// Rustdoc has multiple passes and if the footnote pass is run before the link replacer
+// one, intra doc links are not generated inside footnote definitions. This test
+// therefore ensures that intra-doc link are correctly generated inside footnote
+// definitions.
+//
+// Regression test for <https://github.com/rust-lang/rust/issues/132208>.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ has - '//*[@class="docblock"]//a[@href="struct.Bar.html"]' 'a'
+//@ has - '//*[@class="docblock"]//*[@class="footnotes"]//a[@href="struct.Foo.html"]' 'b'
+
+//! [a]: crate::Bar
+//! [b]: crate::Foo
+//!
+//! link in body: [a]
+//!
+//! see footnote[^1]
+//!
+//! [^1]: link in footnote: [b]
+
+pub struct Bar;
+pub struct Foo;

From 5980dfe063cea6135400046ce252a276ba8362bc Mon Sep 17 00:00:00 2001
From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com>
Date: Tue, 17 Dec 2024 18:15:33 +0100
Subject: [PATCH 03/14] ci: remove duplicate task definition

---
 .../host-x86_64/i686-gnu-nopt/Dockerfile      |  4 ++-
 src/ci/docker/host-x86_64/i686-gnu/Dockerfile |  4 ++-
 .../host-x86_64/x86_64-gnu-llvm-18/Dockerfile | 15 +++++----
 .../host-x86_64/x86_64-gnu-llvm-19/Dockerfile | 15 +++++----
 src/ci/docker/scripts/stage_2_test_set1.sh    |  9 +++++
 ...6_64-gnu-llvm1.sh => stage_2_test_set2.sh} |  2 +-
 src/ci/docker/scripts/x86_64-gnu-llvm.sh      |  2 --
 src/ci/docker/scripts/x86_64-gnu-llvm2.sh     |  6 +---
 src/ci/github-actions/jobs.yml                | 33 ++++---------------
 9 files changed, 41 insertions(+), 49 deletions(-)
 create mode 100755 src/ci/docker/scripts/stage_2_test_set1.sh
 rename src/ci/docker/scripts/{x86_64-gnu-llvm1.sh => stage_2_test_set2.sh} (67%)

diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
index e2736720607..241199d3baf 100644
--- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
@@ -28,4 +28,6 @@ RUN echo "optimize = false" >> /config/nopt-std-config.toml
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
 ARG SCRIPT_ARG
-ENV SCRIPT=${SCRIPT_ARG}
+COPY scripts/stage_2_test_set1.sh /scripts/
+COPY scripts/stage_2_test_set2.sh /scripts/
+ENV SCRIPT ${SCRIPT_ARG}
diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
index dec25461bb4..a715f7182d2 100644
--- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
@@ -25,4 +25,6 @@ RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
 ARG SCRIPT_ARG
-ENV SCRIPT=${SCRIPT_ARG}
+COPY scripts/stage_2_test_set1.sh /scripts/
+COPY scripts/stage_2_test_set2.sh /scripts/
+ENV SCRIPT /scripts/${SCRIPT_ARG}
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile
index 42df58517ca..e157debfd09 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile
@@ -60,9 +60,12 @@ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
 RUN /scripts/build-gccjit.sh /scripts
 
 ARG SCRIPT_ARG
-COPY scripts/add_dummy_commit.sh /tmp/add_dummy_commit.sh
-COPY scripts/x86_64-gnu-llvm.sh /tmp/x86_64-gnu-llvm.sh
-COPY scripts/x86_64-gnu-llvm1.sh /tmp/x86_64-gnu-llvm1.sh
-COPY scripts/x86_64-gnu-llvm2.sh /tmp/x86_64-gnu-llvm2.sh
-COPY scripts/x86_64-gnu-llvm3.sh /tmp/x86_64-gnu-llvm3.sh
-ENV SCRIPT /tmp/${SCRIPT_ARG}
+
+COPY scripts/add_dummy_commit.sh /tmp/
+COPY scripts/x86_64-gnu-llvm.sh /tmp/
+COPY scripts/x86_64-gnu-llvm2.sh /tmp/
+COPY scripts/x86_64-gnu-llvm3.sh /tmp/
+COPY scripts/stage_2_test_set1.sh /tmp/
+COPY scripts/stage_2_test_set2.sh /tmp/
+
+ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}"
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
index f2aadbe87cf..e7016e7d3c0 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
@@ -60,9 +60,12 @@ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
 RUN /scripts/build-gccjit.sh /scripts
 
 ARG SCRIPT_ARG
-COPY scripts/add_dummy_commit.sh /tmp/add_dummy_commit.sh
-COPY scripts/x86_64-gnu-llvm.sh /tmp/x86_64-gnu-llvm.sh
-COPY scripts/x86_64-gnu-llvm1.sh /tmp/x86_64-gnu-llvm1.sh
-COPY scripts/x86_64-gnu-llvm2.sh /tmp/x86_64-gnu-llvm2.sh
-COPY scripts/x86_64-gnu-llvm3.sh /tmp/x86_64-gnu-llvm3.sh
-ENV SCRIPT /tmp/${SCRIPT_ARG}
+
+COPY scripts/add_dummy_commit.sh /tmp/
+COPY scripts/x86_64-gnu-llvm.sh /tmp/
+COPY scripts/x86_64-gnu-llvm2.sh /tmp/
+COPY scripts/x86_64-gnu-llvm3.sh /tmp/
+COPY scripts/stage_2_test_set1.sh /tmp/
+COPY scripts/stage_2_test_set2.sh /tmp/
+
+ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}"
diff --git a/src/ci/docker/scripts/stage_2_test_set1.sh b/src/ci/docker/scripts/stage_2_test_set1.sh
new file mode 100755
index 00000000000..3baff4b5221
--- /dev/null
+++ b/src/ci/docker/scripts/stage_2_test_set1.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+set -ex
+
+# Run a subset of tests. Used to run tests in parallel in multiple jobs.
+
+../x.py --stage 2 test \
+  --skip compiler \
+  --skip src
diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm1.sh b/src/ci/docker/scripts/stage_2_test_set2.sh
similarity index 67%
rename from src/ci/docker/scripts/x86_64-gnu-llvm1.sh
rename to src/ci/docker/scripts/stage_2_test_set2.sh
index 56ef39aae15..872d758dce3 100755
--- a/src/ci/docker/scripts/x86_64-gnu-llvm1.sh
+++ b/src/ci/docker/scripts/stage_2_test_set2.sh
@@ -2,7 +2,7 @@
 
 set -ex
 
-/tmp/add_dummy_commit.sh
+# Run a subset of tests. Used to run tests in parallel in multiple jobs.
 
 ../x.py --stage 2 test \
   --skip tests \
diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
index e7dcc1ddff4..e0435a3ff5c 100755
--- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh
+++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
@@ -2,8 +2,6 @@
 
 set -ex
 
-/tmp/add_dummy_commit.sh
-
 # NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
 ../x.py --stage 2 test --skip src/tools/tidy
 
diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm2.sh b/src/ci/docker/scripts/x86_64-gnu-llvm2.sh
index c9f6b98f01f..fe5382aaa48 100755
--- a/src/ci/docker/scripts/x86_64-gnu-llvm2.sh
+++ b/src/ci/docker/scripts/x86_64-gnu-llvm2.sh
@@ -2,13 +2,9 @@
 
 set -ex
 
-/tmp/add_dummy_commit.sh
-
 ##### Test stage 2 #####
 
-../x.py --stage 2 test \
-  --skip compiler \
-  --skip src
+/tmp/stage_2_test_set1.sh
 
 # Run the `mir-opt` tests again but this time for a 32-bit target.
 # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index fe0fdde39d0..9819c26cba8 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -58,22 +58,6 @@ envs:
     NO_DEBUG_ASSERTIONS: 1
     NO_OVERFLOW_CHECKS: 1
 
-  # Different set of tests to run tests in parallel in multiple jobs.
-  stage_2_test_set1: &stage_2_test_set1
-    DOCKER_SCRIPT: >-
-      python3 ../x.py --stage 2 test
-      --skip compiler
-      --skip src
-
-  stage_2_test_set2: &stage_2_test_set2
-    DOCKER_SCRIPT: >-
-      python3 ../x.py --stage 2 test
-      --skip tests
-      --skip coverage-map
-      --skip coverage-run
-      --skip library
-      --skip tidyselftest
-
   production:
     &production
     DEPLOY_BUCKET: rust-lang-ci2
@@ -234,14 +218,14 @@ auto:
   - image: i686-gnu-1
     env:
       IMAGE: i686-gnu
-      <<: *stage_2_test_set1
+      DOCKER_SCRIPT: stage_2_test_set1.sh
     <<: *job-linux-4c
 
   # Skip tests that run in i686-gnu-1
   - image: i686-gnu-2
     env:
       IMAGE: i686-gnu
-      <<: *stage_2_test_set2
+      DOCKER_SCRIPT: stage_2_test_set2.sh
     <<: *job-linux-4c
 
   # The i686-gnu-nopt job is split into multiple jobs to run tests in parallel.
@@ -249,7 +233,7 @@ auto:
   - image: i686-gnu-nopt-1
     env:
       IMAGE: i686-gnu-nopt
-      <<: *stage_2_test_set1
+      DOCKER_SCRIPT: /scripts/stage_2_test_set1.sh
     <<: *job-linux-4c
 
   # Skip tests that run in i686-gnu-nopt-1
@@ -258,12 +242,7 @@ auto:
       IMAGE: i686-gnu-nopt
       DOCKER_SCRIPT: >-
         python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std &&
-        python3 ../x.py --stage 2 test
-        --skip tests
-        --skip coverage-map
-        --skip coverage-run
-        --skip library
-        --skip tidyselftest
+        /scripts/stage_2_test_set2.sh
     <<: *job-linux-4c
 
   - image: mingw-check
@@ -319,7 +298,7 @@ auto:
     env:
       RUST_BACKTRACE: 1
       IMAGE: x86_64-gnu-llvm-19
-      DOCKER_SCRIPT: x86_64-gnu-llvm1.sh
+      DOCKER_SCRIPT: stage_2_test_set1.sh
     <<: *job-linux-4c
 
   # Skip tests that run in x86_64-gnu-llvm-19-{1,3}
@@ -345,7 +324,7 @@ auto:
       RUST_BACKTRACE: 1
       READ_ONLY_SRC: "0"
       IMAGE: x86_64-gnu-llvm-18
-      DOCKER_SCRIPT: x86_64-gnu-llvm1.sh
+      DOCKER_SCRIPT: stage_2_test_set1.sh
     <<: *job-linux-4c
 
   # Skip tests that run in x86_64-gnu-llvm-18-{1,3}

From 21de42bf8ddd0f39c766c7705990152302ae1f3b Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 1 Dec 2024 13:12:43 +0100
Subject: [PATCH 04/14] Variants::Single: do not use invalid VariantIdx for
 uninhabited enums

---
 compiler/rustc_abi/src/layout.rs              |  14 +-
 compiler/rustc_abi/src/lib.rs                 |   8 +-
 .../src/discriminant.rs                       |   5 +-
 compiler/rustc_codegen_gcc/src/type_of.rs     |   6 +-
 .../src/debuginfo/metadata/enums/cpp_like.rs  |   4 +-
 compiler/rustc_codegen_llvm/src/type_of.rs    |   8 +-
 compiler/rustc_codegen_ssa/src/mir/place.rs   |   3 +-
 .../src/interpret/discriminant.rs             |  23 ++--
 .../src/interpret/validity.rs                 |   4 +-
 .../rustc_middle/src/mir/interpret/error.rs   |   2 +-
 compiler/rustc_middle/src/ty/layout.rs        |  13 +-
 .../rustc_mir_transform/src/jump_threading.rs |  31 +----
 .../src/unreachable_enum_branching.rs         |   6 +-
 .../rustc_smir/src/rustc_smir/convert/abi.rs  |   6 +-
 compiler/rustc_transmute/src/layout/tree.rs   |  10 +-
 compiler/rustc_ty_utils/src/layout.rs         |  14 +-
 .../rustc_ty_utils/src/layout/invariant.rs    | 124 ++++++++++--------
 compiler/stable_mir/src/abi.rs                |   1 +
 .../rust-analyzer/crates/hir-ty/src/layout.rs |   8 +-
 .../crates/hir-ty/src/mir/eval.rs             |   3 +-
 .../rust-analyzer/crates/hir-ty/src/utils.rs  |   2 +-
 .../set_no_discriminant.f.JumpThreading.diff  |   3 +-
 ...no_discriminant.generic.JumpThreading.diff |   3 +-
 tests/mir-opt/set_no_discriminant.rs          |  21 +--
 tests/ui/abi/c-zst.aarch64-darwin.stderr      |   8 +-
 tests/ui/abi/c-zst.powerpc-linux.stderr       |   8 +-
 tests/ui/abi/c-zst.s390x-linux.stderr         |   8 +-
 tests/ui/abi/c-zst.sparc64-linux.stderr       |   8 +-
 tests/ui/abi/c-zst.x86_64-linux.stderr        |   8 +-
 .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr |   8 +-
 tests/ui/abi/debug.stderr                     |  96 ++++++++++----
 tests/ui/abi/sysv64-zst.stderr                |   8 +-
 tests/ui/abi/win64-zst.x86_64-linux.stderr    |   8 +-
 .../abi/win64-zst.x86_64-windows-gnu.stderr   |   8 +-
 .../abi/win64-zst.x86_64-windows-msvc.stderr  |   8 +-
 tests/ui/layout/debug.stderr                  |  64 ++++++---
 tests/ui/layout/hexagon-enum.stderr           |  20 ++-
 ...-scalarpair-payload-might-be-uninit.stderr |  48 +++++--
 .../issue-96185-overaligned-enum.stderr       |  16 ++-
 tests/ui/layout/thumb-enum.stderr             |  20 ++-
 .../layout/zero-sized-array-enum-niche.stderr |  36 +++--
 ...-variants.aarch64-unknown-linux-gnu.stderr |  20 ++-
 ...-c-dead-variants.armebv7r-none-eabi.stderr |  20 ++-
 ...-dead-variants.i686-pc-windows-msvc.stderr |  20 ++-
 ...d-variants.x86_64-unknown-linux-gnu.stderr |  20 ++-
 tests/ui/repr/repr-c-int-dead-variants.stderr |  20 ++-
 .../type/pattern_types/range_patterns.stderr  |  28 +++-
 47 files changed, 549 insertions(+), 281 deletions(-)

diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index e6d66f608da..f2b50ae408e 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -120,7 +120,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             .max_by_key(|niche| niche.available(dl));
 
         LayoutData {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: Some(VariantIdx::new(0)) },
             fields: FieldsShape::Arbitrary {
                 offsets: [Size::ZERO, b_offset].into(),
                 memory_index: [0, 1].into(),
@@ -214,7 +214,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
     ) -> LayoutData<FieldIdx, VariantIdx> {
         let dl = self.cx.data_layout();
         LayoutData {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: None },
             fields: FieldsShape::Primitive,
             backend_repr: BackendRepr::Uninhabited,
             largest_niche: None,
@@ -385,7 +385,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         };
 
         Ok(LayoutData {
-            variants: Variants::Single { index: only_variant_idx },
+            variants: Variants::Single { index: Some(only_variant_idx) },
             fields: FieldsShape::Union(union_field_count),
             backend_repr: abi,
             largest_niche: None,
@@ -424,7 +424,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         };
 
         let mut st = self.univariant(&variants[v], repr, kind)?;
-        st.variants = Variants::Single { index: v };
+        st.variants = Variants::Single { index: Some(v) };
 
         if is_unsafe_cell {
             let hide_niches = |scalar: &mut _| match scalar {
@@ -543,7 +543,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 .iter_enumerated()
                 .map(|(j, v)| {
                     let mut st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?;
-                    st.variants = Variants::Single { index: j };
+                    st.variants = Variants::Single { index: Some(j) };
 
                     align = align.max(st.align);
                     max_repr_align = max_repr_align.max(st.max_repr_align);
@@ -736,7 +736,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                     repr,
                     StructKind::Prefixed(min_ity.size(), prefix_align),
                 )?;
-                st.variants = Variants::Single { index: i };
+                st.variants = Variants::Single { index: Some(i) };
                 // Find the first field we can't move later
                 // to make room for a larger discriminant.
                 for field_idx in st.fields.index_by_increasing_offset() {
@@ -1344,7 +1344,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         };
 
         Ok(LayoutData {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: Some(VariantIdx::new(0)) },
             fields: FieldsShape::Arbitrary { offsets, memory_index },
             backend_repr: abi,
             largest_niche,
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 15a27c0b6ee..242e2cadd18 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1506,9 +1506,9 @@ impl BackendRepr {
 pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single {
-        /// Always 0 for non-enums/generators.
-        /// For enums without a variant, this is an invalid index!
-        index: VariantIdx,
+        /// Always `Some(0)` for types without variants (i.e., everything except for `!`, enums, and
+        /// generators). `None` indicates an uninhabited type; this is used for zero-variant enums.
+        index: Option<VariantIdx>,
     },
 
     /// Enum-likes with more than one variant: each variant comes with
@@ -1706,7 +1706,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
         let size = scalar.size(cx);
         let align = scalar.align(cx);
         LayoutData {
-            variants: Variants::Single { index: VariantIdx::new(0) },
+            variants: Variants::Single { index: Some(VariantIdx::new(0)) },
             fields: FieldsShape::Primitive,
             backend_repr: BackendRepr::Scalar(scalar),
             largest_niche,
diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs
index 45794a42665..055063c876f 100644
--- a/compiler/rustc_codegen_cranelift/src/discriminant.rs
+++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs
@@ -19,7 +19,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
     }
     match layout.variants {
         Variants::Single { index } => {
-            assert_eq!(index, variant_index);
+            assert_eq!(index.unwrap(), variant_index);
         }
         Variants::Multiple {
             tag: _,
@@ -86,9 +86,10 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
 
     let (tag_scalar, tag_field, tag_encoding) = match &layout.variants {
         Variants::Single { index } => {
+            let index = index.unwrap();
             let discr_val = layout
                 .ty
-                .discriminant_for_variant(fx.tcx, *index)
+                .discriminant_for_variant(fx.tcx, index)
                 .map_or(u128::from(index.as_u32()), |discr| discr.val);
 
             let val = match dest_layout.ty.kind() {
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 0efdf36da48..426d28f4ed7 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -99,14 +99,14 @@ fn uncached_gcc_type<'gcc, 'tcx>(
             if !cx.sess().fewer_names() =>
         {
             let mut name = with_no_trimmed_paths!(layout.ty.to_string());
-            if let (&ty::Adt(def, _), &Variants::Single { index }) =
+            if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) =
                 (layout.ty.kind(), &layout.variants)
             {
                 if def.is_enum() && !def.variants().is_empty() {
                     write!(&mut name, "::{}", def.variant(index).name).unwrap();
                 }
             }
-            if let (&ty::Coroutine(_, _), &Variants::Single { index }) =
+            if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) =
                 (layout.ty.kind(), &layout.variants)
             {
                 write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
@@ -230,7 +230,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
 
         // Check the cache.
         let variant_index = match self.variants {
-            Variants::Single { index } => Some(index),
+            Variants::Single { index } => index,
             _ => None,
         };
         let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned();
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index d374767f187..8ec83fa7c92 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -213,11 +213,11 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
         |cx, enum_type_di_node| {
             match enum_type_and_layout.variants {
                 Variants::Single { index: variant_index } => {
-                    if enum_adt_def.variants().is_empty() {
+                    let Some(variant_index) = variant_index else {
                         // Uninhabited enums have Variants::Single. We don't generate
                         // any members for them.
                         return smallvec![];
-                    }
+                    };
 
                     build_single_variant_union_fields(
                         cx,
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 2b05e24a7ba..833a687fe74 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -35,14 +35,14 @@ fn uncached_llvm_type<'a, 'tcx>(
             if !cx.sess().fewer_names() =>
         {
             let mut name = with_no_visible_paths!(with_no_trimmed_paths!(layout.ty.to_string()));
-            if let (&ty::Adt(def, _), &Variants::Single { index }) =
+            if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) =
                 (layout.ty.kind(), &layout.variants)
             {
-                if def.is_enum() && !def.variants().is_empty() {
+                if def.is_enum() {
                     write!(&mut name, "::{}", def.variant(index).name).unwrap();
                 }
             }
-            if let (&ty::Coroutine(_, _), &Variants::Single { index }) =
+            if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) =
                 (layout.ty.kind(), &layout.variants)
             {
                 write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
@@ -216,7 +216,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
 
         // Check the cache.
         let variant_index = match self.variants {
-            Variants::Single { index } => Some(index),
+            Variants::Single { index } => index,
             _ => None,
         };
         if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) {
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index a9e80e27ed4..cef3d8255a0 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -244,6 +244,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         }
         let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
             Variants::Single { index } => {
+                let index = index.unwrap(); // we already checked `is_uninhabited`
                 let discr_val = self
                     .layout
                     .ty
@@ -366,7 +367,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         }
         match self.layout.variants {
             Variants::Single { index } => {
-                assert_eq!(index, variant_index);
+                assert_eq!(index.unwrap(), variant_index);
             }
             Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => {
                 let ptr = self.project_field(bx, tag_field);
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 6faac1582ab..6cfd1613229 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -44,7 +44,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
-    /// Read discriminant, return the runtime value as well as the variant index.
+    /// Read discriminant, return the variant index.
     /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
     ///
     /// Will never return an uninhabited variant.
@@ -66,21 +66,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
         let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout().variants {
             Variants::Single { index } => {
-                // Do some extra checks on enums.
-                if ty.is_enum() {
-                    // Hilariously, `Single` is used even for 0-variant enums.
-                    // (See https://github.com/rust-lang/rust/issues/89765).
-                    if ty.ty_adt_def().unwrap().variants().is_empty() {
-                        throw_ub!(UninhabitedEnumVariantRead(index))
-                    }
+                if op.layout().is_uninhabited() {
                     // For consistency with `write_discriminant`, and to make sure that
                     // `project_downcast` cannot fail due to strange layouts, we declare immediate UB
-                    // for uninhabited variants.
-                    if op.layout().for_variant(self, index).is_uninhabited() {
-                        throw_ub!(UninhabitedEnumVariantRead(index))
-                    }
+                    // for uninhabited enums.
+                    throw_ub!(UninhabitedEnumVariantRead(None));
                 }
-                return interp_ok(index);
+                // Since the type is inhabited, there must be an index.
+                return interp_ok(index.unwrap());
             }
             Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
                 (tag, tag_encoding, tag_field)
@@ -199,11 +192,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // `uninhabited_enum_branching` MIR pass. It also ensures consistency with
         // `write_discriminant`.
         if op.layout().for_variant(self, index).is_uninhabited() {
-            throw_ub!(UninhabitedEnumVariantRead(index))
+            throw_ub!(UninhabitedEnumVariantRead(Some(index)))
         }
         interp_ok(index)
     }
 
+    /// Read discriminant, return the user-visible discriminant.
+    /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
     pub fn discriminant_for_variant(
         &self,
         ty: Ty<'tcx>,
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 8e18b243906..832183b42dc 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -342,7 +342,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                 match layout.variants {
                     Variants::Single { index } => {
                         // Inside a variant
-                        PathElem::Field(def.variant(index).fields[FieldIdx::from_usize(field)].name)
+                        PathElem::Field(
+                            def.variant(index.unwrap()).fields[FieldIdx::from_usize(field)].name,
+                        )
                     }
                     Variants::Multiple { .. } => bug!("we handled variants above"),
                 }
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index fbada6ec405..37328470aa7 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -392,7 +392,7 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     /// A discriminant of an uninhabited enum variant is written.
     UninhabitedEnumVariantWritten(VariantIdx),
     /// An uninhabited enum variant is projected.
-    UninhabitedEnumVariantRead(VariantIdx),
+    UninhabitedEnumVariantRead(Option<VariantIdx>),
     /// Trying to set discriminant to the niched variant, but the value does not match.
     InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
     /// ABI-incompatible argument types.
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index ad1680ed3a2..5f7b30b5d04 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -734,7 +734,7 @@ where
         let layout = match this.variants {
             Variants::Single { index }
                 // If all variants but one are uninhabited, the variant layout is the enum layout.
-                if index == variant_index &&
+                if index == Some(variant_index) &&
                 // Don't confuse variants of uninhabited enums with the enum itself.
                 // For more details see https://github.com/rust-lang/rust/issues/69763.
                 this.fields != FieldsShape::Primitive =>
@@ -743,6 +743,8 @@ where
             }
 
             Variants::Single { index } => {
+                // `Single` variant enums *can* have other variants, but those are uninhabited.
+
                 let tcx = cx.tcx();
                 let typing_env = cx.typing_env();
 
@@ -758,7 +760,7 @@ where
                     _ => bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty),
                 };
                 tcx.mk_layout(LayoutData {
-                    variants: Variants::Single { index: variant_index },
+                    variants: Variants::Single { index: Some(variant_index) },
                     fields: match NonZero::new(fields) {
                         Some(fields) => FieldsShape::Union(fields),
                         None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() },
@@ -775,7 +777,7 @@ where
             Variants::Multiple { ref variants, .. } => cx.tcx().mk_layout(variants[variant_index].clone()),
         };
 
-        assert_eq!(*layout.variants(), Variants::Single { index: variant_index });
+        assert_eq!(*layout.variants(), Variants::Single { index: Some(variant_index) });
 
         TyAndLayout { ty: this.ty, layout }
     }
@@ -905,7 +907,7 @@ where
                     Variants::Single { index } => TyMaybeWithLayout::Ty(
                         args.as_coroutine()
                             .state_tys(def_id, tcx)
-                            .nth(index.as_usize())
+                            .nth(index.unwrap().as_usize())
                             .unwrap()
                             .nth(i)
                             .unwrap(),
@@ -924,7 +926,8 @@ where
                 ty::Adt(def, args) => {
                     match this.variants {
                         Variants::Single { index } => {
-                            let field = &def.variant(index).fields[FieldIdx::from_usize(i)];
+                            let field =
+                                &def.variant(index.unwrap()).fields[FieldIdx::from_usize(i)];
                             TyMaybeWithLayout::Ty(field.ty(tcx, args))
                         }
 
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index beed007589b..8feb90ff7a0 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -35,7 +35,6 @@
 //! Likewise, applying the optimisation can create a lot of new MIR, so we bound the instruction
 //! cost by `MAX_COST`.
 
-use rustc_abi::{TagEncoding, Variants};
 use rustc_arena::DroplessArena;
 use rustc_const_eval::const_eval::DummyMachine;
 use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable};
@@ -565,31 +564,15 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
             StatementKind::SetDiscriminant { box place, variant_index } => {
                 let Some(discr_target) = self.map.find_discr(place.as_ref()) else { return };
                 let enum_ty = place.ty(self.body, self.tcx).ty;
-                // `SetDiscriminant` may be a no-op if the assigned variant is the untagged variant
-                // of a niche encoding. If we cannot ensure that we write to the discriminant, do
-                // nothing.
-                let Ok(enum_layout) = self.ecx.layout_of(enum_ty) else {
+                // `SetDiscriminant` guarantees that the discriminant is now `variant_index`.
+                // Even if the discriminant write does nothing due to niches, it is UB to set the
+                // discriminant when the data does not encode the desired discriminant.
+                let Some(discr) =
+                    self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err()
+                else {
                     return;
                 };
-                let writes_discriminant = match enum_layout.variants {
-                    Variants::Single { index } => {
-                        assert_eq!(index, *variant_index);
-                        true
-                    }
-                    Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => true,
-                    Variants::Multiple {
-                        tag_encoding: TagEncoding::Niche { untagged_variant, .. },
-                        ..
-                    } => *variant_index != untagged_variant,
-                };
-                if writes_discriminant {
-                    let Some(discr) =
-                        self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err()
-                    else {
-                        return;
-                    };
-                    self.process_immediate(bb, discr_target, discr, state);
-                }
+                self.process_immediate(bb, discr_target, discr, state);
             }
             // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`.
             StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 57e255b7c32..0ce3955163b 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -54,7 +54,11 @@ fn variant_discriminants<'tcx>(
     tcx: TyCtxt<'tcx>,
 ) -> FxHashSet<u128> {
     match &layout.variants {
-        Variants::Single { index } => {
+        Variants::Single { index: None } => {
+            // Uninhabited, no valid discriminant.
+            FxHashSet::default()
+        }
+        Variants::Single { index: Some(index) } => {
             let mut res = FxHashSet::default();
             res.insert(
                 ty.discriminant_for_variant(tcx, *index)
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index af24fd23f50..2717f4ab62f 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -164,9 +164,9 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         match self {
-            rustc_abi::Variants::Single { index } => {
-                VariantsShape::Single { index: index.stable(tables) }
-            }
+            rustc_abi::Variants::Single { index } => VariantsShape::Single {
+                index: index.unwrap_or(rustc_abi::VariantIdx::from_u32(0)).stable(tables),
+            },
             rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => {
                 VariantsShape::Multiple {
                     tag: tag.stable(tables),
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 83463babc4f..049f4734e7b 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -339,14 +339,12 @@ pub(crate) mod rustc {
 
             match layout.variants() {
                 Variants::Single { index } => {
-                    // Hilariously, `Single` is used even for 0-variant enums;
-                    // `index` is just junk in that case.
-                    if ty.ty_adt_def().unwrap().variants().is_empty() {
-                        Ok(Self::uninhabited())
-                    } else {
+                    if let Some(index) = index {
                         // `Variants::Single` on enums with variants denotes that
                         // the enum delegates its layout to the variant at `index`.
                         layout_of_variant(*index, None)
+                    } else {
+                        Ok(Self::uninhabited())
                     }
                 }
                 Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
@@ -504,7 +502,7 @@ pub(crate) mod rustc {
             ty::Adt(def, args) => {
                 match layout.variants {
                     Variants::Single { index } => {
-                        let field = &def.variant(index).fields[i];
+                        let field = &def.variant(index.unwrap()).fields[i];
                         field.ty(cx.tcx(), args)
                     }
                     // Discriminant field for enums (where applicable).
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 7c7c3803ad9..b393190a493 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -339,7 +339,7 @@ fn layout_of_uncached<'tcx>(
             let largest_niche = if count != 0 { element.largest_niche } else { None };
 
             tcx.mk_layout(LayoutData {
-                variants: Variants::Single { index: FIRST_VARIANT },
+                variants: Variants::Single { index: Some(FIRST_VARIANT) },
                 fields: FieldsShape::Array { stride: element.size, count },
                 backend_repr: abi,
                 largest_niche,
@@ -352,7 +352,7 @@ fn layout_of_uncached<'tcx>(
         ty::Slice(element) => {
             let element = cx.layout_of(element)?;
             tcx.mk_layout(LayoutData {
-                variants: Variants::Single { index: FIRST_VARIANT },
+                variants: Variants::Single { index: Some(FIRST_VARIANT) },
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
                 backend_repr: BackendRepr::Memory { sized: false },
                 largest_niche: None,
@@ -363,7 +363,7 @@ fn layout_of_uncached<'tcx>(
             })
         }
         ty::Str => tcx.mk_layout(LayoutData {
-            variants: Variants::Single { index: FIRST_VARIANT },
+            variants: Variants::Single { index: Some(FIRST_VARIANT) },
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
             backend_repr: BackendRepr::Memory { sized: false },
             largest_niche: None,
@@ -534,7 +534,7 @@ fn layout_of_uncached<'tcx>(
             };
 
             tcx.mk_layout(LayoutData {
-                variants: Variants::Single { index: FIRST_VARIANT },
+                variants: Variants::Single { index: Some(FIRST_VARIANT) },
                 fields,
                 backend_repr: abi,
                 largest_niche: e_ly.largest_niche,
@@ -926,7 +926,7 @@ fn coroutine_layout<'tcx>(
                 &ReprOptions::default(),
                 StructKind::Prefixed(prefix_size, prefix_align.abi),
             )?;
-            variant.variants = Variants::Single { index };
+            variant.variants = Variants::Single { index: Some(index) };
 
             let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else {
                 bug!();
@@ -1105,7 +1105,9 @@ fn variant_info_for_adt<'tcx>(
 
     match layout.variants {
         Variants::Single { index } => {
-            if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
+            if let Some(index) = index
+                && layout.fields != FieldsShape::Primitive
+            {
                 debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
                 let variant_def = &adt_def.variant(index);
                 let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs
index f39b87622f4..7e2375154c0 100644
--- a/compiler/rustc_ty_utils/src/layout/invariant.rs
+++ b/compiler/rustc_ty_utils/src/layout/invariant.rs
@@ -241,63 +241,81 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
 
     check_layout_abi(cx, layout);
 
-    if let Variants::Multiple { variants, tag, tag_encoding, .. } = &layout.variants {
-        if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } = tag_encoding {
-            let niche_size = tag.size(cx);
-            assert!(*niche_start <= niche_size.unsigned_int_max());
-            for (idx, variant) in variants.iter_enumerated() {
-                // Ensure all inhabited variants are accounted for.
-                if !variant.is_uninhabited() {
-                    assert!(idx == *untagged_variant || niche_variants.contains(&idx));
-                }
+    match &layout.variants {
+        Variants::Single { index: None } => {
+            assert!(layout.is_uninhabited());
+        }
+        Variants::Single { index: Some(idx) } => {
+            if let Some(variants) = layout.ty.variant_range(tcx) {
+                assert!(variants.contains(idx));
+            } else {
+                // Types without variants use `0` as dummy variant index.
+                assert!(idx.as_u32() == 0);
             }
         }
-        for variant in variants.iter() {
-            // No nested "multiple".
-            assert_matches!(variant.variants, Variants::Single { .. });
-            // Variants should have the same or a smaller size as the full thing,
-            // and same for alignment.
-            if variant.size > layout.size {
-                bug!(
-                    "Type with size {} bytes has variant with size {} bytes: {layout:#?}",
-                    layout.size.bytes(),
-                    variant.size.bytes(),
-                )
-            }
-            if variant.align.abi > layout.align.abi {
-                bug!(
-                    "Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}",
-                    layout.align.abi.bytes(),
-                    variant.align.abi.bytes(),
-                )
-            }
-            // Skip empty variants.
-            if variant.size == Size::ZERO || variant.fields.count() == 0 || variant.is_uninhabited()
+        Variants::Multiple { variants, tag, tag_encoding, .. } => {
+            if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } =
+                tag_encoding
             {
-                // These are never actually accessed anyway, so we can skip the coherence check
-                // for them. They also fail that check, since they have
-                // `Aggregate`/`Uninhabited` ABI even when the main type is
-                // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size
-                // 0, and sometimes, variants without fields have non-0 size.)
-                continue;
-            }
-            // The top-level ABI and the ABI of the variants should be coherent.
-            let scalar_coherent =
-                |s1: Scalar, s2: Scalar| s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx);
-            let abi_coherent = match (layout.backend_repr, variant.backend_repr) {
-                (BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => scalar_coherent(s1, s2),
-                (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => {
-                    scalar_coherent(a1, a2) && scalar_coherent(b1, b2)
+                let niche_size = tag.size(cx);
+                assert!(*niche_start <= niche_size.unsigned_int_max());
+                for (idx, variant) in variants.iter_enumerated() {
+                    // Ensure all inhabited variants are accounted for.
+                    if !variant.is_uninhabited() {
+                        assert!(idx == *untagged_variant || niche_variants.contains(&idx));
+                    }
+                }
+            }
+            for variant in variants.iter() {
+                // No nested "multiple".
+                assert_matches!(variant.variants, Variants::Single { .. });
+                // Variants should have the same or a smaller size as the full thing,
+                // and same for alignment.
+                if variant.size > layout.size {
+                    bug!(
+                        "Type with size {} bytes has variant with size {} bytes: {layout:#?}",
+                        layout.size.bytes(),
+                        variant.size.bytes(),
+                    )
+                }
+                if variant.align.abi > layout.align.abi {
+                    bug!(
+                        "Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}",
+                        layout.align.abi.bytes(),
+                        variant.align.abi.bytes(),
+                    )
+                }
+                // Skip empty variants.
+                if variant.size == Size::ZERO
+                    || variant.fields.count() == 0
+                    || variant.is_uninhabited()
+                {
+                    // These are never actually accessed anyway, so we can skip the coherence check
+                    // for them. They also fail that check, since they have
+                    // `Aggregate`/`Uninhabited` ABI even when the main type is
+                    // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size
+                    // 0, and sometimes, variants without fields have non-0 size.)
+                    continue;
+                }
+                // The top-level ABI and the ABI of the variants should be coherent.
+                let scalar_coherent = |s1: Scalar, s2: Scalar| {
+                    s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx)
+                };
+                let abi_coherent = match (layout.backend_repr, variant.backend_repr) {
+                    (BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => scalar_coherent(s1, s2),
+                    (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => {
+                        scalar_coherent(a1, a2) && scalar_coherent(b1, b2)
+                    }
+                    (BackendRepr::Uninhabited, _) => true,
+                    (BackendRepr::Memory { .. }, _) => true,
+                    _ => false,
+                };
+                if !abi_coherent {
+                    bug!(
+                        "Variant ABI is incompatible with top-level ABI:\nvariant={:#?}\nTop-level: {layout:#?}",
+                        variant
+                    );
                 }
-                (BackendRepr::Uninhabited, _) => true,
-                (BackendRepr::Memory { .. }, _) => true,
-                _ => false,
-            };
-            if !abi_coherent {
-                bug!(
-                    "Variant ABI is incompatible with top-level ABI:\nvariant={:#?}\nTop-level: {layout:#?}",
-                    variant
-                );
             }
         }
     }
diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs
index 2ac30b5aff1..cf28a0c5885 100644
--- a/compiler/stable_mir/src/abi.rs
+++ b/compiler/stable_mir/src/abi.rs
@@ -181,6 +181,7 @@ impl FieldsShape {
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum VariantsShape {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
+    // FIXME: needs to become `Option` like in the internal type.
     Single { index: VariantIdx },
 
     /// Enum-likes with more than one inhabited variant: each variant comes with
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index 0c1f63880cd..08026f11c83 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -189,7 +189,7 @@ fn layout_of_simd_ty(
     };
 
     Ok(Arc::new(Layout {
-        variants: Variants::Single { index: struct_variant_idx() },
+        variants: Variants::Single { index: Some(struct_variant_idx()) },
         fields,
         backend_repr: BackendRepr::Vector { element: e_abi, count: e_len },
         largest_niche: e_ly.largest_niche,
@@ -305,7 +305,7 @@ pub fn layout_of_ty_query(
             let largest_niche = if count != 0 { element.largest_niche } else { None };
 
             Layout {
-                variants: Variants::Single { index: struct_variant_idx() },
+                variants: Variants::Single { index: Some(struct_variant_idx()) },
                 fields: FieldsShape::Array { stride: element.size, count },
                 backend_repr,
                 largest_niche,
@@ -318,7 +318,7 @@ pub fn layout_of_ty_query(
         TyKind::Slice(element) => {
             let element = db.layout_of_ty(element.clone(), trait_env)?;
             Layout {
-                variants: Variants::Single { index: struct_variant_idx() },
+                variants: Variants::Single { index: Some(struct_variant_idx()) },
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
                 backend_repr: BackendRepr::Memory { sized: false },
                 largest_niche: None,
@@ -329,7 +329,7 @@ pub fn layout_of_ty_query(
             }
         }
         TyKind::Str => Layout {
-            variants: Variants::Single { index: struct_variant_idx() },
+            variants: Variants::Single { index: Some(struct_variant_idx()) },
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
             backend_repr: BackendRepr::Memory { sized: false },
             largest_niche: None,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index d7029651fc1..9375853e915 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -1639,7 +1639,8 @@ impl Evaluator<'_> {
         };
         match &layout.variants {
             Variants::Single { index } => {
-                let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?;
+                let r = self
+                    .const_eval_discriminant(self.db.enum_data(e).variants[index.unwrap().0].0)?;
                 Ok(r)
             }
             Variants::Multiple { tag, tag_encoding, variants, .. } => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 06719b09f73..43ed6a06f42 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -335,7 +335,7 @@ pub(crate) fn detect_variant_from_bytes<'a>(
 ) -> Option<(EnumVariantId, &'a Layout)> {
     let (var_id, var_layout) = match &layout.variants {
         hir_def::layout::Variants::Single { index } => {
-            (db.enum_data(e).variants[index.0].0, layout)
+            (db.enum_data(e).variants[index.unwrap().0].0, layout)
         }
         hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
             let size = tag.size(target_data_layout).bytes_usize();
diff --git a/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff b/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff
index 3d9852aef65..992b16fabf6 100644
--- a/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff
+++ b/tests/mir-opt/set_no_discriminant.f.JumpThreading.diff
@@ -10,7 +10,8 @@
           _2 = E::<char>::A;
           discriminant(_2) = 1;
           _1 = discriminant(_2);
-          switchInt(copy _1) -> [0: bb1, otherwise: bb2];
+-         switchInt(copy _1) -> [0: bb1, otherwise: bb2];
++         goto -> bb2;
       }
   
       bb1: {
diff --git a/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff b/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff
index c7af1638316..0600b751699 100644
--- a/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff
+++ b/tests/mir-opt/set_no_discriminant.generic.JumpThreading.diff
@@ -10,7 +10,8 @@
           _2 = E::<T>::A;
           discriminant(_2) = 1;
           _1 = discriminant(_2);
-          switchInt(copy _1) -> [0: bb1, otherwise: bb2];
+-         switchInt(copy _1) -> [0: bb1, otherwise: bb2];
++         goto -> bb2;
       }
   
       bb1: {
diff --git a/tests/mir-opt/set_no_discriminant.rs b/tests/mir-opt/set_no_discriminant.rs
index 586e28ae426..c44575a4d61 100644
--- a/tests/mir-opt/set_no_discriminant.rs
+++ b/tests/mir-opt/set_no_discriminant.rs
@@ -1,5 +1,6 @@
 // `SetDiscriminant` does not actually write anything if the chosen variant is the untagged variant
-// of a niche encoding. Verify that we do not thread over this case.
+// of a niche encoding. However, it is UB to call `SetDiscriminant` with the untagged variant if the
+// value currently encodes a different variant. Verify that we do correctly thread in this case.
 //@ test-mir-pass: JumpThreading
 
 #![feature(custom_mir)]
@@ -16,20 +17,21 @@ enum E<T> {
 #[custom_mir(dialect = "runtime")]
 pub fn f() -> usize {
     // CHECK-LABEL: fn f(
-    // CHECK-NOT: goto
-    // CHECK: switchInt(
-    // CHECK-NOT: goto
+    // CHECK-NOT: switchInt
+    // CHECK: goto
+    // CHECK-NOT: switchInt
     mir! {
         let a: isize;
         let e: E<char>;
         {
             e = E::A;
-            SetDiscriminant(e, 1);
+            SetDiscriminant(e, 1); // UB!
             a = Discriminant(e);
             match a {
                 0 => bb0,
                 _ => bb1,
             }
+
         }
         bb0 = {
             RET = 0;
@@ -46,15 +48,15 @@ pub fn f() -> usize {
 #[custom_mir(dialect = "runtime")]
 pub fn generic<T>() -> usize {
     // CHECK-LABEL: fn generic(
-    // CHECK-NOT: goto
-    // CHECK: switchInt(
-    // CHECK-NOT: goto
+    // CHECK-NOT: switchInt
+    // CHECK: goto
+    // CHECK-NOT: switchInt
     mir! {
         let a: isize;
         let e: E<T>;
         {
             e = E::A;
-            SetDiscriminant(e, 1);
+            SetDiscriminant(e, 1); // UB!
             a = Discriminant(e);
             match a {
                 0 => bb0,
@@ -72,6 +74,7 @@ pub fn generic<T>() -> usize {
     }
 }
 
+// CHECK-LABEL: fn main(
 fn main() {
     assert_eq!(f(), 0);
     assert_eq!(generic::<char>(), 0);
diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr
index 7d384bc875f..aae92bd7dc9 100644
--- a/tests/ui/abi/c-zst.aarch64-darwin.stderr
+++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr
index 7980710bab6..4ff4a8b90cf 100644
--- a/tests/ui/abi/c-zst.powerpc-linux.stderr
+++ b/tests/ui/abi/c-zst.powerpc-linux.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr
index 7980710bab6..4ff4a8b90cf 100644
--- a/tests/ui/abi/c-zst.s390x-linux.stderr
+++ b/tests/ui/abi/c-zst.s390x-linux.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr
index 7980710bab6..4ff4a8b90cf 100644
--- a/tests/ui/abi/c-zst.sparc64-linux.stderr
+++ b/tests/ui/abi/c-zst.sparc64-linux.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr
index 7d384bc875f..aae92bd7dc9 100644
--- a/tests/ui/abi/c-zst.x86_64-linux.stderr
+++ b/tests/ui/abi/c-zst.x86_64-linux.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
index 7980710bab6..4ff4a8b90cf 100644
--- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
+++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr
index aa51c42c58d..0cbdf366616 100644
--- a/tests/ui/abi/debug.stderr
+++ b/tests/ui/abi/debug.stderr
@@ -21,7 +21,9 @@ error: fn_abi_of(test) = FnAbi {
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -67,7 +69,9 @@ error: fn_abi_of(test) = FnAbi {
                            },
                        ),
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -124,7 +128,9 @@ error: fn_abi_of(TestFnPtr) = FnAbi {
                                },
                            ),
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -161,7 +167,9 @@ error: fn_abi_of(TestFnPtr) = FnAbi {
                        fields: Primitive,
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -210,7 +218,9 @@ error: fn_abi_of(test_generic) = FnAbi {
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -244,7 +254,9 @@ error: fn_abi_of(test_generic) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -292,7 +304,9 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -326,7 +340,9 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -362,7 +378,9 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -396,7 +414,9 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -435,7 +455,9 @@ error: ABIs are not compatible
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -473,7 +495,9 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -506,7 +530,9 @@ error: ABIs are not compatible
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -544,7 +570,9 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -585,7 +613,9 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -619,7 +649,9 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -655,7 +687,9 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -689,7 +723,9 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -731,7 +767,9 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -765,7 +803,9 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -801,7 +841,9 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -835,7 +877,9 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -902,7 +946,9 @@ error: fn_abi_of(assoc_test) = FnAbi {
                                },
                            ),
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -938,7 +984,9 @@ error: fn_abi_of(assoc_test) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr
index 8e1791e27d2..920963c6987 100644
--- a/tests/ui/abi/sysv64-zst.stderr
+++ b/tests/ui/abi/sysv64-zst.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/win64-zst.x86_64-linux.stderr b/tests/ui/abi/win64-zst.x86_64-linux.stderr
index 76d90670eb1..2752555b4f3 100644
--- a/tests/ui/abi/win64-zst.x86_64-linux.stderr
+++ b/tests/ui/abi/win64-zst.x86_64-linux.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr
index 7ee90e24744..19abb5930b1 100644
--- a/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr
+++ b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -56,7 +58,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr
index 76d90670eb1..2752555b4f3 100644
--- a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr
+++ b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr
@@ -18,7 +18,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: 0,
+                               index: Some(
+                                   0,
+                               ),
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -45,7 +47,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr
index bd31665dac1..8ae2933c427 100644
--- a/tests/ui/layout/debug.stderr
+++ b/tests/ui/layout/debug.stderr
@@ -57,7 +57,9 @@ error: layout_of(E) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -83,7 +85,9 @@ error: layout_of(E) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -134,7 +138,9 @@ error: layout_of(S) = Layout {
            },
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -158,7 +164,9 @@ error: layout_of(U) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -251,7 +259,9 @@ error: layout_of(Result<i32, i32>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -288,7 +298,9 @@ error: layout_of(Result<i32, i32>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -321,7 +333,9 @@ error: layout_of(i32) = Layout {
            fields: Primitive,
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -345,7 +359,9 @@ error: layout_of(V) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(2 bytes),
@@ -369,7 +385,9 @@ error: layout_of(W) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(2 bytes),
@@ -393,7 +411,9 @@ error: layout_of(Y) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(2 bytes),
@@ -417,7 +437,9 @@ error: layout_of(P1) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -441,7 +463,9 @@ error: layout_of(P2) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -465,7 +489,9 @@ error: layout_of(P3) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -489,7 +515,9 @@ error: layout_of(P4) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -518,7 +546,9 @@ error: layout_of(P5) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -547,7 +577,9 @@ error: layout_of(MaybeUninit<u8>) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr
index 59fe667923f..a934f270911 100644
--- a/tests/ui/layout/hexagon-enum.stderr
+++ b/tests/ui/layout/hexagon-enum.stderr
@@ -57,7 +57,9 @@ error: layout_of(A) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -131,7 +133,9 @@ error: layout_of(B) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -205,7 +209,9 @@ error: layout_of(C) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(2 bytes),
@@ -279,7 +285,9 @@ error: layout_of(P) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -353,7 +361,9 @@ error: layout_of(T) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
index ca041fb539b..8b4e46de845 100644
--- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
+++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
@@ -79,7 +79,9 @@ error: layout_of(MissingPayloadField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -99,7 +101,9 @@ error: layout_of(MissingPayloadField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -197,7 +201,9 @@ error: layout_of(CommonPayloadField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -234,7 +240,9 @@ error: layout_of(CommonPayloadField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -330,7 +338,9 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -366,7 +376,9 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -478,7 +490,9 @@ error: layout_of(NicheFirst) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -498,7 +512,9 @@ error: layout_of(NicheFirst) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -518,7 +534,9 @@ error: layout_of(NicheFirst) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 2,
+                           index: Some(
+                               2,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -630,7 +648,9 @@ error: layout_of(NicheSecond) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -650,7 +670,9 @@ error: layout_of(NicheSecond) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -670,7 +692,9 @@ error: layout_of(NicheSecond) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 2,
+                           index: Some(
+                               2,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr
index bc40a2aa482..92643445595 100644
--- a/tests/ui/layout/issue-96185-overaligned-enum.stderr
+++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr
@@ -51,7 +51,9 @@ error: layout_of(Aligned1) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -73,7 +75,9 @@ error: layout_of(Aligned1) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -151,7 +155,9 @@ error: layout_of(Aligned2) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(1 bytes),
@@ -173,7 +179,9 @@ error: layout_of(Aligned2) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(1 bytes),
diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr
index bf043af586b..f35cf0dab3d 100644
--- a/tests/ui/layout/thumb-enum.stderr
+++ b/tests/ui/layout/thumb-enum.stderr
@@ -57,7 +57,9 @@ error: layout_of(A) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -131,7 +133,9 @@ error: layout_of(B) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -205,7 +209,9 @@ error: layout_of(C) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(2 bytes),
@@ -279,7 +285,9 @@ error: layout_of(P) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -353,7 +361,9 @@ error: layout_of(T) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr
index d61408098df..4c6f636b267 100644
--- a/tests/ui/layout/zero-sized-array-enum-niche.stderr
+++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr
@@ -55,7 +55,9 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -88,7 +90,9 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -160,7 +164,9 @@ error: layout_of(MultipleAlignments) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(2 bytes),
@@ -184,7 +190,9 @@ error: layout_of(MultipleAlignments) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -217,7 +225,9 @@ error: layout_of(MultipleAlignments) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: 2,
+                           index: Some(
+                               2,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -289,7 +299,9 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -322,7 +334,9 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -398,7 +412,9 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -431,7 +447,9 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
index 64a0cb7f31a..08fd4237eeb 100644
--- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
@@ -51,7 +51,9 @@ error: layout_of(Univariant) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -133,7 +135,9 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -169,7 +173,9 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
index 5c4daa6d519..473268cac1a 100644
--- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
@@ -51,7 +51,9 @@ error: layout_of(Univariant) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -133,7 +135,9 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -169,7 +173,9 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
index 64a0cb7f31a..08fd4237eeb 100644
--- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
@@ -51,7 +51,9 @@ error: layout_of(Univariant) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -133,7 +135,9 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -169,7 +173,9 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
index 64a0cb7f31a..08fd4237eeb 100644
--- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
@@ -51,7 +51,9 @@ error: layout_of(Univariant) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -133,7 +135,9 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -169,7 +173,9 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr
index 75005a64523..1200f120d37 100644
--- a/tests/ui/repr/repr-c-int-dead-variants.stderr
+++ b/tests/ui/repr/repr-c-int-dead-variants.stderr
@@ -51,7 +51,9 @@ error: layout_of(UnivariantU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -133,7 +135,9 @@ error: layout_of(TwoVariantsU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -169,7 +173,9 @@ error: layout_of(TwoVariantsU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -241,7 +247,9 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -267,7 +275,9 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr
index 0eed7c2ce1c..9954471968d 100644
--- a/tests/ui/type/pattern_types/range_patterns.stderr
+++ b/tests/ui/type/pattern_types/range_patterns.stderr
@@ -32,7 +32,9 @@ error: layout_of(NonZero<u32>) = Layout {
                },
            ),
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -69,7 +71,9 @@ error: layout_of((u32) is 1..=) = Layout {
                },
            ),
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -133,7 +137,9 @@ error: layout_of(Option<(u32) is 1..=>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -172,7 +178,9 @@ error: layout_of(Option<(u32) is 1..=>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -241,7 +249,9 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: 0,
+                           index: Some(
+                               0,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -280,7 +290,9 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: 1,
+                           index: Some(
+                               1,
+                           ),
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -329,7 +341,9 @@ error: layout_of(NonZeroU32New) = Layout {
                },
            ),
            variants: Single {
-               index: 0,
+               index: Some(
+                   0,
+               ),
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),

From e023590de407f417e0f3da675a372eca7acf60c6 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 1 Dec 2024 17:33:01 +0100
Subject: [PATCH 05/14] make no-variant types a dedicated Variants variant

---
 compiler/rustc_abi/src/callconv.rs            |  2 +-
 compiler/rustc_abi/src/layout.rs              | 19 ++--
 compiler/rustc_abi/src/lib.rs                 | 10 +-
 .../src/discriminant.rs                       |  7 +-
 compiler/rustc_codegen_gcc/src/type_of.rs     |  6 +-
 .../src/debuginfo/metadata/enums/cpp_like.rs  | 26 +++--
 .../src/debuginfo/metadata/enums/mod.rs       |  2 +-
 .../src/debuginfo/metadata/enums/native.rs    |  4 +-
 compiler/rustc_codegen_llvm/src/type_of.rs    |  6 +-
 .../rustc_codegen_ssa/src/debuginfo/mod.rs    |  4 +-
 compiler/rustc_codegen_ssa/src/mir/place.rs   |  8 +-
 .../src/interpret/discriminant.rs             |  8 +-
 .../src/interpret/validity.rs                 |  9 +-
 .../rustc_const_eval/src/interpret/visitor.rs |  4 +-
 .../src/util/check_validity_requirement.rs    |  1 +
 compiler/rustc_middle/src/ty/layout.rs        | 24 ++---
 .../rustc_mir_transform/src/large_enums.rs    |  2 +-
 .../src/unreachable_enum_branching.rs         |  4 +-
 .../rustc_smir/src/rustc_smir/convert/abi.rs  |  7 +-
 .../rustc_target/src/callconv/loongarch.rs    |  2 +-
 compiler/rustc_target/src/callconv/riscv.rs   |  2 +-
 compiler/rustc_target/src/callconv/x86_64.rs  |  2 +-
 compiler/rustc_transmute/src/layout/tree.rs   | 15 ++-
 compiler/rustc_ty_utils/src/layout.rs         | 26 +++--
 .../rustc_ty_utils/src/layout/invariant.rs    |  8 +-
 compiler/stable_mir/src/abi.rs                |  4 +-
 src/tools/miri/src/helpers.rs                 |  2 +-
 .../rust-analyzer/crates/hir-ty/src/layout.rs |  8 +-
 .../crates/hir-ty/src/mir/eval.rs             |  8 +-
 .../rust-analyzer/crates/hir-ty/src/utils.rs  |  3 +-
 tests/ui/abi/c-zst.aarch64-darwin.stderr      |  8 +-
 tests/ui/abi/c-zst.powerpc-linux.stderr       |  8 +-
 tests/ui/abi/c-zst.s390x-linux.stderr         |  8 +-
 tests/ui/abi/c-zst.sparc64-linux.stderr       |  8 +-
 tests/ui/abi/c-zst.x86_64-linux.stderr        |  8 +-
 .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr |  8 +-
 tests/ui/abi/debug.stderr                     | 96 +++++--------------
 tests/ui/abi/sysv64-zst.stderr                |  8 +-
 tests/ui/abi/win64-zst.x86_64-linux.stderr    |  8 +-
 .../abi/win64-zst.x86_64-windows-gnu.stderr   |  8 +-
 .../abi/win64-zst.x86_64-windows-msvc.stderr  |  8 +-
 tests/ui/layout/debug.stderr                  | 64 ++++---------
 tests/ui/layout/hexagon-enum.stderr           | 20 +---
 ...-scalarpair-payload-might-be-uninit.stderr | 48 +++-------
 .../issue-96185-overaligned-enum.stderr       | 16 +---
 tests/ui/layout/thumb-enum.stderr             | 20 +---
 .../layout/zero-sized-array-enum-niche.stderr | 36 ++-----
 ...-variants.aarch64-unknown-linux-gnu.stderr | 20 +---
 ...-c-dead-variants.armebv7r-none-eabi.stderr | 20 +---
 ...-dead-variants.i686-pc-windows-msvc.stderr | 20 +---
 ...d-variants.x86_64-unknown-linux-gnu.stderr | 20 +---
 tests/ui/repr/repr-c-int-dead-variants.stderr | 20 +---
 .../type/pattern_types/range_patterns.stderr  | 28 ++----
 53 files changed, 246 insertions(+), 495 deletions(-)

diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs
index ee63e46e88c..400395f99ff 100644
--- a/compiler/rustc_abi/src/callconv.rs
+++ b/compiler/rustc_abi/src/callconv.rs
@@ -206,7 +206,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
                 let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
 
                 match &self.variants {
-                    abi::Variants::Single { .. } => {}
+                    abi::Variants::Single { .. } | abi::Variants::Empty => {}
                     abi::Variants::Multiple { variants, .. } => {
                         // Treat enum variants like union members.
                         // HACK(eddyb) pretend the `enum` field (discriminant)
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index f2b50ae408e..226a46f605c 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -120,7 +120,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             .max_by_key(|niche| niche.available(dl));
 
         LayoutData {
-            variants: Variants::Single { index: Some(VariantIdx::new(0)) },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Arbitrary {
                 offsets: [Size::ZERO, b_offset].into(),
                 memory_index: [0, 1].into(),
@@ -213,8 +213,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         &self,
     ) -> LayoutData<FieldIdx, VariantIdx> {
         let dl = self.cx.data_layout();
+        // This is also used for uninhabited enums, so we use `Variants::Empty`.
         LayoutData {
-            variants: Variants::Single { index: None },
+            variants: Variants::Empty,
             fields: FieldsShape::Primitive,
             backend_repr: BackendRepr::Uninhabited,
             largest_niche: None,
@@ -385,7 +386,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         };
 
         Ok(LayoutData {
-            variants: Variants::Single { index: Some(only_variant_idx) },
+            variants: Variants::Single { index: only_variant_idx },
             fields: FieldsShape::Union(union_field_count),
             backend_repr: abi,
             largest_niche: None,
@@ -424,7 +425,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         };
 
         let mut st = self.univariant(&variants[v], repr, kind)?;
-        st.variants = Variants::Single { index: Some(v) };
+        st.variants = Variants::Single { index: v };
 
         if is_unsafe_cell {
             let hide_niches = |scalar: &mut _| match scalar {
@@ -543,7 +544,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                 .iter_enumerated()
                 .map(|(j, v)| {
                     let mut st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?;
-                    st.variants = Variants::Single { index: Some(j) };
+                    st.variants = Variants::Single { index: j };
 
                     align = align.max(st.align);
                     max_repr_align = max_repr_align.max(st.max_repr_align);
@@ -736,7 +737,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
                     repr,
                     StructKind::Prefixed(min_ity.size(), prefix_align),
                 )?;
-                st.variants = Variants::Single { index: Some(i) };
+                st.variants = Variants::Single { index: i };
                 // Find the first field we can't move later
                 // to make room for a larger discriminant.
                 for field_idx in st.fields.index_by_increasing_offset() {
@@ -1004,8 +1005,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
                 Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants }
             }
-            Variants::Single { .. } => {
-                panic!("encountered a single-variant enum during multi-variant layout")
+            Variants::Single { .. } | Variants::Empty => {
+                panic!("encountered a single-variant or empty enum during multi-variant layout")
             }
         };
         Ok(best_layout.layout)
@@ -1344,7 +1345,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         };
 
         Ok(LayoutData {
-            variants: Variants::Single { index: Some(VariantIdx::new(0)) },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Arbitrary { offsets, memory_index },
             backend_repr: abi,
             largest_niche,
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 242e2cadd18..ca15f7d9920 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1504,11 +1504,13 @@ impl BackendRepr {
 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
 pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
+    /// A type with no valid variants. Must be uninhabited.
+    Empty,
+
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single {
-        /// Always `Some(0)` for types without variants (i.e., everything except for `!`, enums, and
-        /// generators). `None` indicates an uninhabited type; this is used for zero-variant enums.
-        index: Option<VariantIdx>,
+        /// Always `0` for types that cannot have multiple variants.
+        index: VariantIdx,
     },
 
     /// Enum-likes with more than one variant: each variant comes with
@@ -1706,7 +1708,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
         let size = scalar.size(cx);
         let align = scalar.align(cx);
         LayoutData {
-            variants: Variants::Single { index: Some(VariantIdx::new(0)) },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Primitive,
             backend_repr: BackendRepr::Scalar(scalar),
             largest_niche,
diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs
index 055063c876f..4d0d5dc60eb 100644
--- a/compiler/rustc_codegen_cranelift/src/discriminant.rs
+++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs
@@ -18,8 +18,9 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
         return;
     }
     match layout.variants {
+        Variants::Empty => unreachable!("we already handled uninhabited types"),
         Variants::Single { index } => {
-            assert_eq!(index.unwrap(), variant_index);
+            assert_eq!(index, variant_index);
         }
         Variants::Multiple {
             tag: _,
@@ -85,11 +86,11 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
     }
 
     let (tag_scalar, tag_field, tag_encoding) = match &layout.variants {
+        Variants::Empty => unreachable!("we already handled uninhabited types"),
         Variants::Single { index } => {
-            let index = index.unwrap();
             let discr_val = layout
                 .ty
-                .discriminant_for_variant(fx.tcx, index)
+                .discriminant_for_variant(fx.tcx, *index)
                 .map_or(u128::from(index.as_u32()), |discr| discr.val);
 
             let val = match dest_layout.ty.kind() {
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 426d28f4ed7..0efdf36da48 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -99,14 +99,14 @@ fn uncached_gcc_type<'gcc, 'tcx>(
             if !cx.sess().fewer_names() =>
         {
             let mut name = with_no_trimmed_paths!(layout.ty.to_string());
-            if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) =
+            if let (&ty::Adt(def, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
                 if def.is_enum() && !def.variants().is_empty() {
                     write!(&mut name, "::{}", def.variant(index).name).unwrap();
                 }
             }
-            if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) =
+            if let (&ty::Coroutine(_, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
                 write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
@@ -230,7 +230,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
 
         // Check the cache.
         let variant_index = match self.variants {
-            Variants::Single { index } => index,
+            Variants::Single { index } => Some(index),
             _ => None,
         };
         let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned();
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 8ec83fa7c92..12a46184d10 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -212,21 +212,18 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
         ),
         |cx, enum_type_di_node| {
             match enum_type_and_layout.variants {
-                Variants::Single { index: variant_index } => {
-                    let Some(variant_index) = variant_index else {
-                        // Uninhabited enums have Variants::Single. We don't generate
-                        // any members for them.
-                        return smallvec![];
-                    };
-
-                    build_single_variant_union_fields(
-                        cx,
-                        enum_adt_def,
-                        enum_type_and_layout,
-                        enum_type_di_node,
-                        variant_index,
-                    )
+                Variants::Empty => {
+                    // Uninhabited enums have Variants::Single. We don't generate
+                    // any members for them.
+                    return smallvec![];
                 }
+                Variants::Single { index: variant_index } => build_single_variant_union_fields(
+                    cx,
+                    enum_adt_def,
+                    enum_type_and_layout,
+                    enum_type_di_node,
+                    variant_index,
+                ),
                 Variants::Multiple {
                     tag_encoding: TagEncoding::Direct,
                     ref variants,
@@ -303,6 +300,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
                 )
             }
             Variants::Single { .. }
+            | Variants::Empty
             | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => {
                 bug!(
                     "Encountered coroutine with non-direct-tag layout: {:?}",
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 65ab22ad89e..9f6a5cc89e0 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -392,7 +392,7 @@ fn compute_discriminant_value<'ll, 'tcx>(
     variant_index: VariantIdx,
 ) -> DiscrResult {
     match enum_type_and_layout.layout.variants() {
-        &Variants::Single { .. } => DiscrResult::NoDiscriminant,
+        &Variants::Single { .. } | &Variants::Empty => DiscrResult::NoDiscriminant,
         &Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => DiscrResult::Value(
             enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val,
         ),
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 241bf167a81..11824398f24 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -358,8 +358,8 @@ fn build_discr_member_di_node<'ll, 'tcx>(
     let containing_scope = enum_or_coroutine_type_di_node;
 
     match enum_or_coroutine_type_and_layout.layout.variants() {
-        // A single-variant enum has no discriminant.
-        &Variants::Single { .. } => None,
+        // A single-variant or no-variant enum has no discriminant.
+        &Variants::Single { .. } | &Variants::Empty => None,
 
         &Variants::Multiple { tag_field, .. } => {
             let tag_base_type = tag_base_type(cx.tcx, enum_or_coroutine_type_and_layout);
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 833a687fe74..b0b6da869da 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -35,14 +35,14 @@ fn uncached_llvm_type<'a, 'tcx>(
             if !cx.sess().fewer_names() =>
         {
             let mut name = with_no_visible_paths!(with_no_trimmed_paths!(layout.ty.to_string()));
-            if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) =
+            if let (&ty::Adt(def, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
                 if def.is_enum() {
                     write!(&mut name, "::{}", def.variant(index).name).unwrap();
                 }
             }
-            if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) =
+            if let (&ty::Coroutine(_, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
                 write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
@@ -216,7 +216,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
 
         // Check the cache.
         let variant_index = match self.variants {
-            Variants::Single { index } => index,
+            Variants::Single { index } => Some(index),
             _ => None,
         };
         if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
index 88d36b19da4..7c62c03d574 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
@@ -65,8 +65,8 @@ fn tag_base_type_opt<'tcx>(
     });
 
     match enum_type_and_layout.layout.variants() {
-        // A single-variant enum has no discriminant.
-        Variants::Single { .. } => None,
+        // A single-variant or no-variant enum has no discriminant.
+        Variants::Single { .. } | Variants::Empty => None,
 
         Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => {
             // Niche tags are always normalized to unsized integers of the correct size.
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index cef3d8255a0..c634f864ffb 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -243,8 +243,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
             return bx.cx().const_poison(cast_to);
         }
         let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
+            Variants::Empty => unreachable!("we already handled uninhabited types"),
             Variants::Single { index } => {
-                let index = index.unwrap(); // we already checked `is_uninhabited`
                 let discr_val = self
                     .layout
                     .ty
@@ -366,9 +366,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
             return;
         }
         match self.layout.variants {
-            Variants::Single { index } => {
-                assert_eq!(index.unwrap(), variant_index);
-            }
+            Variants::Empty => unreachable!("we already handled uninhabited types"),
+            Variants::Single { index } => assert_eq!(index, variant_index),
+
             Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => {
                 let ptr = self.project_field(bx, tag_field);
                 let to =
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 6cfd1613229..2f0b1cb6d1e 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -65,15 +65,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // We use "tag" to refer to how the discriminant is encoded in memory, which can be either
         // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
         let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout().variants {
+            Variants::Empty => {
+                throw_ub!(UninhabitedEnumVariantRead(None));
+            }
             Variants::Single { index } => {
                 if op.layout().is_uninhabited() {
                     // For consistency with `write_discriminant`, and to make sure that
                     // `project_downcast` cannot fail due to strange layouts, we declare immediate UB
                     // for uninhabited enums.
-                    throw_ub!(UninhabitedEnumVariantRead(None));
+                    throw_ub!(UninhabitedEnumVariantRead(Some(index)));
                 }
                 // Since the type is inhabited, there must be an index.
-                return interp_ok(index.unwrap());
+                return interp_ok(index);
             }
             Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
                 (tag, tag_encoding, tag_field)
@@ -238,6 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
 
         match layout.variants {
+            abi::Variants::Empty => unreachable!("we already handled uninhabited types"),
             abi::Variants::Single { .. } => {
                 // The tag of a `Single` enum is like the tag of the niched
                 // variant: there's no tag as the discriminant is encoded
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 832183b42dc..6f101395ccf 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -302,7 +302,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                     };
                 }
             }
-            Variants::Single { .. } => {}
+            Variants::Single { .. } | Variants::Empty => {}
         }
 
         // Now we know we are projecting to a field, so figure out which one.
@@ -342,10 +342,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                 match layout.variants {
                     Variants::Single { index } => {
                         // Inside a variant
-                        PathElem::Field(
-                            def.variant(index.unwrap()).fields[FieldIdx::from_usize(field)].name,
-                        )
+                        PathElem::Field(def.variant(index).fields[FieldIdx::from_usize(field)].name)
                     }
+                    Variants::Empty => panic!("there is no field in Variants::Empty types"),
                     Variants::Multiple { .. } => bug!("we handled variants above"),
                 }
             }
@@ -1012,7 +1011,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
             }
             // Don't forget potential other variants.
             match &layout.variants {
-                Variants::Single { .. } => {
+                Variants::Single { .. } | Variants::Empty => {
                     // Fully handled above.
                 }
                 Variants::Multiple { variants, .. } => {
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index 76ab0bb544f..3647c109a6e 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -218,8 +218,8 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
                 // recurse with the inner type
                 self.visit_variant(v, idx, &inner)?;
             }
-            // For single-variant layouts, we already did anything there is to do.
-            Variants::Single { .. } => {}
+            // For single-variant layouts, we already did everything there is to do.
+            Variants::Single { .. } | Variants::Empty => {}
         }
 
         interp_ok(())
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 651a797e97c..a729d9325c8 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -155,6 +155,7 @@ fn check_validity_requirement_lax<'tcx>(
     }
 
     match &this.variants {
+        Variants::Empty => return Ok(false),
         Variants::Single { .. } => {
             // All fields of this single variant have already been checked above, there is nothing
             // else to do.
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 5f7b30b5d04..367b0c07f9b 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -734,23 +734,22 @@ where
         let layout = match this.variants {
             Variants::Single { index }
                 // If all variants but one are uninhabited, the variant layout is the enum layout.
-                if index == Some(variant_index) &&
-                // Don't confuse variants of uninhabited enums with the enum itself.
-                // For more details see https://github.com/rust-lang/rust/issues/69763.
-                this.fields != FieldsShape::Primitive =>
+                if index == variant_index =>
             {
                 this.layout
             }
 
-            Variants::Single { index } => {
-                // `Single` variant enums *can* have other variants, but those are uninhabited.
+            Variants::Single { .. } | Variants::Empty => {
+                // Single-variant and no-variant enums *can* have other variants, but those are
+                // uninhabited. Produce a layout that has the right fields for that variant, so that
+                // the rest of the compiler can project fields etc as usual.
 
                 let tcx = cx.tcx();
                 let typing_env = cx.typing_env();
 
                 // Deny calling for_variant more than once for non-Single enums.
                 if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) {
-                    assert_eq!(original_layout.variants, Variants::Single { index });
+                    assert_eq!(original_layout.variants, this.variants);
                 }
 
                 let fields = match this.ty.kind() {
@@ -760,7 +759,7 @@ where
                     _ => bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty),
                 };
                 tcx.mk_layout(LayoutData {
-                    variants: Variants::Single { index: Some(variant_index) },
+                    variants: Variants::Single { index: variant_index },
                     fields: match NonZero::new(fields) {
                         Some(fields) => FieldsShape::Union(fields),
                         None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() },
@@ -777,7 +776,7 @@ where
             Variants::Multiple { ref variants, .. } => cx.tcx().mk_layout(variants[variant_index].clone()),
         };
 
-        assert_eq!(*layout.variants(), Variants::Single { index: Some(variant_index) });
+        assert_eq!(*layout.variants(), Variants::Single { index: variant_index });
 
         TyAndLayout { ty: this.ty, layout }
     }
@@ -904,10 +903,11 @@ where
                 ),
 
                 ty::Coroutine(def_id, args) => match this.variants {
+                    Variants::Empty => unreachable!(),
                     Variants::Single { index } => TyMaybeWithLayout::Ty(
                         args.as_coroutine()
                             .state_tys(def_id, tcx)
-                            .nth(index.unwrap().as_usize())
+                            .nth(index.as_usize())
                             .unwrap()
                             .nth(i)
                             .unwrap(),
@@ -926,10 +926,10 @@ where
                 ty::Adt(def, args) => {
                     match this.variants {
                         Variants::Single { index } => {
-                            let field =
-                                &def.variant(index.unwrap()).fields[FieldIdx::from_usize(i)];
+                            let field = &def.variant(index).fields[FieldIdx::from_usize(i)];
                             TyMaybeWithLayout::Ty(field.ty(tcx, args))
                         }
+                        Variants::Empty => panic!("there is no field in Variants::Empty types"),
 
                         // Discriminant field for enums (where applicable).
                         Variants::Multiple { tag, .. } => {
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 8be5a63d008..490e7dd8f7e 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -216,7 +216,7 @@ impl EnumSizeOpt {
         };
         let layout = tcx.layout_of(typing_env.as_query_input(ty)).ok()?;
         let variants = match &layout.variants {
-            Variants::Single { .. } => return None,
+            Variants::Single { .. } | Variants::Empty => return None,
             Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None,
 
             Variants::Multiple { variants, .. } if variants.len() <= 1 => return None,
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 0ce3955163b..55dcad0680a 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -54,11 +54,11 @@ fn variant_discriminants<'tcx>(
     tcx: TyCtxt<'tcx>,
 ) -> FxHashSet<u128> {
     match &layout.variants {
-        Variants::Single { index: None } => {
+        Variants::Empty => {
             // Uninhabited, no valid discriminant.
             FxHashSet::default()
         }
-        Variants::Single { index: Some(index) } => {
+        Variants::Single { index } => {
             let mut res = FxHashSet::default();
             res.insert(
                 ty.discriminant_for_variant(tcx, *index)
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index 2717f4ab62f..b39a15a8633 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -164,9 +164,10 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         match self {
-            rustc_abi::Variants::Single { index } => VariantsShape::Single {
-                index: index.unwrap_or(rustc_abi::VariantIdx::from_u32(0)).stable(tables),
-            },
+            rustc_abi::Variants::Single { index } => {
+                VariantsShape::Single { index: index.stable(tables) }
+            }
+            rustc_abi::Variants::Empty => VariantsShape::Empty,
             rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => {
                 VariantsShape::Multiple {
                     tag: tag.stable(tables),
diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs
index d1234c3cc91..8bf61cb1337 100644
--- a/compiler/rustc_target/src/callconv/loongarch.rs
+++ b/compiler/rustc_target/src/callconv/loongarch.rs
@@ -116,7 +116,7 @@ where
             FieldsShape::Arbitrary { .. } => {
                 match arg_layout.variants {
                     abi::Variants::Multiple { .. } => return Err(CannotUseFpConv),
-                    abi::Variants::Single { .. } => (),
+                    abi::Variants::Single { .. } | abi::Variants::Empty => (),
                 }
                 for i in arg_layout.fields.index_by_increasing_offset() {
                     let field = arg_layout.field(cx, i);
diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs
index c0298edb5ab..4d858392c97 100644
--- a/compiler/rustc_target/src/callconv/riscv.rs
+++ b/compiler/rustc_target/src/callconv/riscv.rs
@@ -122,7 +122,7 @@ where
             FieldsShape::Arbitrary { .. } => {
                 match arg_layout.variants {
                     abi::Variants::Multiple { .. } => return Err(CannotUseFpConv),
-                    abi::Variants::Single { .. } => (),
+                    abi::Variants::Single { .. } | abi::Variants::Empty => (),
                 }
                 for i in arg_layout.fields.index_by_increasing_offset() {
                     let field = arg_layout.field(cx, i);
diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs
index bd101b23ea1..37aecf323a1 100644
--- a/compiler/rustc_target/src/callconv/x86_64.rs
+++ b/compiler/rustc_target/src/callconv/x86_64.rs
@@ -65,7 +65,7 @@ where
                 }
 
                 match &layout.variants {
-                    abi::Variants::Single { .. } => {}
+                    abi::Variants::Single { .. } | abi::Variants::Empty => {}
                     abi::Variants::Multiple { variants, .. } => {
                         // Treat enum variants like union members.
                         for variant_idx in variants.indices() {
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 049f4734e7b..4cc6292a3ee 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -338,14 +338,11 @@ pub(crate) mod rustc {
                 };
 
             match layout.variants() {
+                Variants::Empty => Ok(Self::uninhabited()),
                 Variants::Single { index } => {
-                    if let Some(index) = index {
-                        // `Variants::Single` on enums with variants denotes that
-                        // the enum delegates its layout to the variant at `index`.
-                        layout_of_variant(*index, None)
-                    } else {
-                        Ok(Self::uninhabited())
-                    }
+                    // `Variants::Single` on enums with variants denotes that
+                    // the enum delegates its layout to the variant at `index`.
+                    layout_of_variant(*index, None)
                 }
                 Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
                     // `Variants::Multiple` denotes an enum with multiple
@@ -498,13 +495,15 @@ pub(crate) mod rustc {
         (ty, layout): (Ty<'tcx>, Layout<'tcx>),
         i: FieldIdx,
     ) -> Ty<'tcx> {
+        // FIXME: Why does this not just use `ty_and_layout_field`?
         match ty.kind() {
             ty::Adt(def, args) => {
                 match layout.variants {
                     Variants::Single { index } => {
-                        let field = &def.variant(index.unwrap()).fields[i];
+                        let field = &def.variant(index).fields[i];
                         field.ty(cx.tcx(), args)
                     }
+                    Variants::Empty => panic!("there is no field in Variants::Empty types"),
                     // Discriminant field for enums (where applicable).
                     Variants::Multiple { tag, .. } => {
                         assert_eq!(i.as_usize(), 0);
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index b393190a493..a3b2ed07d4b 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -339,7 +339,7 @@ fn layout_of_uncached<'tcx>(
             let largest_niche = if count != 0 { element.largest_niche } else { None };
 
             tcx.mk_layout(LayoutData {
-                variants: Variants::Single { index: Some(FIRST_VARIANT) },
+                variants: Variants::Single { index: FIRST_VARIANT },
                 fields: FieldsShape::Array { stride: element.size, count },
                 backend_repr: abi,
                 largest_niche,
@@ -352,7 +352,7 @@ fn layout_of_uncached<'tcx>(
         ty::Slice(element) => {
             let element = cx.layout_of(element)?;
             tcx.mk_layout(LayoutData {
-                variants: Variants::Single { index: Some(FIRST_VARIANT) },
+                variants: Variants::Single { index: FIRST_VARIANT },
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
                 backend_repr: BackendRepr::Memory { sized: false },
                 largest_niche: None,
@@ -363,7 +363,7 @@ fn layout_of_uncached<'tcx>(
             })
         }
         ty::Str => tcx.mk_layout(LayoutData {
-            variants: Variants::Single { index: Some(FIRST_VARIANT) },
+            variants: Variants::Single { index: FIRST_VARIANT },
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
             backend_repr: BackendRepr::Memory { sized: false },
             largest_niche: None,
@@ -534,7 +534,7 @@ fn layout_of_uncached<'tcx>(
             };
 
             tcx.mk_layout(LayoutData {
-                variants: Variants::Single { index: Some(FIRST_VARIANT) },
+                variants: Variants::Single { index: FIRST_VARIANT },
                 fields,
                 backend_repr: abi,
                 largest_niche: e_ly.largest_niche,
@@ -926,7 +926,7 @@ fn coroutine_layout<'tcx>(
                 &ReprOptions::default(),
                 StructKind::Prefixed(prefix_size, prefix_align.abi),
             )?;
-            variant.variants = Variants::Single { index: Some(index) };
+            variant.variants = Variants::Single { index };
 
             let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else {
                 bug!();
@@ -1104,17 +1104,13 @@ fn variant_info_for_adt<'tcx>(
     };
 
     match layout.variants {
+        Variants::Empty => (vec![], None),
+
         Variants::Single { index } => {
-            if let Some(index) = index
-                && layout.fields != FieldsShape::Primitive
-            {
-                debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
-                let variant_def = &adt_def.variant(index);
-                let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
-                (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
-            } else {
-                (vec![], None)
-            }
+            debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
+            let variant_def = &adt_def.variant(index);
+            let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
+            (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
         }
 
         Variants::Multiple { tag, ref tag_encoding, .. } => {
diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs
index 7e2375154c0..8d5403ed324 100644
--- a/compiler/rustc_ty_utils/src/layout/invariant.rs
+++ b/compiler/rustc_ty_utils/src/layout/invariant.rs
@@ -242,15 +242,15 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
     check_layout_abi(cx, layout);
 
     match &layout.variants {
-        Variants::Single { index: None } => {
+        Variants::Empty => {
             assert!(layout.is_uninhabited());
         }
-        Variants::Single { index: Some(idx) } => {
+        Variants::Single { index } => {
             if let Some(variants) = layout.ty.variant_range(tcx) {
-                assert!(variants.contains(idx));
+                assert!(variants.contains(index));
             } else {
                 // Types without variants use `0` as dummy variant index.
-                assert!(idx.as_u32() == 0);
+                assert!(index.as_u32() == 0);
             }
         }
         Variants::Multiple { variants, tag, tag_encoding, .. } => {
diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs
index cf28a0c5885..17e6a852022 100644
--- a/compiler/stable_mir/src/abi.rs
+++ b/compiler/stable_mir/src/abi.rs
@@ -180,8 +180,10 @@ impl FieldsShape {
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
 pub enum VariantsShape {
+    /// A type with no valid variants. Must be uninhabited.
+    Empty,
+
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
-    // FIXME: needs to become `Option` like in the internal type.
     Single { index: VariantIdx },
 
     /// Enum-likes with more than one inhabited variant: each variant comes with
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 1f7c60ad1bd..ef4543dcee8 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -605,7 +605,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                             // `UnsafeCell` action.
                             (self.unsafe_cell_action)(v)
                         }
-                        Variants::Single { .. } => {
+                        Variants::Single { .. } | Variants::Empty => {
                             // Proceed further, try to find where exactly that `UnsafeCell`
                             // is hiding.
                             self.walk_value(v)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index 08026f11c83..0c1f63880cd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -189,7 +189,7 @@ fn layout_of_simd_ty(
     };
 
     Ok(Arc::new(Layout {
-        variants: Variants::Single { index: Some(struct_variant_idx()) },
+        variants: Variants::Single { index: struct_variant_idx() },
         fields,
         backend_repr: BackendRepr::Vector { element: e_abi, count: e_len },
         largest_niche: e_ly.largest_niche,
@@ -305,7 +305,7 @@ pub fn layout_of_ty_query(
             let largest_niche = if count != 0 { element.largest_niche } else { None };
 
             Layout {
-                variants: Variants::Single { index: Some(struct_variant_idx()) },
+                variants: Variants::Single { index: struct_variant_idx() },
                 fields: FieldsShape::Array { stride: element.size, count },
                 backend_repr,
                 largest_niche,
@@ -318,7 +318,7 @@ pub fn layout_of_ty_query(
         TyKind::Slice(element) => {
             let element = db.layout_of_ty(element.clone(), trait_env)?;
             Layout {
-                variants: Variants::Single { index: Some(struct_variant_idx()) },
+                variants: Variants::Single { index: struct_variant_idx() },
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
                 backend_repr: BackendRepr::Memory { sized: false },
                 largest_niche: None,
@@ -329,7 +329,7 @@ pub fn layout_of_ty_query(
             }
         }
         TyKind::Str => Layout {
-            variants: Variants::Single { index: Some(struct_variant_idx()) },
+            variants: Variants::Single { index: struct_variant_idx() },
             fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
             backend_repr: BackendRepr::Memory { sized: false },
             largest_niche: None,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index 9375853e915..e3072d6ee79 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -813,7 +813,7 @@ impl Evaluator<'_> {
                 ProjectionElem::Field(Either::Left(f)) => {
                     let layout = self.layout(&prev_ty)?;
                     let variant_layout = match &layout.variants {
-                        Variants::Single { .. } => &layout,
+                        Variants::Single { .. } | Variants::Empty => &layout,
                         Variants::Multiple { variants, .. } => {
                             &variants[match f.parent {
                                 hir_def::VariantId::EnumVariantId(it) => {
@@ -1638,9 +1638,9 @@ impl Evaluator<'_> {
             return Ok(0);
         };
         match &layout.variants {
+            Variants::Empty => unreachable!(),
             Variants::Single { index } => {
-                let r = self
-                    .const_eval_discriminant(self.db.enum_data(e).variants[index.unwrap().0].0)?;
+                let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?;
                 Ok(r)
             }
             Variants::Multiple { tag, tag_encoding, variants, .. } => {
@@ -1801,7 +1801,7 @@ impl Evaluator<'_> {
         }
         let layout = self.layout_adt(adt, subst)?;
         Ok(match &layout.variants {
-            Variants::Single { .. } => (layout.size.bytes_usize(), layout, None),
+            Variants::Single { .. } | Variants::Empty => (layout.size.bytes_usize(), layout, None),
             Variants::Multiple { variants, tag, tag_encoding, .. } => {
                 let enum_variant_id = match it {
                     VariantId::EnumVariantId(it) => it,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 43ed6a06f42..42e7edaf0f4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -334,8 +334,9 @@ pub(crate) fn detect_variant_from_bytes<'a>(
     e: EnumId,
 ) -> Option<(EnumVariantId, &'a Layout)> {
     let (var_id, var_layout) = match &layout.variants {
+        hir_def::layout::Variants::Empty => unreachable!(),
         hir_def::layout::Variants::Single { index } => {
-            (db.enum_data(e).variants[index.unwrap().0].0, layout)
+            (db.enum_data(e).variants[index.0].0, layout)
         }
         hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
             let size = tag.size(target_data_layout).bytes_usize();
diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr
index aae92bd7dc9..7d384bc875f 100644
--- a/tests/ui/abi/c-zst.aarch64-darwin.stderr
+++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr
index 4ff4a8b90cf..7980710bab6 100644
--- a/tests/ui/abi/c-zst.powerpc-linux.stderr
+++ b/tests/ui/abi/c-zst.powerpc-linux.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr
index 4ff4a8b90cf..7980710bab6 100644
--- a/tests/ui/abi/c-zst.s390x-linux.stderr
+++ b/tests/ui/abi/c-zst.s390x-linux.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr
index 4ff4a8b90cf..7980710bab6 100644
--- a/tests/ui/abi/c-zst.sparc64-linux.stderr
+++ b/tests/ui/abi/c-zst.sparc64-linux.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr
index aae92bd7dc9..7d384bc875f 100644
--- a/tests/ui/abi/c-zst.x86_64-linux.stderr
+++ b/tests/ui/abi/c-zst.x86_64-linux.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
index 4ff4a8b90cf..7980710bab6 100644
--- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
+++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr
index 0cbdf366616..aa51c42c58d 100644
--- a/tests/ui/abi/debug.stderr
+++ b/tests/ui/abi/debug.stderr
@@ -21,9 +21,7 @@ error: fn_abi_of(test) = FnAbi {
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -69,9 +67,7 @@ error: fn_abi_of(test) = FnAbi {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -128,9 +124,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi {
                                },
                            ),
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -167,9 +161,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi {
                        fields: Primitive,
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -218,9 +210,7 @@ error: fn_abi_of(test_generic) = FnAbi {
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -254,9 +244,7 @@ error: fn_abi_of(test_generic) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -304,9 +292,7 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -340,9 +326,7 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -378,9 +362,7 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -414,9 +396,7 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -455,9 +435,7 @@ error: ABIs are not compatible
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -495,9 +473,7 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -530,9 +506,7 @@ error: ABIs are not compatible
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -570,9 +544,7 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -613,9 +585,7 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -649,9 +619,7 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -687,9 +655,7 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -723,9 +689,7 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -767,9 +731,7 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -803,9 +765,7 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -841,9 +801,7 @@ error: ABIs are not compatible
                            fields: Primitive,
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -877,9 +835,7 @@ error: ABIs are not compatible
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
@@ -946,9 +902,7 @@ error: fn_abi_of(assoc_test) = FnAbi {
                                },
                            ),
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -984,9 +938,7 @@ error: fn_abi_of(assoc_test) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr
index 920963c6987..8e1791e27d2 100644
--- a/tests/ui/abi/sysv64-zst.stderr
+++ b/tests/ui/abi/sysv64-zst.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/win64-zst.x86_64-linux.stderr b/tests/ui/abi/win64-zst.x86_64-linux.stderr
index 2752555b4f3..76d90670eb1 100644
--- a/tests/ui/abi/win64-zst.x86_64-linux.stderr
+++ b/tests/ui/abi/win64-zst.x86_64-linux.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr
index 19abb5930b1..7ee90e24744 100644
--- a/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr
+++ b/tests/ui/abi/win64-zst.x86_64-windows-gnu.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -58,9 +56,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr
index 2752555b4f3..76d90670eb1 100644
--- a/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr
+++ b/tests/ui/abi/win64-zst.x86_64-windows-msvc.stderr
@@ -18,9 +18,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                            },
                            largest_niche: None,
                            variants: Single {
-                               index: Some(
-                                   0,
-                               ),
+                               index: 0,
                            },
                            max_repr_align: None,
                            unadjusted_abi_align: $SOME_ALIGN,
@@ -47,9 +45,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: $SOME_ALIGN,
diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr
index 8ae2933c427..bd31665dac1 100644
--- a/tests/ui/layout/debug.stderr
+++ b/tests/ui/layout/debug.stderr
@@ -57,9 +57,7 @@ error: layout_of(E) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -85,9 +83,7 @@ error: layout_of(E) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -138,9 +134,7 @@ error: layout_of(S) = Layout {
            },
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -164,9 +158,7 @@ error: layout_of(U) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -259,9 +251,7 @@ error: layout_of(Result<i32, i32>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -298,9 +288,7 @@ error: layout_of(Result<i32, i32>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -333,9 +321,7 @@ error: layout_of(i32) = Layout {
            fields: Primitive,
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -359,9 +345,7 @@ error: layout_of(V) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(2 bytes),
@@ -385,9 +369,7 @@ error: layout_of(W) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(2 bytes),
@@ -411,9 +393,7 @@ error: layout_of(Y) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(2 bytes),
@@ -437,9 +417,7 @@ error: layout_of(P1) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -463,9 +441,7 @@ error: layout_of(P2) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -489,9 +465,7 @@ error: layout_of(P3) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -515,9 +489,7 @@ error: layout_of(P4) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -546,9 +518,7 @@ error: layout_of(P5) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
@@ -577,9 +547,7 @@ error: layout_of(MaybeUninit<u8>) = Layout {
            ),
            largest_niche: None,
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(1 bytes),
diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr
index a934f270911..59fe667923f 100644
--- a/tests/ui/layout/hexagon-enum.stderr
+++ b/tests/ui/layout/hexagon-enum.stderr
@@ -57,9 +57,7 @@ error: layout_of(A) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -133,9 +131,7 @@ error: layout_of(B) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -209,9 +205,7 @@ error: layout_of(C) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(2 bytes),
@@ -285,9 +279,7 @@ error: layout_of(P) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -361,9 +353,7 @@ error: layout_of(T) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
index 8b4e46de845..ca041fb539b 100644
--- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
+++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr
@@ -79,9 +79,7 @@ error: layout_of(MissingPayloadField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -101,9 +99,7 @@ error: layout_of(MissingPayloadField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -201,9 +197,7 @@ error: layout_of(CommonPayloadField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -240,9 +234,7 @@ error: layout_of(CommonPayloadField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -338,9 +330,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -376,9 +366,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -490,9 +478,7 @@ error: layout_of(NicheFirst) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -512,9 +498,7 @@ error: layout_of(NicheFirst) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -534,9 +518,7 @@ error: layout_of(NicheFirst) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               2,
-                           ),
+                           index: 2,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -648,9 +630,7 @@ error: layout_of(NicheSecond) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -670,9 +650,7 @@ error: layout_of(NicheSecond) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -692,9 +670,7 @@ error: layout_of(NicheSecond) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               2,
-                           ),
+                           index: 2,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr
index 92643445595..bc40a2aa482 100644
--- a/tests/ui/layout/issue-96185-overaligned-enum.stderr
+++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr
@@ -51,9 +51,7 @@ error: layout_of(Aligned1) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -75,9 +73,7 @@ error: layout_of(Aligned1) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -155,9 +151,7 @@ error: layout_of(Aligned2) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: Some(
                            Align(1 bytes),
@@ -179,9 +173,7 @@ error: layout_of(Aligned2) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: Some(
                            Align(1 bytes),
diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr
index f35cf0dab3d..bf043af586b 100644
--- a/tests/ui/layout/thumb-enum.stderr
+++ b/tests/ui/layout/thumb-enum.stderr
@@ -57,9 +57,7 @@ error: layout_of(A) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -133,9 +131,7 @@ error: layout_of(B) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -209,9 +205,7 @@ error: layout_of(C) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(2 bytes),
@@ -285,9 +279,7 @@ error: layout_of(P) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -361,9 +353,7 @@ error: layout_of(T) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr
index 4c6f636b267..d61408098df 100644
--- a/tests/ui/layout/zero-sized-array-enum-niche.stderr
+++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr
@@ -55,9 +55,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -90,9 +88,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -164,9 +160,7 @@ error: layout_of(MultipleAlignments) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(2 bytes),
@@ -190,9 +184,7 @@ error: layout_of(MultipleAlignments) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -225,9 +217,7 @@ error: layout_of(MultipleAlignments) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               2,
-                           ),
+                           index: 2,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -299,9 +289,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -334,9 +322,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -412,9 +398,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -447,9 +431,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
index 08fd4237eeb..64a0cb7f31a 100644
--- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr
@@ -51,9 +51,7 @@ error: layout_of(Univariant) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -135,9 +133,7 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -173,9 +169,7 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
index 473268cac1a..5c4daa6d519 100644
--- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr
@@ -51,9 +51,7 @@ error: layout_of(Univariant) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -135,9 +133,7 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -173,9 +169,7 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
index 08fd4237eeb..64a0cb7f31a 100644
--- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr
@@ -51,9 +51,7 @@ error: layout_of(Univariant) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -135,9 +133,7 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -173,9 +169,7 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
index 08fd4237eeb..64a0cb7f31a 100644
--- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
+++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr
@@ -51,9 +51,7 @@ error: layout_of(Univariant) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -135,9 +133,7 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -173,9 +169,7 @@ error: layout_of(TwoVariants) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr
index 1200f120d37..75005a64523 100644
--- a/tests/ui/repr/repr-c-int-dead-variants.stderr
+++ b/tests/ui/repr/repr-c-int-dead-variants.stderr
@@ -51,9 +51,7 @@ error: layout_of(UnivariantU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -135,9 +133,7 @@ error: layout_of(TwoVariantsU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -173,9 +169,7 @@ error: layout_of(TwoVariantsU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -247,9 +241,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: Some(
                            Align(8 bytes),
@@ -275,9 +267,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(8 bytes),
diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr
index 9954471968d..0eed7c2ce1c 100644
--- a/tests/ui/type/pattern_types/range_patterns.stderr
+++ b/tests/ui/type/pattern_types/range_patterns.stderr
@@ -32,9 +32,7 @@ error: layout_of(NonZero<u32>) = Layout {
                },
            ),
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -71,9 +69,7 @@ error: layout_of((u32) is 1..=) = Layout {
                },
            ),
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),
@@ -137,9 +133,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -178,9 +172,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -249,9 +241,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
                        },
                        largest_niche: None,
                        variants: Single {
-                           index: Some(
-                               0,
-                           ),
+                           index: 0,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(1 bytes),
@@ -290,9 +280,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
                            },
                        ),
                        variants: Single {
-                           index: Some(
-                               1,
-                           ),
+                           index: 1,
                        },
                        max_repr_align: None,
                        unadjusted_abi_align: Align(4 bytes),
@@ -341,9 +329,7 @@ error: layout_of(NonZeroU32New) = Layout {
                },
            ),
            variants: Single {
-               index: Some(
-                   0,
-               ),
+               index: 0,
            },
            max_repr_align: None,
            unadjusted_abi_align: Align(4 bytes),

From 85f01386daef14e107cb87c27fc6271f1f2fa584 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 2 Dec 2024 17:56:18 +0100
Subject: [PATCH 06/14] add comment explaining why ty_and_layout_field is not
 used

Co-authored-by: Jack Wrenn <me@jswrenn.com>
---
 compiler/rustc_transmute/src/layout/tree.rs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 4cc6292a3ee..6ce9969aefe 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -495,7 +495,10 @@ pub(crate) mod rustc {
         (ty, layout): (Ty<'tcx>, Layout<'tcx>),
         i: FieldIdx,
     ) -> Ty<'tcx> {
-        // FIXME: Why does this not just use `ty_and_layout_field`?
+        // We cannot use `ty_and_layout_field` to retrieve the field type, since
+        // `ty_and_layout_field` erases regions in the returned type. We must
+        // not erase regions here, since we may need to ultimately emit outlives
+        // obligations as a consequence of the transmutability analysis.
         match ty.kind() {
             ty::Adt(def, args) => {
                 match layout.variants {

From 397ae3cdf641b8d303ab9d004013f956c2991727 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sat, 7 Dec 2024 18:37:33 +0100
Subject: [PATCH 07/14] fix outdated comment

Co-authored-by: Camille Gillot <gillot.camille@gmail.com>
---
 .../src/debuginfo/metadata/enums/cpp_like.rs                   | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 12a46184d10..23e11748e52 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -213,8 +213,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
         |cx, enum_type_di_node| {
             match enum_type_and_layout.variants {
                 Variants::Empty => {
-                    // Uninhabited enums have Variants::Single. We don't generate
-                    // any members for them.
+                    // We don't generate any members for uninhabited types.
                     return smallvec![];
                 }
                 Variants::Single { index: variant_index } => build_single_variant_union_fields(

From b103347753f69e1ac23ea7b8e393628352cdfb13 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github333195615777966@oli-obk.de>
Date: Thu, 12 Dec 2024 20:07:58 +0000
Subject: [PATCH 08/14] Remove a redundant write_ty call

---
 compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index d6948081505..c3fe716163e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1104,7 +1104,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if let Res::Local(hid) = res {
             let ty = self.local_ty(span, hid);
             let ty = self.normalize(span, ty);
-            self.write_ty(hir_id, ty);
             return (ty, res);
         }
 

From 45920d2f52e7d3025466b6207f78189d0c347d82 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github333195615777966@oli-obk.de>
Date: Thu, 12 Dec 2024 20:17:32 +0000
Subject: [PATCH 09/14] Remove redundant tainting. We already taint the first
 time we set the value

---
 compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index c3fe716163e..2a4914348a9 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -147,13 +147,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut typeck = self.typeck_results.borrow_mut();
         let mut node_ty = typeck.node_types_mut();
         if let Some(ty) = node_ty.get(id)
-            && let Err(e) = ty.error_reported()
+            && ty.references_error()
         {
-            // Do not overwrite nodes that were already marked as `{type error}`. This allows us to
-            // silence unnecessary errors from obligations that were set earlier than a type error
-            // was produced, but that is overwritten by later analysis. This happens in particular
-            // for `Sized` obligations introduced in gather_locals. (#117846)
-            self.set_tainted_by_errors(e);
             return;
         }
 

From 661b8f5694ff1d188172ecb893b71cd5da2f6072 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github333195615777966@oli-obk.de>
Date: Thu, 12 Dec 2024 20:17:32 +0000
Subject: [PATCH 10/14] Forbid overwriting types in typeck

---
 .../rustc_hir_typeck/src/fn_ctxt/_impl.rs     | 20 +++++++++++++------
 .../rustc_hir_typeck/src/fn_ctxt/checks.rs    |  7 ++++---
 .../ui/pattern/slice-pattern-refutable.stderr | 12 ++++++-----
 .../pattern/slice-patterns-ambiguity.stderr   | 14 +++++++------
 4 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 2a4914348a9..364499378b0 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -146,13 +146,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag());
         let mut typeck = self.typeck_results.borrow_mut();
         let mut node_ty = typeck.node_types_mut();
-        if let Some(ty) = node_ty.get(id)
-            && ty.references_error()
-        {
-            return;
-        }
 
-        node_ty.insert(id, ty);
+        if let Some(prev) = node_ty.insert(id, ty) {
+            if prev.references_error() {
+                node_ty.insert(id, prev);
+            } else if !ty.references_error() {
+                // Could change this to a bug, but there's lots of diagnostic code re-lowering
+                // or re-typechecking nodes that were already typecked.
+                // Lots of that diagnostics code relies on subtle effects of re-lowering, so we'll
+                // let it keep doing that and just ensure that compilation won't succeed.
+                self.dcx().span_delayed_bug(
+                    self.tcx.hir().span(id),
+                    format!("`{prev}` overridden by `{ty}` for {id:?} in {:?}", self.body_id),
+                );
+            }
+        }
 
         if let Err(e) = ty.error_reported() {
             self.set_tainted_by_errors(e);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index c1f08d237eb..fffea8f640b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1750,10 +1750,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) {
+    pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) -> Ty<'tcx> {
         // Determine and write the type which we'll check the pattern against.
         let decl_ty = self.local_ty(decl.span, decl.hir_id);
-        self.write_ty(decl.hir_id, decl_ty);
 
         // Type check the initializer.
         if let Some(ref init) = decl.init {
@@ -1785,11 +1784,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             self.diverges.set(previous_diverges);
         }
+        decl_ty
     }
 
     /// Type check a `let` statement.
     fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) {
-        self.check_decl(local.into());
+        let ty = self.check_decl(local.into());
+        self.write_ty(local.hir_id, ty);
         if local.pat.is_never_pattern() {
             self.diverges.set(Diverges::Always {
                 span: local.pat.span,
diff --git a/tests/ui/pattern/slice-pattern-refutable.stderr b/tests/ui/pattern/slice-pattern-refutable.stderr
index df5b58d3e9c..3d9f769d134 100644
--- a/tests/ui/pattern/slice-pattern-refutable.stderr
+++ b/tests/ui/pattern/slice-pattern-refutable.stderr
@@ -1,13 +1,15 @@
 error[E0282]: type annotations needed
-  --> $DIR/slice-pattern-refutable.rs:14:9
+  --> $DIR/slice-pattern-refutable.rs:14:28
    |
 LL |     let [a, b, c] = Zeroes.into() else {
-   |         ^^^^^^^^^
+   |         ---------          ^^^^
+   |         |
+   |         type must be known at this point
    |
-help: consider giving this pattern a type
+help: try using a fully qualified path to specify the expected types
    |
-LL |     let [a, b, c]: /* Type */ = Zeroes.into() else {
-   |                  ++++++++++++
+LL |     let [a, b, c] = <Zeroes as Into<T>>::into(Zeroes) else {
+   |                     ++++++++++++++++++++++++++      ~
 
 error[E0282]: type annotations needed
   --> $DIR/slice-pattern-refutable.rs:21:31
diff --git a/tests/ui/pattern/slice-patterns-ambiguity.stderr b/tests/ui/pattern/slice-patterns-ambiguity.stderr
index 3ef99d0e2d1..690776196ce 100644
--- a/tests/ui/pattern/slice-patterns-ambiguity.stderr
+++ b/tests/ui/pattern/slice-patterns-ambiguity.stderr
@@ -1,13 +1,15 @@
-error[E0282]: type annotations needed for `&_`
-  --> $DIR/slice-patterns-ambiguity.rs:25:9
+error[E0282]: type annotations needed
+  --> $DIR/slice-patterns-ambiguity.rs:25:26
    |
 LL |     let &[a, b] = Zeroes.into() else {
-   |         ^^^^^^^
+   |          ------          ^^^^
+   |          |
+   |          type must be known at this point
    |
-help: consider giving this pattern a type, where the placeholders `_` are specified
+help: try using a fully qualified path to specify the expected types
    |
-LL |     let &[a, b]: &_ = Zeroes.into() else {
-   |                ++++
+LL |     let &[a, b] = <Zeroes as Into<&_>>::into(Zeroes) else {
+   |                   +++++++++++++++++++++++++++      ~
 
 error[E0282]: type annotations needed
   --> $DIR/slice-patterns-ambiguity.rs:32:29

From b0d923c33be9927c66e06b196db4ed98d05e539b Mon Sep 17 00:00:00 2001
From: lcnr <rust@lcnr.de>
Date: Wed, 18 Dec 2024 18:27:26 +0100
Subject: [PATCH 11/14] move lint_unused_mut into subfn

---
 compiler/rustc_borrowck/src/lib.rs | 62 ++++++++++++++++--------------
 1 file changed, 33 insertions(+), 29 deletions(-)

diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 63e20b16f7a..19b5c8689c8 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -334,35 +334,7 @@ fn do_mir_borrowck<'tcx>(
     mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals);
 
     debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
-    let used_mut = std::mem::take(&mut mbcx.used_mut);
-    for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) {
-        let local_decl = &mbcx.body.local_decls[local];
-        let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data {
-            ClearCrossCrate::Set(data) => data.lint_root,
-            _ => continue,
-        };
-
-        // Skip over locals that begin with an underscore or have no name
-        match mbcx.local_names[local] {
-            Some(name) => {
-                if name.as_str().starts_with('_') {
-                    continue;
-                }
-            }
-            None => continue,
-        }
-
-        let span = local_decl.source_info.span;
-        if span.desugaring_kind().is_some() {
-            // If the `mut` arises as part of a desugaring, we should ignore it.
-            continue;
-        }
-
-        let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
-
-        tcx.emit_node_span_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span })
-    }
-
+    mbcx.lint_unused_mut();
     let tainted_by_errors = mbcx.emit_errors();
 
     let result = BorrowCheckResult {
@@ -2390,6 +2362,38 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         // `BasicBlocks` computes dominators on-demand and caches them.
         self.body.basic_blocks.dominators()
     }
+
+    fn lint_unused_mut(&self) {
+        let tcx = self.infcx.tcx;
+        let body = self.body;
+        for local in body.mut_vars_and_args_iter().filter(|local| !self.used_mut.contains(local)) {
+            let local_decl = &body.local_decls[local];
+            let lint_root = match &body.source_scopes[local_decl.source_info.scope].local_data {
+                ClearCrossCrate::Set(data) => data.lint_root,
+                _ => continue,
+            };
+
+            // Skip over locals that begin with an underscore or have no name
+            match self.local_names[local] {
+                Some(name) => {
+                    if name.as_str().starts_with('_') {
+                        continue;
+                    }
+                }
+                None => continue,
+            }
+
+            let span = local_decl.source_info.span;
+            if span.desugaring_kind().is_some() {
+                // If the `mut` arises as part of a desugaring, we should ignore it.
+                continue;
+            }
+
+            let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
+
+            tcx.emit_node_span_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span })
+        }
+    }
 }
 
 mod diags {

From bb1a90f939cf07a717a36af60b9f58f90ede26c0 Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Tue, 17 Dec 2024 22:24:14 +0300
Subject: [PATCH 12/14] reduce compiler `Assemble` complexity

`compile::Assemble` is already complicated by its nature (as it handles core
internals like recursive building logic, etc.) and also handles half of `LldWrapper`
tool logic for no good reason since it should be done in the build step directly.

This change moves it there to reduce complexity of `compile::Assemble` logic.

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/core/build_steps/compile.rs | 25 ++----------
 src/bootstrap/src/core/build_steps/tool.rs    | 39 ++++++++++++++-----
 2 files changed, 34 insertions(+), 30 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 0cacd6e4f37..928023bd60b 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1892,12 +1892,6 @@ impl Step for Assemble {
             });
         }
 
-        let lld_install = if builder.config.lld_enabled {
-            Some(builder.ensure(llvm::Lld { target: target_compiler.host }))
-        } else {
-            None
-        };
-
         let stage = target_compiler.stage;
         let host = target_compiler.host;
         let (host_info, dir_name) = if build_compiler.host == host {
@@ -1958,22 +1952,11 @@ impl Step for Assemble {
 
         copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
 
-        if let Some(lld_install) = lld_install {
-            let src_exe = exe("lld", target_compiler.host);
-            let dst_exe = exe("rust-lld", target_compiler.host);
-            builder.copy_link(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe));
-            let self_contained_lld_dir = libdir_bin.join("gcc-ld");
-            t!(fs::create_dir_all(&self_contained_lld_dir));
-            let lld_wrapper_exe = builder.ensure(crate::core::build_steps::tool::LldWrapper {
-                compiler: build_compiler,
-                target: target_compiler.host,
+        if builder.config.lld_enabled {
+            builder.ensure(crate::core::build_steps::tool::LldWrapper {
+                build_compiler,
+                target_compiler,
             });
-            for name in crate::LLD_FILE_NAMES {
-                builder.copy_link(
-                    &lld_wrapper_exe,
-                    &self_contained_lld_dir.join(exe(name, target_compiler.host)),
-                );
-            }
         }
 
         if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 3cfbef27f87..04f1e10f493 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -1,8 +1,8 @@
 use std::path::PathBuf;
 use std::{env, fs};
 
-use crate::core::build_steps::compile;
 use crate::core::build_steps::toolstate::ToolState;
+use crate::core::build_steps::{compile, llvm};
 use crate::core::builder;
 use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
@@ -722,21 +722,27 @@ impl Step for Cargo {
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct LldWrapper {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
+    pub build_compiler: Compiler,
+    pub target_compiler: Compiler,
 }
 
 impl Step for LldWrapper {
-    type Output = PathBuf;
+    type Output = ();
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         run.never()
     }
 
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
-        builder.ensure(ToolBuild {
-            compiler: self.compiler,
-            target: self.target,
+    fn run(self, builder: &Builder<'_>) {
+        if builder.config.dry_run() {
+            return;
+        }
+
+        let target = self.target_compiler.host;
+
+        let executable = builder.ensure(ToolBuild {
+            compiler: self.build_compiler,
+            target,
             tool: "lld-wrapper",
             mode: Mode::ToolStd,
             path: "src/tools/lld-wrapper",
@@ -744,7 +750,22 @@ impl Step for LldWrapper {
             extra_features: Vec::new(),
             allow_features: "",
             cargo_args: Vec::new(),
-        })
+        });
+
+        let libdir_bin = builder.sysroot_target_bindir(self.target_compiler, target);
+        t!(fs::create_dir_all(&libdir_bin));
+
+        let lld_install = builder.ensure(llvm::Lld { target });
+        let src_exe = exe("lld", target);
+        let dst_exe = exe("rust-lld", target);
+
+        builder.copy_link(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe));
+        let self_contained_lld_dir = libdir_bin.join("gcc-ld");
+        t!(fs::create_dir_all(&self_contained_lld_dir));
+
+        for name in crate::LLD_FILE_NAMES {
+            builder.copy_link(&executable, &self_contained_lld_dir.join(exe(name, target)));
+        }
     }
 }
 

From 1f352acd34cc3d1a50d0c9b5da3b695167aadf04 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 19 Dec 2024 02:31:52 +0000
Subject: [PATCH 13/14] Use TypingEnv from MIR builder

---
 compiler/rustc_mir_build/src/builder/scope.rs | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 882e29de46d..67a0c9c7935 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -1119,10 +1119,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         region_scope: region::Scope,
         local: Local,
     ) {
-        if !self.local_decls[local].ty.has_significant_drop(self.tcx, ty::TypingEnv {
-            typing_mode: ty::TypingMode::non_body_analysis(),
-            param_env: self.param_env,
-        }) {
+        if !self.local_decls[local].ty.has_significant_drop(self.tcx, self.typing_env()) {
             return;
         }
         for scope in self.scopes.scopes.iter_mut().rev() {

From e5e0387cdbc21be09ed39eeaff1a72d3cb2ba389 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 19 Dec 2024 02:28:14 +0000
Subject: [PATCH 14/14] Rename Scope.id to Scope.local_id, remove trivial
 accessor

---
 .../rustc_hir_analysis/src/check/region.rs    | 22 ++++++-------
 compiler/rustc_middle/src/middle/region.rs    | 32 +++++++------------
 compiler/rustc_middle/src/ty/rvalue_scopes.rs |  6 ++--
 .../src/builder/expr/as_temp.rs               |  4 +--
 compiler/rustc_mir_build/src/builder/mod.rs   |  4 +--
 compiler/rustc_mir_build/src/builder/scope.rs |  2 +-
 compiler/rustc_mir_build/src/thir/cx/block.rs |  8 ++---
 compiler/rustc_mir_build/src/thir/cx/expr.rs  | 16 +++++++---
 8 files changed, 45 insertions(+), 49 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index b9cb48cafdc..ca6729a5bbd 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -129,7 +129,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
                     let mut prev_cx = visitor.cx;
 
                     visitor.enter_scope(Scope {
-                        id: blk.hir_id.local_id,
+                        local_id: blk.hir_id.local_id,
                         data: ScopeData::Remainder(FirstStatementIndex::new(i)),
                     });
                     visitor.cx.var_parent = visitor.cx.parent;
@@ -154,7 +154,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
                     // the first such subscope, which has the block itself as a
                     // parent.
                     visitor.enter_scope(Scope {
-                        id: blk.hir_id.local_id,
+                        local_id: blk.hir_id.local_id,
                         data: ScopeData::Remainder(FirstStatementIndex::new(i)),
                     });
                     visitor.cx.var_parent = visitor.cx.parent;
@@ -184,7 +184,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
                 visitor
                     .scope_tree
                     .backwards_incompatible_scope
-                    .insert(local_id, Scope { id: local_id, data: ScopeData::Node });
+                    .insert(local_id, Scope { local_id, data: ScopeData::Node });
             }
             visitor.visit_expr(tail_expr);
         }
@@ -221,7 +221,7 @@ fn resolve_arm<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, arm: &'tcx hir
 }
 
 fn resolve_pat<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
-    visitor.record_child_scope(Scope { id: pat.hir_id.local_id, data: ScopeData::Node });
+    visitor.record_child_scope(Scope { local_id: pat.hir_id.local_id, data: ScopeData::Node });
 
     // If this is a binding then record the lifetime of that binding.
     if let PatKind::Binding(..) = pat.kind {
@@ -485,7 +485,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
             } else {
                 ScopeData::IfThen
             };
-            visitor.enter_scope(Scope { id: then.hir_id.local_id, data });
+            visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data });
             visitor.cx.var_parent = visitor.cx.parent;
             visitor.visit_expr(cond);
             visitor.visit_expr(then);
@@ -500,7 +500,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
             } else {
                 ScopeData::IfThen
             };
-            visitor.enter_scope(Scope { id: then.hir_id.local_id, data });
+            visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data });
             visitor.cx.var_parent = visitor.cx.parent;
             visitor.visit_expr(cond);
             visitor.visit_expr(then);
@@ -516,7 +516,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
 
     if let hir::ExprKind::Yield(_, source) = &expr.kind {
         // Mark this expr's scope and all parent scopes as containing `yield`.
-        let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node };
+        let mut scope = Scope { local_id: expr.hir_id.local_id, data: ScopeData::Node };
         loop {
             let span = match expr.kind {
                 hir::ExprKind::Yield(expr, hir::YieldSource::Await { .. }) => {
@@ -803,9 +803,9 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
         // account for the destruction scope representing the scope of
         // the destructors that run immediately after it completes.
         if self.terminating_scopes.contains(&id) {
-            self.enter_scope(Scope { id, data: ScopeData::Destruction });
+            self.enter_scope(Scope { local_id: id, data: ScopeData::Destruction });
         }
-        self.enter_scope(Scope { id, data: ScopeData::Node });
+        self.enter_scope(Scope { local_id: id, data: ScopeData::Node });
     }
 
     fn enter_body(&mut self, hir_id: hir::HirId, f: impl FnOnce(&mut Self)) {
@@ -822,8 +822,8 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
         let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false);
         self.terminating_scopes.insert(hir_id.local_id);
 
-        self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::CallSite });
-        self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::Arguments });
+        self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::CallSite });
+        self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::Arguments });
 
         f(self);
 
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 114211b27c1..66861519e17 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -84,23 +84,23 @@ use crate::ty::TyCtxt;
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct Scope {
-    pub id: hir::ItemLocalId,
+    pub local_id: hir::ItemLocalId,
     pub data: ScopeData,
 }
 
 impl fmt::Debug for Scope {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.data {
-            ScopeData::Node => write!(fmt, "Node({:?})", self.id),
-            ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.id),
-            ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id),
-            ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id),
-            ScopeData::IfThen => write!(fmt, "IfThen({:?})", self.id),
-            ScopeData::IfThenRescope => write!(fmt, "IfThen[edition2024]({:?})", self.id),
+            ScopeData::Node => write!(fmt, "Node({:?})", self.local_id),
+            ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.local_id),
+            ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.local_id),
+            ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.local_id),
+            ScopeData::IfThen => write!(fmt, "IfThen({:?})", self.local_id),
+            ScopeData::IfThenRescope => write!(fmt, "IfThen[edition2024]({:?})", self.local_id),
             ScopeData::Remainder(fsi) => write!(
                 fmt,
                 "Remainder {{ block: {:?}, first_statement_index: {}}}",
-                self.id,
+                self.local_id,
                 fsi.as_u32(),
             ),
         }
@@ -164,18 +164,8 @@ rustc_index::newtype_index! {
 rustc_data_structures::static_assert_size!(ScopeData, 4);
 
 impl Scope {
-    /// Returns an item-local ID associated with this scope.
-    ///
-    /// N.B., likely to be replaced as API is refined; e.g., pnkfelix
-    /// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
-    pub fn item_local_id(&self) -> hir::ItemLocalId {
-        self.id
-    }
-
     pub fn hir_id(&self, scope_tree: &ScopeTree) -> Option<HirId> {
-        scope_tree
-            .root_body
-            .map(|hir_id| HirId { owner: hir_id.owner, local_id: self.item_local_id() })
+        scope_tree.root_body.map(|hir_id| HirId { owner: hir_id.owner, local_id: self.local_id })
     }
 
     /// Returns the span of this `Scope`. Note that in general the
@@ -350,7 +340,7 @@ impl ScopeTree {
 
     pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) {
         debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
-        assert!(var != lifetime.item_local_id());
+        assert!(var != lifetime.local_id);
         self.var_map.insert(var, lifetime);
     }
 
@@ -359,7 +349,7 @@ impl ScopeTree {
         match &candidate_type {
             RvalueCandidateType::Borrow { lifetime: Some(lifetime), .. }
             | RvalueCandidateType::Pattern { lifetime: Some(lifetime), .. } => {
-                assert!(var.local_id != lifetime.item_local_id())
+                assert!(var.local_id != lifetime.local_id)
             }
             _ => {}
         }
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index 57c2d7623d2..b00c8169a36 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -35,7 +35,7 @@ impl RvalueScopes {
         // if there's one. Static items, for instance, won't
         // have an enclosing scope, hence no scope will be
         // returned.
-        let mut id = Scope { id: expr_id, data: ScopeData::Node };
+        let mut id = Scope { local_id: expr_id, data: ScopeData::Node };
         let mut backwards_incompatible = None;
 
         while let Some(&(p, _)) = region_scope_tree.parent_map.get(&id) {
@@ -60,7 +60,7 @@ impl RvalueScopes {
                     if backwards_incompatible.is_none() {
                         backwards_incompatible = region_scope_tree
                             .backwards_incompatible_scope
-                            .get(&p.item_local_id())
+                            .get(&p.local_id)
                             .copied();
                     }
                     id = p
@@ -76,7 +76,7 @@ impl RvalueScopes {
     pub fn record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: Option<Scope>) {
         debug!("record_rvalue_scope(var={var:?}, lifetime={lifetime:?})");
         if let Some(lifetime) = lifetime {
-            assert!(var != lifetime.item_local_id());
+            assert!(var != lifetime.local_id);
         }
         self.map.insert(var, lifetime);
     }
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs
index 5e3a24e18fb..2927f5b0c45 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs
@@ -75,11 +75,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     LocalInfo::BlockTailTemp(tail_info)
                 }
 
-                _ if let Some(Scope { data: ScopeData::IfThenRescope, id }) =
+                _ if let Some(Scope { data: ScopeData::IfThenRescope, local_id }) =
                     temp_lifetime.temp_lifetime =>
                 {
                     LocalInfo::IfThenRescopeTemp {
-                        if_then: HirId { owner: this.hir_id.owner, local_id: id },
+                        if_then: HirId { owner: this.hir_id.owner, local_id },
                     }
                 }
 
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index fdd951c8899..0a60899248a 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -531,9 +531,9 @@ fn construct_fn<'tcx>(
     );
 
     let call_site_scope =
-        region::Scope { id: body.id().hir_id.local_id, data: region::ScopeData::CallSite };
+        region::Scope { local_id: body.id().hir_id.local_id, data: region::ScopeData::CallSite };
     let arg_scope =
-        region::Scope { id: body.id().hir_id.local_id, data: region::ScopeData::Arguments };
+        region::Scope { local_id: body.id().hir_id.local_id, data: region::ScopeData::Arguments };
     let source_info = builder.source_info(span);
     let call_site_s = (call_site_scope, source_info);
     let _: BlockAnd<()> = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 67a0c9c7935..d0febcca451 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -89,7 +89,7 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{ExprId, LintLevel};
-use rustc_middle::{bug, span_bug, ty};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint::Level;
 use rustc_span::source_map::Spanned;
 use rustc_span::{DUMMY_SP, Span};
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index 069c2e7881e..c9df027687a 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -16,7 +16,7 @@ impl<'tcx> Cx<'tcx> {
         let block = Block {
             targeted_by_break: block.targeted_by_break,
             region_scope: region::Scope {
-                id: block.hir_id.local_id,
+                local_id: block.hir_id.local_id,
                 data: region::ScopeData::Node,
             },
             span: block.span,
@@ -51,7 +51,7 @@ impl<'tcx> Cx<'tcx> {
                         let stmt = Stmt {
                             kind: StmtKind::Expr {
                                 scope: region::Scope {
-                                    id: hir_id.local_id,
+                                    local_id: hir_id.local_id,
                                     data: region::ScopeData::Node,
                                 },
                                 expr: self.mirror_expr(expr),
@@ -65,7 +65,7 @@ impl<'tcx> Cx<'tcx> {
                     }
                     hir::StmtKind::Let(local) => {
                         let remainder_scope = region::Scope {
-                            id: block_id,
+                            local_id: block_id,
                             data: region::ScopeData::Remainder(region::FirstStatementIndex::new(
                                 index,
                             )),
@@ -108,7 +108,7 @@ impl<'tcx> Cx<'tcx> {
                             kind: StmtKind::Let {
                                 remainder_scope,
                                 init_scope: region::Scope {
-                                    id: hir_id.local_id,
+                                    local_id: hir_id.local_id,
                                     data: region::ScopeData::Node,
                                 },
                                 pattern,
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index ae49b266153..0338ac674e5 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -45,7 +45,7 @@ impl<'tcx> Cx<'tcx> {
     #[instrument(level = "trace", skip(self, hir_expr))]
     pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId {
         let expr_scope =
-            region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
+            region::Scope { local_id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
 
         trace!(?hir_expr.hir_id, ?hir_expr.span);
 
@@ -814,14 +814,20 @@ impl<'tcx> Cx<'tcx> {
             hir::ExprKind::Become(call) => ExprKind::Become { value: self.mirror_expr(call) },
             hir::ExprKind::Break(dest, ref value) => match dest.target_id {
                 Ok(target_id) => ExprKind::Break {
-                    label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
+                    label: region::Scope {
+                        local_id: target_id.local_id,
+                        data: region::ScopeData::Node,
+                    },
                     value: value.map(|value| self.mirror_expr(value)),
                 },
                 Err(err) => bug!("invalid loop id for break: {}", err),
             },
             hir::ExprKind::Continue(dest) => match dest.target_id {
                 Ok(loop_id) => ExprKind::Continue {
-                    label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node },
+                    label: region::Scope {
+                        local_id: loop_id.local_id,
+                        data: region::ScopeData::Node,
+                    },
                 },
                 Err(err) => bug!("invalid loop id for continue: {}", err),
             },
@@ -831,7 +837,7 @@ impl<'tcx> Cx<'tcx> {
             },
             hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
                 if_then_scope: region::Scope {
-                    id: then.hir_id.local_id,
+                    local_id: then.hir_id.local_id,
                     data: {
                         if expr.span.at_least_rust_2024() {
                             region::ScopeData::IfThenRescope
@@ -1021,7 +1027,7 @@ impl<'tcx> Cx<'tcx> {
             guard: arm.guard.as_ref().map(|g| self.mirror_expr(g)),
             body: self.mirror_expr(arm.body),
             lint_level: LintLevel::Explicit(arm.hir_id),
-            scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
+            scope: region::Scope { local_id: arm.hir_id.local_id, data: region::ScopeData::Node },
             span: arm.span,
         };
         self.thir.arms.push(arm)