From d21aa86c652c523f6b39e53866690a1d89d97f15 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <39484203+jieyouxu@users.noreply.github.com>
Date: Sun, 13 Oct 2024 19:11:58 +0800
Subject: [PATCH 01/15] unicode-table-generator: match bin name with tool name

Bootstrap assumes that the binary name is the same as tool name, just
makes everyone's lives easier.
---
 Cargo.lock                                   | 14 +++++++-------
 src/tools/unicode-table-generator/Cargo.toml |  2 +-
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index c62c379f70d7b..33e855bccc1e3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5584,13 +5584,6 @@ dependencies = [
  "version_check",
 ]
 
-[[package]]
-name = "unicode-bdd"
-version = "0.1.0"
-dependencies = [
- "ucd-parse",
-]
-
 [[package]]
 name = "unicode-bidi"
 version = "0.3.15"
@@ -5640,6 +5633,13 @@ version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
 
+[[package]]
+name = "unicode-table-generator"
+version = "0.1.0"
+dependencies = [
+ "ucd-parse",
+]
+
 [[package]]
 name = "unicode-width"
 version = "0.1.14"
diff --git a/src/tools/unicode-table-generator/Cargo.toml b/src/tools/unicode-table-generator/Cargo.toml
index ef01877c0b94b..f8a500922d052 100644
--- a/src/tools/unicode-table-generator/Cargo.toml
+++ b/src/tools/unicode-table-generator/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "unicode-bdd"
+name = "unicode-table-generator"
 version = "0.1.0"
 edition = "2021"
 

From 3748c5eecf5e2884f469132e2ba46f782c671a26 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <39484203+jieyouxu@users.noreply.github.com>
Date: Sun, 13 Oct 2024 19:13:38 +0800
Subject: [PATCH 02/15] bootstrap: register `src/tools/unicode-table-generator`
 as a runnable tool

---
 src/bootstrap/src/core/build_steps/run.rs  | 22 ++++++++++++++++++++++
 src/bootstrap/src/core/build_steps/tool.rs |  1 +
 src/bootstrap/src/core/builder.rs          |  1 +
 3 files changed, 24 insertions(+)

diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index c7bcd76caddb9..a6dff7fde8054 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -283,3 +283,25 @@ impl Step for GenerateCompletions {
         run.builder.ensure(GenerateCompletions);
     }
 }
+
+#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
+pub struct UnicodeTableGenerator;
+
+impl Step for UnicodeTableGenerator {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/unicode-table-generator")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(UnicodeTableGenerator);
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        let mut cmd = builder.tool_cmd(Tool::UnicodeTableGenerator);
+        cmd.arg(builder.src.join("library/core/src/unicode/unicode_data.rs"));
+        cmd.run(builder);
+    }
+}
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index a01497c2bb98a..0d2ffd1c08dc7 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -360,6 +360,7 @@ bootstrap_tool!(
     CoverageDump, "src/tools/coverage-dump", "coverage-dump";
     RustcPerfWrapper, "src/tools/rustc-perf-wrapper", "rustc-perf-wrapper";
     WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
+    UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
 );
 
 /// These are the submodules that are required for rustbook to work due to
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 9ac0b0a01f7ee..2b82e6c569c0b 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -1010,6 +1010,7 @@ impl<'a> Builder<'a> {
                 run::GenerateCopyright,
                 run::GenerateWindowsSys,
                 run::GenerateCompletions,
+                run::UnicodeTableGenerator,
             ),
             Kind::Setup => {
                 describe!(setup::Profile, setup::Hook, setup::Link, setup::Editor)

From 75a9c86a7786e72dd432bbef1e3bf99f25654496 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <39484203+jieyouxu@users.noreply.github.com>
Date: Sun, 13 Oct 2024 19:33:10 +0800
Subject: [PATCH 03/15] unicode-table-generator: sync comments

These comments were updated on master but not through this tool, so the
comments in the tool became outdated. Sync the comments to stay
consistent.
---
 src/tools/unicode-table-generator/src/range_search.rs | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs
index 3a5b869f72f76..221e5d75ef568 100644
--- a/src/tools/unicode-table-generator/src/range_search.rs
+++ b/src/tools/unicode-table-generator/src/range_search.rs
@@ -16,16 +16,14 @@ const fn bitset_search<
     let bucket_idx = (needle / 64) as usize;
     let chunk_map_idx = bucket_idx / CHUNK_SIZE;
     let chunk_piece = bucket_idx % CHUNK_SIZE;
-    // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
-    // feature stabilizes.
+    // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const.
     let chunk_idx = if chunk_map_idx < chunk_idx_map.len() {
         chunk_idx_map[chunk_map_idx]
     } else {
         return false;
     };
     let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize;
-    // FIXME: const-hack: Revert to `slice::get` after `const_slice_index`
-    // feature stabilizes.
+    // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const.
     let word = if idx < bitset_canonical.len() {
         bitset_canonical[idx]
     } else {

From be89da5ab5b4e01cead1219ac7d68ac93751e69b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <39484203+jieyouxu@users.noreply.github.com>
Date: Sun, 13 Oct 2024 19:45:25 +0800
Subject: [PATCH 04/15] triagebot: add reminder for
 `library/core/src/unicode/unicode_data.rs` that it needs to be generated by
 tool

And should not be directly edited.
---
 triagebot.toml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/triagebot.toml b/triagebot.toml
index 60ec1043aadb3..b3f6a94d7f40a 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -674,6 +674,15 @@ instead.
 """
 cc = ["@calebzulawski", "@programmerjake"]
 
+[mentions."library/core/src/unicode/unicode_data.rs"]
+message = """
+`library/core/src/unicode/unicode_data.rs` is generated by
+`src/tools/unicode-table-generator` via `./x run
+src/tools/unicode-table-generator`. If you want to modify `unicode_data.rs`,
+please modify the tool then regenerate the library source file with the tool
+instead of editing the library source file manually.
+"""
+
 [mentions."src/librustdoc/clean/types.rs"]
 cc = ["@camelid"]
 

From f5577a8174685aca342b9189e625648f25a23a20 Mon Sep 17 00:00:00 2001
From: Giang Dao <dtrnggiang@gmail.com>
Date: Mon, 7 Oct 2024 19:07:57 +0800
Subject: [PATCH 05/15] fix missing rustfmt and clippy for msi

---
 src/bootstrap/src/core/build_steps/dist.rs | 31 +++++++++++++++-
 src/etc/installer/msi/rust.wxs             | 41 +++++++++++++++++++++-
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 90e6a10d9d685..cf8ed11c6b090 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1633,6 +1633,8 @@ impl Step for Extended {
                     "rust-analyzer-preview".to_string()
                 } else if name == "clippy" {
                     "clippy-preview".to_string()
+                } else if name == "rustfmt" {
+                    "rustfmt-preview".to_string()
                 } else if name == "miri" {
                     "miri-preview".to_string()
                 } else if name == "rustc-codegen-cranelift" {
@@ -1652,7 +1654,7 @@ impl Step for Extended {
             prepare("cargo");
             prepare("rust-analysis");
             prepare("rust-std");
-            for tool in &["clippy", "rust-analyzer", "rust-docs", "miri"] {
+            for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1770,6 +1772,24 @@ impl Step for Extended {
                     .arg(etc.join("msi/remove-duplicates.xsl"))
                     .run(builder);
             }
+            if built_tools.contains("rustfmt") {
+                command(&heat)
+                    .current_dir(&exe)
+                    .arg("dir")
+                    .arg("rustfmt")
+                    .args(heat_flags)
+                    .arg("-cg")
+                    .arg("RustFmtGroup")
+                    .arg("-dr")
+                    .arg("RustFmt")
+                    .arg("-var")
+                    .arg("var.RustFmtDir")
+                    .arg("-out")
+                    .arg(exe.join("RustFmtGroup.wxs"))
+                    .arg("-t")
+                    .arg(etc.join("msi/remove-duplicates.xsl"))
+                    .run(builder);
+            }
             if built_tools.contains("miri") {
                 command(&heat)
                     .current_dir(&exe)
@@ -1841,6 +1861,9 @@ impl Step for Extended {
                 if built_tools.contains("clippy") {
                     cmd.arg("-dClippyDir=clippy");
                 }
+                if built_tools.contains("rustfmt") {
+                    cmd.arg("-dRustFmtDir=rustfmt");
+                }
                 if built_tools.contains("rust-docs") {
                     cmd.arg("-dDocsDir=rust-docs");
                 }
@@ -1867,6 +1890,9 @@ impl Step for Extended {
             if built_tools.contains("clippy") {
                 candle("ClippyGroup.wxs".as_ref());
             }
+            if built_tools.contains("rustfmt") {
+                candle("RustFmtGroup.wxs".as_ref());
+            }
             if built_tools.contains("miri") {
                 candle("MiriGroup.wxs".as_ref());
             }
@@ -1905,6 +1931,9 @@ impl Step for Extended {
             if built_tools.contains("clippy") {
                 cmd.arg("ClippyGroup.wixobj");
             }
+            if built_tools.contains("rustfmt") {
+                cmd.arg("RustFmtGroup.wixobj");
+            }
             if built_tools.contains("miri") {
                 cmd.arg("MiriGroup.wixobj");
             }
diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs
index f29e1e4d27a27..2d155bf0b1019 100644
--- a/src/etc/installer/msi/rust.wxs
+++ b/src/etc/installer/msi/rust.wxs
@@ -172,6 +172,11 @@
                     <!-- tool-rust-docs-end -->
                     <Directory Id="Cargo" Name="." />
                     <Directory Id="Std" Name="." />
+                    <Directory Id="RustFmt" Name="." />
+                    <Directory Id="RustAnalyzer" Name="." />
+                    <Directory Id="Miri" Name="." />
+                    <Directory Id="Analysis" Name="." />
+                    <Directory Id="Clippy" Name="." />
                 </Directory>
             </Directory>
 
@@ -279,7 +284,41 @@
                  <ComponentRef Id="PathEnvPerMachine" />
                  <ComponentRef Id="PathEnvPerUser" />
         </Feature>
-
+        <Feature Id="RustFmt"
+                 Title="Formatter for rust"
+                 Display="7"
+                 Level="1"
+                 AllowAdvertise="no">
+                 <ComponentGroupRef Id="RustFmtGroup" />
+        </Feature>
+        <Feature Id="Clippy"
+                 Title="Formatter and checker for rust"
+                 Display="8"
+                 Level="1"
+                 AllowAdvertise="no">
+                 <ComponentGroupRef Id="ClippyGroup" />
+        </Feature>
+        <Feature Id="Miri"
+                 Title="Soundness checker for rust"
+                 Display="9"
+                 Level="1"
+                 AllowAdvertise="no">
+                 <ComponentGroupRef Id="MiriGroup" />
+        </Feature>
+        <Feature Id="RustAnalyzer"
+                 Title="Analyzer for rust"
+                 Display="10"
+                 Level="1"
+                 AllowAdvertise="no">
+                 <ComponentGroupRef Id="RustAnalyzerGroup" />
+        </Feature>
+        <Feature Id="Analysis"
+                 Title="Analysis for rust"
+                 Display="11"
+                 Level="1"
+                 AllowAdvertise="no">
+                 <ComponentGroupRef Id="AnalysisGroup" />
+        </Feature>
         <UIRef Id="RustUI" />
     </Product>
 </Wix>

From 2316749ca954030afed6145342808a8c1ae29fac Mon Sep 17 00:00:00 2001
From: Giang Dao <dtrnggiang@gmail.com>
Date: Mon, 7 Oct 2024 19:10:18 +0800
Subject: [PATCH 06/15] fix missing rustfmt for apple darwin

---
 src/bootstrap/src/core/build_steps/dist.rs | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index cf8ed11c6b090..80ba9f4444863 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1591,9 +1591,15 @@ impl Step for Extended {
             prepare("cargo");
             prepare("rust-std");
             prepare("rust-analysis");
-            prepare("clippy");
-            prepare("rust-analyzer");
-            for tool in &["rust-docs", "miri", "rustc-codegen-cranelift"] {
+
+            for tool in &[
+                "clippy",
+                "rustfmt",
+                "rust-analyzer",
+                "rust-docs",
+                "miri",
+                "rustc-codegen-cranelift",
+            ] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }

From e78d78868a4c9a4e29a02f70ede75ca8cfd39bef Mon Sep 17 00:00:00 2001
From: Noratrieb <48135649+Noratrieb@users.noreply.github.com>
Date: Thu, 17 Oct 2024 19:34:04 +0200
Subject: [PATCH 07/15] Allow `#[deny(..)]` inside `#[forbid(..)]` as a no-op
 with a warning

Forbid cannot be overriden. When someome tries to do this anyways,
it results in a hard error. That makes sense.

Except it doesn't, because macros. Macros may reasonably use `#[deny]`
in their expansion to assert
that their expanded code follows the lint. This is doesn't work when the
output gets expanded into a `forbid()` context. This is pretty silly,
since both the macros and the code agree on the lint!

Therefore, we allow `#[deny(..)]`ing a lint that's already forbidden,
keeping the level at forbid.
---
 compiler/rustc_lint/src/levels.rs             |  5 ++-
 compiler/rustc_lint_defs/src/builtin.rs       |  2 +-
 src/tools/tidy/src/issues.txt                 |  1 -
 tests/ui/lint/auxiliary/deny-macro.rs         |  7 ++++
 tests/ui/lint/deny-inside-forbid-ignored.rs   | 16 +++++++++
 .../ui/lint/deny-inside-forbid-ignored.stderr | 35 +++++++++++++++++++
 tests/ui/lint/forbid-macro-with-deny.rs       | 16 +++++++++
 ...0819-dont-override-forbid-in-same-scope.rs |  4 +--
 ...-dont-override-forbid-in-same-scope.stderr |  5 +--
 tests/ui/lint/issue-80988.rs                  | 10 ------
 tests/ui/lint/issue-80988.stderr              | 15 --------
 11 files changed, 84 insertions(+), 32 deletions(-)
 create mode 100644 tests/ui/lint/auxiliary/deny-macro.rs
 create mode 100644 tests/ui/lint/deny-inside-forbid-ignored.rs
 create mode 100644 tests/ui/lint/deny-inside-forbid-ignored.stderr
 create mode 100644 tests/ui/lint/forbid-macro-with-deny.rs
 delete mode 100644 tests/ui/lint/issue-80988.rs
 delete mode 100644 tests/ui/lint/issue-80988.stderr

diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 89a67fc0d8988..95a8e7625ff48 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -493,7 +493,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
         //
         // This means that this only errors if we're truly lowering the lint
         // level from forbid.
-        if self.lint_added_lints && level != Level::Forbid && old_level == Level::Forbid {
+        if self.lint_added_lints && level == Level::Deny && old_level == Level::Forbid {
+            // Having a deny inside a forbid is fine and is ignored, so we skip this check.
+            return;
+        } else if self.lint_added_lints && level != Level::Forbid && old_level == Level::Forbid {
             // Backwards compatibility check:
             //
             // We used to not consider `forbid(lint_group)`
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 45a5ce0ca20e9..c11571182fe21 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -156,7 +156,7 @@ declare_lint! {
     ///
     /// ```rust
     /// #![forbid(warnings)]
-    /// #![deny(bad_style)]
+    /// #![warn(bad_style)]
     ///
     /// fn main() {}
     /// ```
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 22126674c156b..97c42752c12dd 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -2758,7 +2758,6 @@ ui/lint/issue-63364.rs
 ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs
 ui/lint/issue-79546-fuel-ice.rs
 ui/lint/issue-79744.rs
-ui/lint/issue-80988.rs
 ui/lint/issue-81218.rs
 ui/lint/issue-83477.rs
 ui/lint/issue-87274-paren-parent.rs
diff --git a/tests/ui/lint/auxiliary/deny-macro.rs b/tests/ui/lint/auxiliary/deny-macro.rs
new file mode 100644
index 0000000000000..6106cd0ef1750
--- /dev/null
+++ b/tests/ui/lint/auxiliary/deny-macro.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+macro_rules! emit_deny {
+    () => {
+        #[deny(unsafe_code)]
+        let _so_safe = 0;
+    };
+}
diff --git a/tests/ui/lint/deny-inside-forbid-ignored.rs b/tests/ui/lint/deny-inside-forbid-ignored.rs
new file mode 100644
index 0000000000000..da5a14ce25334
--- /dev/null
+++ b/tests/ui/lint/deny-inside-forbid-ignored.rs
@@ -0,0 +1,16 @@
+/// Ensure that using deny inside forbid is treated as a no-op,
+/// and does not override the level to deny.
+
+#[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+fn main() {
+    #[deny(unsafe_code)] // m-m-maybe we can have unsafe code in here?
+    {
+        #[allow(unsafe_code)] // let's have some unsafe code in here
+        //~^ ERROR allow(unsafe_code) incompatible with previous forbid
+        //~| ERROR allow(unsafe_code) incompatible with previous forbid
+        {
+            unsafe { /* ≽^•⩊•^≼ */ }
+            //~^ ERROR usage of an `unsafe` block
+        }
+    }
+}
diff --git a/tests/ui/lint/deny-inside-forbid-ignored.stderr b/tests/ui/lint/deny-inside-forbid-ignored.stderr
new file mode 100644
index 0000000000000..b7fc0ccf5a23f
--- /dev/null
+++ b/tests/ui/lint/deny-inside-forbid-ignored.stderr
@@ -0,0 +1,35 @@
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+  --> $DIR/deny-inside-forbid-ignored.rs:8:17
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ----------- `forbid` level set here
+...
+LL |         #[allow(unsafe_code)] // let's have some unsafe code in here
+   |                 ^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+  --> $DIR/deny-inside-forbid-ignored.rs:8:17
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ----------- `forbid` level set here
+...
+LL |         #[allow(unsafe_code)] // let's have some unsafe code in here
+   |                 ^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: usage of an `unsafe` block
+  --> $DIR/deny-inside-forbid-ignored.rs:12:13
+   |
+LL |             unsafe { /* ≽^•⩊•^≼ */ }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deny-inside-forbid-ignored.rs:4:10
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/tests/ui/lint/forbid-macro-with-deny.rs b/tests/ui/lint/forbid-macro-with-deny.rs
new file mode 100644
index 0000000000000..e6985ab19d166
--- /dev/null
+++ b/tests/ui/lint/forbid-macro-with-deny.rs
@@ -0,0 +1,16 @@
+//@ aux-build:deny-macro.rs
+//@ check-pass
+
+// Ensure that when a macro (or normal code) does #[deny] inside a #[forbid]
+// context, no error is emitted, as both parties agree on the treatment of the lint.
+
+#![forbid(unsafe_code)]
+
+extern crate deny_macro;
+
+fn main() {
+    deny_macro::emit_deny! {}
+
+    #[deny(unsafe_code)]
+    let _ = 0;
+}
diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs
index 37d9612931717..45b78d75b2749 100644
--- a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs
+++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs
@@ -19,9 +19,9 @@
 fn forbid_first(num: i32) -> i32 {
     #![forbid(unused)]
     #![deny(unused)]
-    //~^ ERROR: deny(unused) incompatible with previous forbid
-    //~| WARNING being phased out
     #![warn(unused)]
+    //~^ ERROR: warn(unused) incompatible with previous forbid
+    //~| WARNING being phased out
     #![allow(unused)]
 
     num * num
diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
index f78bf899b848c..407eaf1c60a77 100644
--- a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
+++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
@@ -1,9 +1,10 @@
-error: deny(unused) incompatible with previous forbid
-  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
    |
 LL |     #![forbid(unused)]
    |               ------ `forbid` level set here
 LL |     #![deny(unused)]
+LL |     #![warn(unused)]
    |             ^^^^^^ overruled by previous forbid
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
diff --git a/tests/ui/lint/issue-80988.rs b/tests/ui/lint/issue-80988.rs
deleted file mode 100644
index 80decd8e7369e..0000000000000
--- a/tests/ui/lint/issue-80988.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Regression test for #80988
-//
-//@ check-pass
-
-#![forbid(warnings)]
-
-#[deny(warnings)]
-//~^ WARNING incompatible with previous forbid
-//~| WARNING being phased out
-fn main() {}
diff --git a/tests/ui/lint/issue-80988.stderr b/tests/ui/lint/issue-80988.stderr
deleted file mode 100644
index afc93fcfeef12..0000000000000
--- a/tests/ui/lint/issue-80988.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-warning: deny(warnings) incompatible with previous forbid
-  --> $DIR/issue-80988.rs:7:8
-   |
-LL | #![forbid(warnings)]
-   |           -------- `forbid` level set here
-LL |
-LL | #[deny(warnings)]
-   |        ^^^^^^^^ overruled by previous forbid
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
-   = note: `#[warn(forbidden_lint_groups)]` on by default
-
-warning: 1 warning emitted
-

From 1af9d11583ea7ce06f78594b7f15bb0ba8bb22b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <39484203+jieyouxu@users.noreply.github.com>
Date: Fri, 18 Oct 2024 16:00:11 +0800
Subject: [PATCH 08/15] Expand test coverage for deny-inside-forbid
 interactions

---
 tests/ui/lint/auxiliary/allow-macro.rs        |  7 ++++
 tests/ui/lint/auxiliary/forbid-macro.rs       |  7 ++++
 tests/ui/lint/auxiliary/warn-macro.rs         |  7 ++++
 ...y-inside-forbid-ignored.cli_forbid.stderr} |  8 ++--
 ...-forbid-ignored.cli_forbid_warnings.stderr | 35 ++++++++++++++++
 tests/ui/lint/deny-inside-forbid-ignored.rs   |  8 +++-
 ...y-inside-forbid-ignored.source_only.stderr | 35 ++++++++++++++++
 .../lint/forbid-macro-with-deny.allow.stderr  | 26 ++++++++++++
 tests/ui/lint/forbid-macro-with-deny.rs       | 41 ++++++++++++++++---
 .../lint/forbid-macro-with-deny.warn.stderr   | 26 ++++++++++++
 10 files changed, 188 insertions(+), 12 deletions(-)
 create mode 100644 tests/ui/lint/auxiliary/allow-macro.rs
 create mode 100644 tests/ui/lint/auxiliary/forbid-macro.rs
 create mode 100644 tests/ui/lint/auxiliary/warn-macro.rs
 rename tests/ui/lint/{deny-inside-forbid-ignored.stderr => deny-inside-forbid-ignored.cli_forbid.stderr} (85%)
 create mode 100644 tests/ui/lint/deny-inside-forbid-ignored.cli_forbid_warnings.stderr
 create mode 100644 tests/ui/lint/deny-inside-forbid-ignored.source_only.stderr
 create mode 100644 tests/ui/lint/forbid-macro-with-deny.allow.stderr
 create mode 100644 tests/ui/lint/forbid-macro-with-deny.warn.stderr

diff --git a/tests/ui/lint/auxiliary/allow-macro.rs b/tests/ui/lint/auxiliary/allow-macro.rs
new file mode 100644
index 0000000000000..35980e2e6ac4c
--- /dev/null
+++ b/tests/ui/lint/auxiliary/allow-macro.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+macro_rules! emit_allow {
+    () => {
+        #[allow(unsafe_code)]
+        let _so_safe = 0;
+    };
+}
diff --git a/tests/ui/lint/auxiliary/forbid-macro.rs b/tests/ui/lint/auxiliary/forbid-macro.rs
new file mode 100644
index 0000000000000..aa74d0cf31439
--- /dev/null
+++ b/tests/ui/lint/auxiliary/forbid-macro.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+macro_rules! emit_forbid {
+    () => {
+        #[forbid(unsafe_code)]
+        let _so_safe = 0;
+    };
+}
diff --git a/tests/ui/lint/auxiliary/warn-macro.rs b/tests/ui/lint/auxiliary/warn-macro.rs
new file mode 100644
index 0000000000000..8216b65c74bc4
--- /dev/null
+++ b/tests/ui/lint/auxiliary/warn-macro.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+macro_rules! emit_warn {
+    () => {
+        #[warn(unsafe_code)]
+        let _so_safe = 0;
+    };
+}
diff --git a/tests/ui/lint/deny-inside-forbid-ignored.stderr b/tests/ui/lint/deny-inside-forbid-ignored.cli_forbid.stderr
similarity index 85%
rename from tests/ui/lint/deny-inside-forbid-ignored.stderr
rename to tests/ui/lint/deny-inside-forbid-ignored.cli_forbid.stderr
index b7fc0ccf5a23f..06086cbef8a2c 100644
--- a/tests/ui/lint/deny-inside-forbid-ignored.stderr
+++ b/tests/ui/lint/deny-inside-forbid-ignored.cli_forbid.stderr
@@ -1,5 +1,5 @@
 error[E0453]: allow(unsafe_code) incompatible with previous forbid
-  --> $DIR/deny-inside-forbid-ignored.rs:8:17
+  --> $DIR/deny-inside-forbid-ignored.rs:12:17
    |
 LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
    |          ----------- `forbid` level set here
@@ -8,7 +8,7 @@ LL |         #[allow(unsafe_code)] // let's have some unsafe code in here
    |                 ^^^^^^^^^^^ overruled by previous forbid
 
 error[E0453]: allow(unsafe_code) incompatible with previous forbid
-  --> $DIR/deny-inside-forbid-ignored.rs:8:17
+  --> $DIR/deny-inside-forbid-ignored.rs:12:17
    |
 LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
    |          ----------- `forbid` level set here
@@ -19,13 +19,13 @@ LL |         #[allow(unsafe_code)] // let's have some unsafe code in here
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: usage of an `unsafe` block
-  --> $DIR/deny-inside-forbid-ignored.rs:12:13
+  --> $DIR/deny-inside-forbid-ignored.rs:16:13
    |
 LL |             unsafe { /* ≽^•⩊•^≼ */ }
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/deny-inside-forbid-ignored.rs:4:10
+  --> $DIR/deny-inside-forbid-ignored.rs:8:10
    |
 LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
    |          ^^^^^^^^^^^
diff --git a/tests/ui/lint/deny-inside-forbid-ignored.cli_forbid_warnings.stderr b/tests/ui/lint/deny-inside-forbid-ignored.cli_forbid_warnings.stderr
new file mode 100644
index 0000000000000..06086cbef8a2c
--- /dev/null
+++ b/tests/ui/lint/deny-inside-forbid-ignored.cli_forbid_warnings.stderr
@@ -0,0 +1,35 @@
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+  --> $DIR/deny-inside-forbid-ignored.rs:12:17
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ----------- `forbid` level set here
+...
+LL |         #[allow(unsafe_code)] // let's have some unsafe code in here
+   |                 ^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+  --> $DIR/deny-inside-forbid-ignored.rs:12:17
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ----------- `forbid` level set here
+...
+LL |         #[allow(unsafe_code)] // let's have some unsafe code in here
+   |                 ^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: usage of an `unsafe` block
+  --> $DIR/deny-inside-forbid-ignored.rs:16:13
+   |
+LL |             unsafe { /* ≽^•⩊•^≼ */ }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deny-inside-forbid-ignored.rs:8:10
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/tests/ui/lint/deny-inside-forbid-ignored.rs b/tests/ui/lint/deny-inside-forbid-ignored.rs
index da5a14ce25334..b14a3e94bb55b 100644
--- a/tests/ui/lint/deny-inside-forbid-ignored.rs
+++ b/tests/ui/lint/deny-inside-forbid-ignored.rs
@@ -1,5 +1,9 @@
-/// Ensure that using deny inside forbid is treated as a no-op,
-/// and does not override the level to deny.
+//! Ensure that using deny inside forbid is treated as a no-op, and does not override the level to
+//! deny.
+
+//@ revisions: source_only cli_forbid cli_forbid_warnings
+//@[cli_forbid] compile-flags: -F unsafe_code
+//@[cli_forbid_warnings] compile-flags: -F warnings
 
 #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
 fn main() {
diff --git a/tests/ui/lint/deny-inside-forbid-ignored.source_only.stderr b/tests/ui/lint/deny-inside-forbid-ignored.source_only.stderr
new file mode 100644
index 0000000000000..06086cbef8a2c
--- /dev/null
+++ b/tests/ui/lint/deny-inside-forbid-ignored.source_only.stderr
@@ -0,0 +1,35 @@
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+  --> $DIR/deny-inside-forbid-ignored.rs:12:17
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ----------- `forbid` level set here
+...
+LL |         #[allow(unsafe_code)] // let's have some unsafe code in here
+   |                 ^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+  --> $DIR/deny-inside-forbid-ignored.rs:12:17
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ----------- `forbid` level set here
+...
+LL |         #[allow(unsafe_code)] // let's have some unsafe code in here
+   |                 ^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: usage of an `unsafe` block
+  --> $DIR/deny-inside-forbid-ignored.rs:16:13
+   |
+LL |             unsafe { /* ≽^•⩊•^≼ */ }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deny-inside-forbid-ignored.rs:8:10
+   |
+LL | #[forbid(unsafe_code)] // NO UNSAFE CODE IN HERE!!
+   |          ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/tests/ui/lint/forbid-macro-with-deny.allow.stderr b/tests/ui/lint/forbid-macro-with-deny.allow.stderr
new file mode 100644
index 0000000000000..77735c1c5d344
--- /dev/null
+++ b/tests/ui/lint/forbid-macro-with-deny.allow.stderr
@@ -0,0 +1,26 @@
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+  --> $DIR/forbid-macro-with-deny.rs:39:5
+   |
+LL | #![forbid(unsafe_code)]
+   |           ----------- `forbid` level set here
+...
+LL |     allow_macro::emit_allow! {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: this error originates in the macro `allow_macro::emit_allow` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0453]: allow(unsafe_code) incompatible with previous forbid
+  --> $DIR/forbid-macro-with-deny.rs:39:5
+   |
+LL | #![forbid(unsafe_code)]
+   |           ----------- `forbid` level set here
+...
+LL |     allow_macro::emit_allow! {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: this error originates in the macro `allow_macro::emit_allow` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0453`.
diff --git a/tests/ui/lint/forbid-macro-with-deny.rs b/tests/ui/lint/forbid-macro-with-deny.rs
index e6985ab19d166..85f67ea36310e 100644
--- a/tests/ui/lint/forbid-macro-with-deny.rs
+++ b/tests/ui/lint/forbid-macro-with-deny.rs
@@ -1,16 +1,45 @@
-//@ aux-build:deny-macro.rs
-//@ check-pass
+//! Ensure that when a macro (or normal code) does `#[deny]` inside a `#[forbid]` context, no error
+//! is emitted, as both parties agree on the treatment of the lint.
+//!
+//! However, still emit an error if the macro does `#[allow]` or `#[warn]`.
 
-// Ensure that when a macro (or normal code) does #[deny] inside a #[forbid]
-// context, no error is emitted, as both parties agree on the treatment of the lint.
+//@ revisions: forbid deny warn allow
+//@[forbid] aux-build:forbid-macro.rs
+//@[deny] aux-build:deny-macro.rs
+//@[warn] aux-build:warn-macro.rs
+//@[allow] aux-build:allow-macro.rs
+
+//@[forbid] check-pass
+//@[deny] check-pass
 
 #![forbid(unsafe_code)]
 
+#[cfg(allow)]
+extern crate allow_macro;
+#[cfg(deny)]
 extern crate deny_macro;
+#[cfg(forbid)]
+extern crate forbid_macro;
+#[cfg(warn)]
+extern crate warn_macro;
 
 fn main() {
-    deny_macro::emit_deny! {}
+    #[cfg(forbid)]
+    forbid_macro::emit_forbid! {} // OK
+
+    #[cfg(deny)]
+    deny_macro::emit_deny! {} // OK
+
+    #[cfg(warn)]
+    warn_macro::emit_warn! {}
+    //[warn]~^ ERROR warn(unsafe_code) incompatible with previous forbid
+    //[warn]~| ERROR warn(unsafe_code) incompatible with previous forbid
+
+    #[cfg(allow)]
+    allow_macro::emit_allow! {}
+    //[allow]~^ ERROR allow(unsafe_code) incompatible with previous forbid
+    //[allow]~| ERROR allow(unsafe_code) incompatible with previous forbid
 
-    #[deny(unsafe_code)]
+    #[deny(unsafe_code)] // OK
     let _ = 0;
 }
diff --git a/tests/ui/lint/forbid-macro-with-deny.warn.stderr b/tests/ui/lint/forbid-macro-with-deny.warn.stderr
new file mode 100644
index 0000000000000..10452ebd1b6bc
--- /dev/null
+++ b/tests/ui/lint/forbid-macro-with-deny.warn.stderr
@@ -0,0 +1,26 @@
+error[E0453]: warn(unsafe_code) incompatible with previous forbid
+  --> $DIR/forbid-macro-with-deny.rs:34:5
+   |
+LL | #![forbid(unsafe_code)]
+   |           ----------- `forbid` level set here
+...
+LL |     warn_macro::emit_warn! {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: this error originates in the macro `warn_macro::emit_warn` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0453]: warn(unsafe_code) incompatible with previous forbid
+  --> $DIR/forbid-macro-with-deny.rs:34:5
+   |
+LL | #![forbid(unsafe_code)]
+   |           ----------- `forbid` level set here
+...
+LL |     warn_macro::emit_warn! {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: this error originates in the macro `warn_macro::emit_warn` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0453`.

From 28fce83cc6d9cce7caf1e4f11462ac76c93ee734 Mon Sep 17 00:00:00 2001
From: clubby789 <jamie@hill-daniel.co.uk>
Date: Sat, 19 Oct 2024 13:02:37 +0000
Subject: [PATCH 09/15] Align boolean option descriptions in `configure.py`

---
 src/bootstrap/configure.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index a555a26367d51..15137fbb2b5c2 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -193,7 +193,8 @@ def is_value_list(key):
         if option.value:
             print('\t{:30} {}'.format('--{}=VAL'.format(option.name), option.desc))
         else:
-            print('\t{:30} {}'.format('--enable-{}  OR  --disable-{}'.format(option.name, option.name), option.desc))
+            print('\t--enable-{:25} OR --disable-{}'.format(option.name, option.name))
+            print('\t\t' + option.desc)
     print('')
     print('This configure script is a thin configuration shim over the true')
     print('configuration system, `config.toml`. You can explore the comments')

From 3310419d35c51b4da14c2fee9c0dcfab6b66ea0d Mon Sep 17 00:00:00 2001
From: Zalathar <Zalathar@users.noreply.github.com>
Date: Fri, 18 Oct 2024 21:43:37 +1100
Subject: [PATCH 10/15] Make `llvm::set_section` take a `&CStr`

---
 .../src/coverageinfo/mapgen.rs                 |  4 +++-
 .../rustc_codegen_llvm/src/coverageinfo/mod.rs | 18 +++++++++---------
 compiler/rustc_codegen_llvm/src/llvm/mod.rs    |  5 ++---
 3 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 4075849323a48..cee704a9c220b 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -1,3 +1,5 @@
+use std::ffi::CStr;
+
 use itertools::Itertools as _;
 use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
@@ -305,7 +307,7 @@ fn generate_coverage_map<'ll>(
 /// specific, well-known section and name.
 fn save_function_record(
     cx: &CodegenCx<'_, '_>,
-    covfun_section_name: &str,
+    covfun_section_name: &CStr,
     mangled_function_name: &str,
     source_hash: u64,
     filenames_ref: u64,
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 4f93e6ab1e52b..484a4d00c13ee 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -1,5 +1,5 @@
 use std::cell::RefCell;
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
 
 use libc::c_uint;
 use rustc_codegen_ssa::traits::{
@@ -292,10 +292,10 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
     .unwrap();
     debug!("covmap var name: {:?}", covmap_var_name);
 
-    let covmap_section_name = llvm::build_string(|s| unsafe {
+    let covmap_section_name = CString::new(llvm::build_byte_buffer(|s| unsafe {
         llvm::LLVMRustCoverageWriteMapSectionNameToString(cx.llmod, s);
-    })
-    .expect("Rust Coverage section name failed UTF-8 conversion");
+    }))
+    .expect("covmap section name should not contain NUL");
     debug!("covmap section name: {:?}", covmap_section_name);
 
     let llglobal = llvm::add_global(cx.llmod, cx.val_ty(cov_data_val), &covmap_var_name);
@@ -310,7 +310,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
 
 pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
-    covfun_section_name: &str,
+    covfun_section_name: &CStr,
     func_name_hash: u64,
     func_record_val: &'ll llvm::Value,
     is_used: bool,
@@ -354,9 +354,9 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
 /// - `__llvm_covfun` on Linux
 /// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix)
 /// - `.lcovfun$M` on Windows (includes `$M` sorting suffix)
-pub(crate) fn covfun_section_name(cx: &CodegenCx<'_, '_>) -> String {
-    llvm::build_string(|s| unsafe {
+pub(crate) fn covfun_section_name(cx: &CodegenCx<'_, '_>) -> CString {
+    CString::new(llvm::build_byte_buffer(|s| unsafe {
         llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
-    })
-    .expect("Rust Coverage function record section name failed UTF-8 conversion")
+    }))
+    .expect("covfun section name should not contain NUL")
 }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index b306396e15a80..e837022044ee0 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -210,10 +210,9 @@ impl MemoryEffects {
     }
 }
 
-pub fn set_section(llglobal: &Value, section_name: &str) {
-    let section_name_cstr = CString::new(section_name).expect("unexpected CString error");
+pub fn set_section(llglobal: &Value, section_name: &CStr) {
     unsafe {
-        LLVMSetSection(llglobal, section_name_cstr.as_ptr());
+        LLVMSetSection(llglobal, section_name.as_ptr());
     }
 }
 

From e32a5be3b0beb84a32b952e91b3acc5f14c1d40b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <39484203+jieyouxu@users.noreply.github.com>
Date: Sun, 20 Oct 2024 11:36:46 +0800
Subject: [PATCH 11/15] compiletest: disambiguate between `tidy` and `tidy`
 (html version)

---
 src/tools/compiletest/src/common.rs  | 4 ++--
 src/tools/compiletest/src/lib.rs     | 6 +++---
 src/tools/compiletest/src/main.rs    | 2 +-
 src/tools/compiletest/src/runtest.rs | 4 +---
 4 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 1ee00a3a4e8ff..ff059940f7ccd 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -338,8 +338,8 @@ pub struct Config {
     /// created in `/<build_base>/rustfix_missing_coverage.txt`
     pub rustfix_coverage: bool,
 
-    /// whether to run `tidy` when a rustdoc test fails
-    pub has_tidy: bool,
+    /// whether to run `tidy` (html-tidy) when a rustdoc test fails
+    pub has_html_tidy: bool,
 
     /// whether to run `enzyme` autodiff tests
     pub has_enzyme: bool,
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index d045c6fe05312..7d6ede9bcdac5 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -230,14 +230,14 @@ pub fn parse_config(args: Vec<String>) -> Config {
     let run_ignored = matches.opt_present("ignored");
     let with_debug_assertions = matches.opt_present("with-debug-assertions");
     let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
-    let has_tidy = if mode == Mode::Rustdoc {
+    let has_html_tidy = if mode == Mode::Rustdoc {
         Command::new("tidy")
             .arg("--version")
             .stdout(Stdio::null())
             .status()
             .map_or(false, |status| status.success())
     } else {
-        // Avoid spawning an external command when we know tidy won't be used.
+        // Avoid spawning an external command when we know html-tidy won't be used.
         false
     };
     let has_enzyme = matches.opt_present("has-enzyme");
@@ -336,7 +336,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
             .opt_str("compare-mode")
             .map(|s| s.parse().expect("invalid --compare-mode provided")),
         rustfix_coverage: matches.opt_present("rustfix-coverage"),
-        has_tidy,
+        has_html_tidy,
         has_enzyme,
         channel: matches.opt_str("channel").unwrap(),
         git_hash: matches.opt_present("git-hash"),
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index b84dd956de062..2f0c7d8ddc516 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -18,7 +18,7 @@ fn main() {
 
     let config = Arc::new(parse_config(env::args().collect()));
 
-    if !config.has_tidy && config.mode == Mode::Rustdoc {
+    if !config.has_html_tidy && config.mode == Mode::Rustdoc {
         eprintln!("warning: `tidy` (html-tidy.org) is not installed; diffs will not be generated");
     }
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 5b8a96a54c2df..36c5106ddad03 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 use std::borrow::Cow;
 use std::collections::{HashMap, HashSet};
 use std::ffi::OsString;
@@ -1897,7 +1895,7 @@ impl<'test> TestCx<'test> {
     }
 
     fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
-        if !self.config.has_tidy {
+        if !self.config.has_html_tidy {
             return;
         }
         println!("info: generating a diff against nightly rustdoc");

From eca5359b832f073e16616fce0080701e7e65d1e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Sun, 20 Oct 2024 10:05:39 +0200
Subject: [PATCH 12/15] add latest crash tests

---
 tests/crashes/131637.rs |  7 +++++++
 tests/crashes/131648.rs |  7 +++++++
 tests/crashes/131668.rs | 12 ++++++++++++
 tests/crashes/131758.rs | 11 +++++++++++
 tests/crashes/131762.rs |  9 +++++++++
 tests/crashes/131787.rs |  5 +++++
 tests/crashes/131886.rs | 12 ++++++++++++
 tests/crashes/131915.rs | 13 +++++++++++++
 8 files changed, 76 insertions(+)
 create mode 100644 tests/crashes/131637.rs
 create mode 100644 tests/crashes/131648.rs
 create mode 100644 tests/crashes/131668.rs
 create mode 100644 tests/crashes/131758.rs
 create mode 100644 tests/crashes/131762.rs
 create mode 100644 tests/crashes/131787.rs
 create mode 100644 tests/crashes/131886.rs
 create mode 100644 tests/crashes/131915.rs

diff --git a/tests/crashes/131637.rs b/tests/crashes/131637.rs
new file mode 100644
index 0000000000000..7d328384a7455
--- /dev/null
+++ b/tests/crashes/131637.rs
@@ -0,0 +1,7 @@
+//@ known-bug: #121637
+#![feature(non_lifetime_binders)]
+trait Trait<Type> {
+    type Type;
+
+    fn method(&self) -> impl for<T> Trait<impl Trait<T>>;
+}
diff --git a/tests/crashes/131648.rs b/tests/crashes/131648.rs
new file mode 100644
index 0000000000000..68046ce2a1fb0
--- /dev/null
+++ b/tests/crashes/131648.rs
@@ -0,0 +1,7 @@
+//@ known-bug: #131648
+#![feature(return_type_notation)]
+
+trait IntFactory {
+    fn stream(self) -> impl IntFactory<stream(..): Send>;
+}
+fn main() {}
diff --git a/tests/crashes/131668.rs b/tests/crashes/131668.rs
new file mode 100644
index 0000000000000..90aa449442568
--- /dev/null
+++ b/tests/crashes/131668.rs
@@ -0,0 +1,12 @@
+//@ known-bug: #131668
+
+#![feature(generic_associated_types_extended)]
+trait B {
+    type Y<const N: i16>;
+}
+
+struct Erase<T: B>(T);
+
+fn make_static() {
+    Erase::<dyn for<'c> B<&'c ()>>(());
+}
diff --git a/tests/crashes/131758.rs b/tests/crashes/131758.rs
new file mode 100644
index 0000000000000..942c5fd7a5025
--- /dev/null
+++ b/tests/crashes/131758.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #131758
+#![feature(unboxed_closures)]
+trait Foo {}
+
+impl<T: Fn<(i32,)>> Foo for T {}
+
+fn baz<T: Foo>(_: T) {}
+
+fn main() {
+    baz(|x| ());
+}
diff --git a/tests/crashes/131762.rs b/tests/crashes/131762.rs
new file mode 100644
index 0000000000000..85cb9c8f20a8b
--- /dev/null
+++ b/tests/crashes/131762.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #131762
+// ignore-tidy-linelength
+
+#![feature(generic_assert)]
+struct FloatWrapper(f64);
+
+fn main() {
+    assert!((0.0 / 0.0 >= 0.0) == (FloatWrapper(0.0 / 0.0) >= FloatWrapper(size_of::<u8>, size_of::<u16>, size_of::<usize> as fn() -> usize)))
+}
diff --git a/tests/crashes/131787.rs b/tests/crashes/131787.rs
new file mode 100644
index 0000000000000..5c24ff8c14303
--- /dev/null
+++ b/tests/crashes/131787.rs
@@ -0,0 +1,5 @@
+//@ known-bug: #131787
+#[track_caller]
+static no_mangle: u32 = {
+    unimplemented!();
+};
diff --git a/tests/crashes/131886.rs b/tests/crashes/131886.rs
new file mode 100644
index 0000000000000..c31c2d6aa8bd7
--- /dev/null
+++ b/tests/crashes/131886.rs
@@ -0,0 +1,12 @@
+//@ known-bug: #131886
+//@ compile-flags: -Zvalidate-mir --crate-type=lib
+#![feature(trait_upcasting, type_alias_impl_trait)]
+
+type Tait = impl Sized;
+
+trait Foo<'a>: Bar<'a, 'a, Tait> {}
+trait Bar<'a, 'b, T> {}
+
+fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) {
+    let _ = x as &dyn Bar<'_, '_, ()>;
+}
diff --git a/tests/crashes/131915.rs b/tests/crashes/131915.rs
new file mode 100644
index 0000000000000..58d45adcb3be7
--- /dev/null
+++ b/tests/crashes/131915.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #131915
+
+macro_rules! y {
+    ( $($matcher:tt)*) => {
+        x
+    };
+}
+
+const _: A<
+    {
+        y! { test.tou8 }
+    },
+>;

From ef5a56f7bcc0d23fe8de35486e85f628b9216766 Mon Sep 17 00:00:00 2001
From: Chris Denton <chris@chrisdenton.dev>
Date: Sun, 20 Oct 2024 08:34:25 +0000
Subject: [PATCH 13/15] Remove outdated comment

#44234 is resolved
---
 compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 69707fdbe8fa1..7bb40996d58f2 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -437,9 +437,6 @@ provide! { tcx, def_id, other, cdata,
 
 pub(in crate::rmeta) fn provide(providers: &mut Providers) {
     provide_cstore_hooks(providers);
-    // FIXME(#44234) - almost all of these queries have no sub-queries and
-    // therefore no actual inputs, they're just reading tables calculated in
-    // resolve! Does this work? Unsure! That's what the issue is about
     providers.queries = rustc_middle::query::Providers {
         allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(),
         alloc_error_handler_kind: |tcx, ()| CStore::from_tcx(tcx).alloc_error_handler_kind(),

From 68d1fd942710eb7cb408f3dea2f6e1845f6cbe87 Mon Sep 17 00:00:00 2001
From: Jubilee Young <workingjubilee@gmail.com>
Date: Thu, 17 Oct 2024 14:46:08 -0700
Subject: [PATCH 14/15] compiler: pre-move code for fixing enum layout ICEs

---
 compiler/rustc_ty_utils/src/layout.rs                        | 5 +++--
 .../src/{layout_sanity_check.rs => layout/invariant.rs}      | 2 +-
 compiler/rustc_ty_utils/src/lib.rs                           | 1 -
 .../126966.rs => ui/layout/thaw-transmute-invalid-enum.rs}   | 0
 .../128870.rs => ui/layout/thaw-validate-invalid-enum.rs}    | 0
 5 files changed, 4 insertions(+), 4 deletions(-)
 rename compiler/rustc_ty_utils/src/{layout_sanity_check.rs => layout/invariant.rs} (99%)
 rename tests/{crashes/126966.rs => ui/layout/thaw-transmute-invalid-enum.rs} (100%)
 rename tests/{crashes/128870.rs => ui/layout/thaw-validate-invalid-enum.rs} (100%)

diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index afdfa2e80c1f6..db70a12a4d1c8 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -30,7 +30,8 @@ use {rustc_abi as abi, rustc_hir as hir};
 use crate::errors::{
     MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType,
 };
-use crate::layout_sanity_check::sanity_check_layout;
+
+mod invariant;
 
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { layout_of, ..*providers };
@@ -79,7 +80,7 @@ fn layout_of<'tcx>(
         record_layout_for_printing(&cx, layout);
     }
 
-    sanity_check_layout(&cx, &layout);
+    invariant::partially_check_layout(&cx, &layout);
 
     Ok(layout)
 }
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs
similarity index 99%
rename from compiler/rustc_ty_utils/src/layout_sanity_check.rs
rename to compiler/rustc_ty_utils/src/layout/invariant.rs
index be0a7c5ee890a..6cf114b74c13d 100644
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout/invariant.rs
@@ -5,7 +5,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout};
 use rustc_target::abi::*;
 
 /// Enforce some basic invariants on layouts.
-pub(super) fn sanity_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
+pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
     let tcx = cx.tcx();
 
     // Type-level uninhabitedness should always imply ABI uninhabitedness.
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index dc5303317a8a0..8be1611bb9ac2 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -29,7 +29,6 @@ mod errors;
 mod implied_bounds;
 mod instance;
 mod layout;
-mod layout_sanity_check;
 mod needs_drop;
 mod opaque_types;
 mod representability;
diff --git a/tests/crashes/126966.rs b/tests/ui/layout/thaw-transmute-invalid-enum.rs
similarity index 100%
rename from tests/crashes/126966.rs
rename to tests/ui/layout/thaw-transmute-invalid-enum.rs
diff --git a/tests/crashes/128870.rs b/tests/ui/layout/thaw-validate-invalid-enum.rs
similarity index 100%
rename from tests/crashes/128870.rs
rename to tests/ui/layout/thaw-validate-invalid-enum.rs

From 9f4c9155d4535e08a3148e792711447e44541cd1 Mon Sep 17 00:00:00 2001
From: Jubilee Young <workingjubilee@gmail.com>
Date: Sun, 20 Oct 2024 01:45:15 -0700
Subject: [PATCH 15/15] compiler: Reject impossible reprs during enum layout

---
 compiler/rustc_abi/src/layout.rs              |  9 +++
 compiler/rustc_ty_utils/src/layout.rs         |  5 ++
 .../ui/layout/thaw-transmute-invalid-enum.rs  |  9 ++-
 .../layout/thaw-transmute-invalid-enum.stderr | 68 +++++++++++++++++++
 tests/ui/layout/thaw-validate-invalid-enum.rs |  5 +-
 .../layout/thaw-validate-invalid-enum.stderr  | 29 ++++++++
 6 files changed, 121 insertions(+), 4 deletions(-)
 create mode 100644 tests/ui/layout/thaw-transmute-invalid-enum.stderr
 create mode 100644 tests/ui/layout/thaw-validate-invalid-enum.stderr

diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 5ce5f14ce57cb..59f42425bb936 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -54,6 +54,9 @@ pub enum LayoutCalculatorError<F> {
 
     /// A union had no fields.
     EmptyUnion,
+
+    /// The fields or variants have irreconcilable reprs
+    ReprConflict,
 }
 
 impl<F> LayoutCalculatorError<F> {
@@ -64,6 +67,7 @@ impl<F> LayoutCalculatorError<F> {
             }
             LayoutCalculatorError::SizeOverflow => LayoutCalculatorError::SizeOverflow,
             LayoutCalculatorError::EmptyUnion => LayoutCalculatorError::EmptyUnion,
+            LayoutCalculatorError::ReprConflict => LayoutCalculatorError::ReprConflict,
         }
     }
 
@@ -77,6 +81,7 @@ impl<F> LayoutCalculatorError<F> {
             }
             LayoutCalculatorError::SizeOverflow => "size overflow",
             LayoutCalculatorError::EmptyUnion => "type is a union with no fields",
+            LayoutCalculatorError::ReprConflict => "type has an invalid repr",
         })
     }
 }
@@ -514,6 +519,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
         }
 
         let dl = self.cx.data_layout();
+        // bail if the enum has an incoherent repr that cannot be computed
+        if repr.packed() {
+            return Err(LayoutCalculatorError::ReprConflict);
+        }
 
         let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> {
             if dont_niche_optimize_enum {
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index db70a12a4d1c8..38b292afe8d71 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -116,6 +116,11 @@ fn map_error<'tcx>(
             cx.tcx().dcx().delayed_bug(format!("computed layout of empty union: {ty:?}"));
             LayoutError::Unknown(ty)
         }
+        LayoutCalculatorError::ReprConflict => {
+            // packed enums are the only known trigger of this, but others might arise
+            cx.tcx().dcx().delayed_bug(format!("computed impossible repr (packed enum?): {ty:?}"));
+            LayoutError::Unknown(ty)
+        }
     };
     error(cx, err)
 }
diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.rs b/tests/ui/layout/thaw-transmute-invalid-enum.rs
index 2c9f1a70f4fbf..835dcc049964f 100644
--- a/tests/ui/layout/thaw-transmute-invalid-enum.rs
+++ b/tests/ui/layout/thaw-transmute-invalid-enum.rs
@@ -1,10 +1,14 @@
-//@ known-bug: rust-lang/rust#126966
+#![crate_type = "lib"]
+
 mod assert {
     use std::mem::{Assume, TransmuteFrom};
+    //~^ ERROR: use of unstable library feature 'transmutability'
+    //~| ERROR: use of unstable library feature 'transmutability'
 
     pub fn is_transmutable<Src, Dst>()
     where
         Dst: TransmuteFrom<Src>,
+        //~^ ERROR: use of unstable library feature 'transmutability'
     {
     }
 }
@@ -15,6 +19,7 @@ enum Ox00 {
 }
 
 #[repr(C, packed(2))]
+//~^ ERROR: attribute should be applied to a struct
 enum OxFF {
     V = 0xFF,
 }
@@ -22,8 +27,10 @@ enum OxFF {
 fn test() {
     union Superset {
         a: Ox00,
+        //~^ ERROR: field must implement `Copy`
         b: OxFF,
     }
 
     assert::is_transmutable::<Superset, Subset>();
+    //~^ ERROR: cannot find type `Subset`
 }
diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.stderr b/tests/ui/layout/thaw-transmute-invalid-enum.stderr
new file mode 100644
index 0000000000000..e6a5399c66b3d
--- /dev/null
+++ b/tests/ui/layout/thaw-transmute-invalid-enum.stderr
@@ -0,0 +1,68 @@
+error[E0412]: cannot find type `Subset` in this scope
+  --> $DIR/thaw-transmute-invalid-enum.rs:34:41
+   |
+LL |     assert::is_transmutable::<Superset, Subset>();
+   |                                         ^^^^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | fn test<Subset>() {
+   |        ++++++++
+
+error[E0517]: attribute should be applied to a struct or union
+  --> $DIR/thaw-transmute-invalid-enum.rs:21:11
+   |
+LL |   #[repr(C, packed(2))]
+   |             ^^^^^^^^^
+LL |
+LL | / enum OxFF {
+LL | |     V = 0xFF,
+LL | | }
+   | |_- not a struct or union
+
+error[E0658]: use of unstable library feature 'transmutability'
+  --> $DIR/thaw-transmute-invalid-enum.rs:4:20
+   |
+LL |     use std::mem::{Assume, TransmuteFrom};
+   |                    ^^^^^^
+   |
+   = note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information
+   = help: add `#![feature(transmutability)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature 'transmutability'
+  --> $DIR/thaw-transmute-invalid-enum.rs:4:28
+   |
+LL |     use std::mem::{Assume, TransmuteFrom};
+   |                            ^^^^^^^^^^^^^
+   |
+   = note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information
+   = help: add `#![feature(transmutability)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature 'transmutability'
+  --> $DIR/thaw-transmute-invalid-enum.rs:10:14
+   |
+LL |         Dst: TransmuteFrom<Src>,
+   |              ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information
+   = help: add `#![feature(transmutability)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+  --> $DIR/thaw-transmute-invalid-enum.rs:29:9
+   |
+LL |         a: Ox00,
+   |         ^^^^^^^
+   |
+   = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
+help: wrap the field type in `ManuallyDrop<...>`
+   |
+LL |         a: std::mem::ManuallyDrop<Ox00>,
+   |            +++++++++++++++++++++++    +
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0412, E0517, E0658, E0740.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/layout/thaw-validate-invalid-enum.rs b/tests/ui/layout/thaw-validate-invalid-enum.rs
index 2b7319621440c..51aff7fb556c2 100644
--- a/tests/ui/layout/thaw-validate-invalid-enum.rs
+++ b/tests/ui/layout/thaw-validate-invalid-enum.rs
@@ -1,7 +1,6 @@
-//@ known-bug: rust-lang/rust#128870
 //@ compile-flags: -Zvalidate-mir
 
-#[repr(packed)]
+#[repr(packed)] //~ ERROR: attribute should be applied to a struct
 #[repr(u32)]
 enum E {
     A,
@@ -12,7 +11,7 @@ enum E {
 fn main() {
     union InvalidTag {
         int: u32,
-        e: E,
+        e: E, //~ ERROR: field must implement `Copy`
     }
     let _invalid_tag = InvalidTag { int: 4 };
 }
diff --git a/tests/ui/layout/thaw-validate-invalid-enum.stderr b/tests/ui/layout/thaw-validate-invalid-enum.stderr
new file mode 100644
index 0000000000000..9e522cba96aa1
--- /dev/null
+++ b/tests/ui/layout/thaw-validate-invalid-enum.stderr
@@ -0,0 +1,29 @@
+error[E0517]: attribute should be applied to a struct or union
+  --> $DIR/thaw-validate-invalid-enum.rs:3:8
+   |
+LL |   #[repr(packed)]
+   |          ^^^^^^
+LL |   #[repr(u32)]
+LL | / enum E {
+LL | |     A,
+LL | |     B,
+LL | |     C,
+LL | | }
+   | |_- not a struct or union
+
+error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+  --> $DIR/thaw-validate-invalid-enum.rs:14:9
+   |
+LL |         e: E,
+   |         ^^^^
+   |
+   = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
+help: wrap the field type in `ManuallyDrop<...>`
+   |
+LL |         e: std::mem::ManuallyDrop<E>,
+   |            +++++++++++++++++++++++ +
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0517, E0740.
+For more information about an error, try `rustc --explain E0517`.