about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-04-24 19:48:38 +0000
committerbors <bors@rust-lang.org>2025-04-24 19:48:38 +0000
commitd7ea436a02d5de4033fcf7fd4eb8ed965d0f574c (patch)
tree0f7a3cb847217a40a76b96f86378cdb4e84eeaba
parent3c877f6a477380ed61155d3bf816df09c9e05b9e (diff)
parenta01655298a800d1022aa0b16340e62ca0cdecbca (diff)
downloadrust-d7ea436a02d5de4033fcf7fd4eb8ed965d0f574c.tar.gz
rust-d7ea436a02d5de4033fcf7fd4eb8ed965d0f574c.zip
Auto merge of #140256 - matthiaskrgr:rollup-8if58zf, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #136083 (Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc)
 - #138282 (Add `#[repr(u128)]`/`#[repr(i128)]` enums to `improper_ctypes_definitions`)
 - #139700 (Autodiff flags)
 - #140139 (rustc_target: Adjust RISC-V feature implication)
 - #140141 (Move zkVM constants into `sys::env_consts`)
 - #140150 (fix MAX_EXP and MIN_EXP docs)
 - #140172 (Make algebraic functions into `const fn` items.)
 - #140191 (Remove git repository from git config)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_cranelift/example/example.rs2
-rw-r--r--compiler/rustc_codegen_gcc/example/example.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs40
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/builder/autodiff.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs25
-rw-r--r--compiler/rustc_lint/src/types.rs12
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs25
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp30
-rw-r--r--compiler/rustc_mir_transform/messages.ftl1
-rw-r--r--compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs100
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs20
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_session/src/config.rs4
-rw-r--r--compiler/rustc_session/src/options.rs6
-rw-r--r--compiler/rustc_target/src/target_features.rs10
-rw-r--r--library/alloctests/tests/fmt.rs1
-rw-r--r--library/core/src/char/convert.rs2
-rw-r--r--library/core/src/intrinsics/mod.rs11
-rw-r--r--library/core/src/num/f128.rs35
-rw-r--r--library/core/src/num/f16.rs35
-rw-r--r--library/core/src/num/f32.rs38
-rw-r--r--library/core/src/num/f64.rs38
-rw-r--r--library/core/src/num/int_macros.rs2
-rw-r--r--library/core/src/num/uint_macros.rs2
-rw-r--r--library/std/src/sys/env_consts.rs11
-rw-r--r--library/std/src/sys/pal/zkvm/env.rs9
m---------library/stdarch0
-rw-r--r--src/bootstrap/src/core/build_steps/suggest.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs1
-rw-r--r--src/bootstrap/src/core/config/config.rs1
-rw-r--r--src/bootstrap/src/utils/tests/git.rs1
-rw-r--r--src/build_helper/src/git.rs1
-rw-r--r--src/build_helper/src/stage0_parser.rs2
-rw-r--r--src/stage01
-rw-r--r--src/tools/bump-stage0/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.fixed8
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.rs8
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.stderr6
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-1782.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute.rs1
-rw-r--r--src/tools/clippy/tests/ui/transmute.stderr108
-rw-r--r--src/tools/clippy/tests/ui/transmute_float_to_int.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmute_float_to_int.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs2
-rw-r--r--src/tools/compiletest/src/common.rs2
-rw-r--r--src/tools/compiletest/src/header/tests.rs1
-rw-r--r--src/tools/compiletest/src/lib.rs2
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs26
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_bool.rs1
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_bool_op.rs1
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_char.rs1
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_char_op.rs1
-rw-r--r--src/tools/miri/tests/pass/float.rs1
-rw-r--r--src/tools/miri/tests/pass/issues/issue-miri-184.rs1
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs2
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs1
-rw-r--r--src/tools/suggest-tests/src/main.rs1
-rw-r--r--tests/codegen/autodiff/identical_fnc.rs45
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.rs2
-rw-r--r--tests/ui/consts/const-eval/transmute-const-promotion.rs1
-rw-r--r--tests/ui/consts/const-eval/transmute-const-promotion.stderr2
-rw-r--r--tests/ui/consts/const-eval/transmute-const.rs1
-rw-r--r--tests/ui/consts/const-eval/transmute-const.stderr2
-rw-r--r--tests/ui/consts/const-eval/ub-enum.rs2
-rw-r--r--tests/ui/consts/const-eval/ub-wide-ptr.rs2
-rw-r--r--tests/ui/consts/extra-const-ub/detect-extra-ub.rs1
-rw-r--r--tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr16
-rw-r--r--tests/ui/consts/issue-69532.rs4
-rw-r--r--tests/ui/issues/issue-25746-bool-transmute.rs1
-rw-r--r--tests/ui/lint/invalid_null_args.rs12
-rw-r--r--tests/ui/lint/invalid_null_args.stderr2
-rw-r--r--tests/ui/lint/lint-ctypes-enum.rs18
-rw-r--r--tests/ui/lint/lint-ctypes-enum.stderr88
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.fixed85
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.rs85
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.stderr235
81 files changed, 1030 insertions, 260 deletions
diff --git a/compiler/rustc_codegen_cranelift/example/example.rs b/compiler/rustc_codegen_cranelift/example/example.rs
index 1ef2aa5dd8e..aeb38331edb 100644
--- a/compiler/rustc_codegen_cranelift/example/example.rs
+++ b/compiler/rustc_codegen_cranelift/example/example.rs
@@ -1,6 +1,6 @@
 #![feature(no_core, unboxed_closures)]
 #![no_core]
-#![allow(dead_code)]
+#![allow(dead_code, unnecessary_transmutes)]
 
 extern crate mini_core;
 
diff --git a/compiler/rustc_codegen_gcc/example/example.rs b/compiler/rustc_codegen_gcc/example/example.rs
index 03470b74d0a..888fa89201e 100644
--- a/compiler/rustc_codegen_gcc/example/example.rs
+++ b/compiler/rustc_codegen_gcc/example/example.rs
@@ -1,6 +1,6 @@
 #![feature(no_core, unboxed_closures)]
 #![no_core]
-#![allow(dead_code)]
+#![allow(dead_code, unnecessary_transmutes)]
 
 extern crate mini_core;
 
@@ -11,11 +11,7 @@ fn abc(a: u8) -> u8 {
 }
 
 fn bcd(b: bool, a: u8) -> u8 {
-    if b {
-        a * 2
-    } else {
-        a * 3
-    }
+    if b { a * 2 } else { a * 3 }
 }
 
 fn call() {
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index a8b49e9552c..925898d8173 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -584,12 +584,10 @@ fn thin_lto(
     }
 }
 
-fn enable_autodiff_settings(ad: &[config::AutoDiff], module: &mut ModuleCodegen<ModuleLlvm>) {
+fn enable_autodiff_settings(ad: &[config::AutoDiff]) {
     for &val in ad {
+        // We intentionally don't use a wildcard, to not forget handling anything new.
         match val {
-            config::AutoDiff::PrintModBefore => {
-                unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
-            }
             config::AutoDiff::PrintPerf => {
                 llvm::set_print_perf(true);
             }
@@ -603,17 +601,23 @@ fn enable_autodiff_settings(ad: &[config::AutoDiff], module: &mut ModuleCodegen<
                 llvm::set_inline(true);
             }
             config::AutoDiff::LooseTypes => {
-                llvm::set_loose_types(false);
+                llvm::set_loose_types(true);
             }
             config::AutoDiff::PrintSteps => {
                 llvm::set_print(true);
             }
-            // We handle this below
+            // We handle this in the PassWrapper.cpp
+            config::AutoDiff::PrintPasses => {}
+            // We handle this in the PassWrapper.cpp
+            config::AutoDiff::PrintModBefore => {}
+            // We handle this in the PassWrapper.cpp
             config::AutoDiff::PrintModAfter => {}
-            // We handle this below
+            // We handle this in the PassWrapper.cpp
             config::AutoDiff::PrintModFinal => {}
             // This is required and already checked
             config::AutoDiff::Enable => {}
+            // We handle this below
+            config::AutoDiff::NoPostopt => {}
         }
     }
     // This helps with handling enums for now.
@@ -647,27 +651,27 @@ pub(crate) fn run_pass_manager(
     // We then run the llvm_optimize function a second time, to optimize the code which we generated
     // in the enzyme differentiation pass.
     let enable_ad = config.autodiff.contains(&config::AutoDiff::Enable);
-    let stage =
-        if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD };
+    let stage = if thin {
+        write::AutodiffStage::PreAD
+    } else {
+        if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD }
+    };
 
     if enable_ad {
-        enable_autodiff_settings(&config.autodiff, module);
+        enable_autodiff_settings(&config.autodiff);
     }
 
     unsafe {
         write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
     }
 
-    if cfg!(llvm_enzyme) && enable_ad {
-        // This is the post-autodiff IR, mainly used for testing and educational purposes.
-        if config.autodiff.contains(&config::AutoDiff::PrintModAfter) {
-            unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
-        }
-
+    if cfg!(llvm_enzyme) && enable_ad && !thin {
         let opt_stage = llvm::OptStage::FatLTO;
         let stage = write::AutodiffStage::PostAD;
-        unsafe {
-            write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
+        if !config.autodiff.contains(&config::AutoDiff::NoPostopt) {
+            unsafe {
+                write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
+            }
         }
 
         // This is the final IR, so people should be able to inspect the optimized autodiff output,
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 18d221d232e..4ac77c8f7f1 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -572,6 +572,10 @@ pub(crate) unsafe fn llvm_optimize(
 
     let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
     let run_enzyme = autodiff_stage == AutodiffStage::DuringAD;
+    let print_before_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModBefore);
+    let print_after_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModAfter);
+    let print_passes = config.autodiff.contains(&config::AutoDiff::PrintPasses);
+    let merge_functions;
     let unroll_loops;
     let vectorize_slp;
     let vectorize_loop;
@@ -579,13 +583,20 @@ pub(crate) unsafe fn llvm_optimize(
     // When we build rustc with enzyme/autodiff support, we want to postpone size-increasing
     // optimizations until after differentiation. Our pipeline is thus: (opt + enzyme), (full opt).
     // We therefore have two calls to llvm_optimize, if autodiff is used.
+    //
+    // We also must disable merge_functions, since autodiff placeholder/dummy bodies tend to be
+    // identical. We run opts before AD, so there is a chance that LLVM will merge our dummies.
+    // In that case, we lack some dummy bodies and can't replace them with the real AD code anymore.
+    // We then would need to abort compilation. This was especially common in test cases.
     if consider_ad && autodiff_stage != AutodiffStage::PostAD {
+        merge_functions = false;
         unroll_loops = false;
         vectorize_slp = false;
         vectorize_loop = false;
     } else {
         unroll_loops =
             opt_level != config::OptLevel::Size && opt_level != config::OptLevel::SizeMin;
+        merge_functions = config.merge_functions;
         vectorize_slp = config.vectorize_slp;
         vectorize_loop = config.vectorize_loop;
     }
@@ -663,13 +674,16 @@ pub(crate) unsafe fn llvm_optimize(
             thin_lto_buffer,
             config.emit_thin_lto,
             config.emit_thin_lto_summary,
-            config.merge_functions,
+            merge_functions,
             unroll_loops,
             vectorize_slp,
             vectorize_loop,
             config.no_builtins,
             config.emit_lifetime_markers,
             run_enzyme,
+            print_before_enzyme,
+            print_after_enzyme,
+            print_passes,
             sanitizer_options.as_ref(),
             pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
             pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index e7c071d05aa..0147bd5a665 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -473,7 +473,7 @@ pub(crate) fn differentiate<'ll>(
         return Err(diag_handler.handle().emit_almost_fatal(AutoDiffWithoutEnable));
     }
 
-    // Before dumping the module, we want all the TypeTrees to become part of the module.
+    // Here we replace the placeholder code with the actual autodiff code, which calls Enzyme.
     for item in diff_items.iter() {
         let name = item.source.clone();
         let fn_def: Option<&llvm::Value> = cx.get_function(&name);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 9ff04f72903..ffb490dcdc2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2454,6 +2454,9 @@ unsafe extern "C" {
         DisableSimplifyLibCalls: bool,
         EmitLifetimeMarkers: bool,
         RunEnzyme: bool,
+        PrintBeforeEnzyme: bool,
+        PrintAfterEnzyme: bool,
+        PrintPasses: bool,
         SanitizerOptions: Option<&SanitizerOptions>,
         PGOGenPath: *const c_char,
         PGOUsePath: *const c_char,
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 4ca317e3a1e..40c63f2b250 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -158,6 +158,31 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 self.copy_op(&val, dest)?;
             }
 
+            sym::fadd_algebraic
+            | sym::fsub_algebraic
+            | sym::fmul_algebraic
+            | sym::fdiv_algebraic
+            | sym::frem_algebraic => {
+                let a = self.read_immediate(&args[0])?;
+                let b = self.read_immediate(&args[1])?;
+
+                let op = match intrinsic_name {
+                    sym::fadd_algebraic => BinOp::Add,
+                    sym::fsub_algebraic => BinOp::Sub,
+                    sym::fmul_algebraic => BinOp::Mul,
+                    sym::fdiv_algebraic => BinOp::Div,
+                    sym::frem_algebraic => BinOp::Rem,
+
+                    _ => bug!(),
+                };
+
+                let res = self.binary_op(op, &a, &b)?;
+                // `binary_op` already called `generate_nan` if needed.
+
+                // FIXME: Miri should add some non-determinism to the result here to catch any dependences on exact computations. This has previously been done, but the behaviour was removed as part of constification.
+                self.write_immediate(*res, dest)?;
+            }
+
             sym::ctpop
             | sym::cttz
             | sym::cttz_nonzero
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index a084dacfb5b..f9dce5a5198 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,7 +1,9 @@
 use std::iter;
 use std::ops::ControlFlow;
 
-use rustc_abi::{BackendRepr, TagEncoding, VariantIdx, Variants, WrappingRange};
+use rustc_abi::{
+    BackendRepr, Integer, IntegerType, TagEncoding, VariantIdx, Variants, WrappingRange,
+};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagMessage;
 use rustc_hir::intravisit::VisitorExt;
@@ -1243,6 +1245,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             };
                         }
 
+                        if let Some(IntegerType::Fixed(Integer::I128, _)) = def.repr().int {
+                            return FfiUnsafe {
+                                ty,
+                                reason: fluent::lint_improper_ctypes_128bit,
+                                help: None,
+                            };
+                        }
+
                         use improper_ctypes::check_non_exhaustive_variant;
 
                         let non_exhaustive = def.variant_list_has_applicable_non_exhaustive();
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index a49eb76734f..17d501c5730 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -117,6 +117,7 @@ declare_lint_pass! {
         UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
         UNNAMEABLE_TEST_ITEMS,
         UNNAMEABLE_TYPES,
+        UNNECESSARY_TRANSMUTES,
         UNREACHABLE_CODE,
         UNREACHABLE_PATTERNS,
         UNSAFE_ATTR_OUTSIDE_UNSAFE,
@@ -4910,6 +4911,30 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `unnecessary_transmutes` lint detects transmutations that have safer alternatives.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// fn bytes_at_home(x: [u8; 4]) -> u32 {
+    ///   unsafe { std::mem::transmute(x) }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Using an explicit method is preferable over calls to
+    /// [`transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html) as
+    /// they more clearly communicate the intent, are easier to review, and
+    /// are less likely to accidentally result in unsoundness.
+    pub UNNECESSARY_TRANSMUTES,
+    Warn,
+    "detects transmutes that are shadowed by std methods"
+}
+
+declare_lint! {
     /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location,
     /// that runs a custom `Drop` destructor.
     /// Some of them may be dropped earlier in Edition 2024 that they used to in Edition 2021 and prior.
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index e02c80c50b1..8bee051dd4c 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -14,6 +14,7 @@
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/Verifier.h"
+#include "llvm/IRPrinter/IRPrintingPasses.h"
 #include "llvm/LTO/LTO.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -703,7 +704,8 @@ extern "C" LLVMRustResult LLVMRustOptimize(
     bool LintIR, LLVMRustThinLTOBuffer **ThinLTOBufferRef, bool EmitThinLTO,
     bool EmitThinLTOSummary, bool MergeFunctions, bool UnrollLoops,
     bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls,
-    bool EmitLifetimeMarkers, bool RunEnzyme,
+    bool EmitLifetimeMarkers, bool RunEnzyme, bool PrintBeforeEnzyme,
+    bool PrintAfterEnzyme, bool PrintPasses,
     LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath,
     const char *PGOUsePath, bool InstrumentCoverage,
     const char *InstrProfileOutput, const char *PGOSampleUsePath,
@@ -1048,14 +1050,38 @@ extern "C" LLVMRustResult LLVMRustOptimize(
   // now load "-enzyme" pass:
 #ifdef ENZYME
   if (RunEnzyme) {
-    registerEnzymeAndPassPipeline(PB, true);
+
+    if (PrintBeforeEnzyme) {
+      // Handle the Rust flag `-Zautodiff=PrintModBefore`.
+      std::string Banner = "Module before EnzymeNewPM";
+      MPM.addPass(PrintModulePass(outs(), Banner, true, false));
+    }
+
+    registerEnzymeAndPassPipeline(PB, false);
     if (auto Err = PB.parsePassPipeline(MPM, "enzyme")) {
       std::string ErrMsg = toString(std::move(Err));
       LLVMRustSetLastError(ErrMsg.c_str());
       return LLVMRustResult::Failure;
     }
+
+    if (PrintAfterEnzyme) {
+      // Handle the Rust flag `-Zautodiff=PrintModAfter`.
+      std::string Banner = "Module after EnzymeNewPM";
+      MPM.addPass(PrintModulePass(outs(), Banner, true, false));
+    }
   }
 #endif
+  if (PrintPasses) {
+    // Print all passes from the PM:
+    std::string Pipeline;
+    raw_string_ostream SOS(Pipeline);
+    MPM.printPipeline(SOS, [&PIC](StringRef ClassName) {
+      auto PassName = PIC.getPassNameForClassName(ClassName);
+      return PassName.empty() ? ClassName : PassName;
+    });
+    outs() << Pipeline;
+    outs() << "\n";
+  }
 
   // Upgrade all calls to old intrinsics first.
   for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl
index 5628f4c9381..a1264471a2d 100644
--- a/compiler/rustc_mir_transform/messages.ftl
+++ b/compiler/rustc_mir_transform/messages.ftl
@@ -84,3 +84,4 @@ mir_transform_undefined_transmute = pointers cannot be transmuted to integers du
     .help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
 
 mir_transform_unknown_pass_name = MIR pass `{$name}` is unknown and will be ignored
+mir_transform_unnecessary_transmute = unnecessary transmute
diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
new file mode 100644
index 00000000000..8be782dcbf0
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
@@ -0,0 +1,100 @@
+use rustc_middle::mir::visit::Visitor;
+use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind};
+use rustc_middle::ty::*;
+use rustc_session::lint::builtin::UNNECESSARY_TRANSMUTES;
+use rustc_span::source_map::Spanned;
+use rustc_span::{Span, sym};
+
+use crate::errors::UnnecessaryTransmute as Error;
+
+/// Check for transmutes that overlap with stdlib methods.
+/// For example, transmuting `[u8; 4]` to `u32`.
+pub(super) struct CheckUnnecessaryTransmutes;
+
+impl<'tcx> crate::MirLint<'tcx> for CheckUnnecessaryTransmutes {
+    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
+        let mut checker = UnnecessaryTransmuteChecker { body, tcx };
+        checker.visit_body(body);
+    }
+}
+
+struct UnnecessaryTransmuteChecker<'a, 'tcx> {
+    body: &'a Body<'tcx>,
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> {
+    fn is_unnecessary_transmute(
+        &self,
+        function: &Operand<'tcx>,
+        arg: String,
+        span: Span,
+    ) -> Option<Error> {
+        let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder();
+        let [input] = fn_sig.inputs() else { return None };
+
+        let err = |sugg| Error { span, sugg, help: None };
+
+        Some(match (input.kind(), fn_sig.output().kind()) {
+            // dont check the length; transmute does that for us.
+            // [u8; _] => primitive
+            (Array(t, _), Uint(_) | Float(_) | Int(_)) if *t.kind() == Uint(UintTy::U8) => Error {
+                sugg: format!("{}::from_ne_bytes({arg})", fn_sig.output()),
+                help: Some(
+                    "there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order",
+                ),
+                span,
+            },
+            // primitive => [u8; _]
+            (Uint(_) | Float(_) | Int(_), Array(t, _)) if *t.kind() == Uint(UintTy::U8) => Error {
+                sugg: format!("{input}::to_ne_bytes({arg})"),
+                help: Some(
+                    "there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order",
+                ),
+                span,
+            },
+            // char → u32
+            (Char, Uint(UintTy::U32)) => err(format!("u32::from({arg})")),
+            // u32 → char
+            (Uint(UintTy::U32), Char) => Error {
+                sugg: format!("char::from_u32_unchecked({arg})"),
+                help: Some("consider `char::from_u32(…).unwrap()`"),
+                span,
+            },
+            // uNN → iNN
+            (Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())),
+            // iNN → uNN
+            (Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())),
+            // fNN → uNN
+            (Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())),
+            // uNN → fNN
+            (Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())),
+            // bool → { x8 }
+            (Bool, Int(..) | Uint(..)) => err(format!("({arg}) as {}", fn_sig.output())),
+            // u8 → bool
+            (Uint(_), Bool) => err(format!("({arg} == 1)")),
+            _ => return None,
+        })
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> {
+    // Check each block's terminator for calls to pointer to integer transmutes
+    // in const functions or associated constants and emit a lint.
+    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+        if let TerminatorKind::Call { func, args, .. } = &terminator.kind
+            && let [Spanned { span: arg, .. }] = **args
+            && let Some((func_def_id, _)) = func.const_fn_def()
+            && self.tcx.is_intrinsic(func_def_id, sym::transmute)
+            && let span = self.body.source_info(location).span
+            && let Some(lint) = self.is_unnecessary_transmute(
+                func,
+                self.tcx.sess.source_map().span_to_snippet(arg).expect("ok"),
+                span,
+            )
+            && let Some(hir_id) = terminator.source_info.scope.lint_root(&self.body.source_scopes)
+        {
+            self.tcx.emit_node_span_lint(UNNECESSARY_TRANSMUTES, hir_id, span, lint);
+        }
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 29698b0c2e4..5b03a4987ed 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -158,6 +158,26 @@ pub(crate) struct MustNotSuspendReason {
     pub reason: String,
 }
 
+pub(crate) struct UnnecessaryTransmute {
+    pub span: Span,
+    pub sugg: String,
+    pub help: Option<&'static str>,
+}
+
+// Needed for def_path_str
+impl<'a> LintDiagnostic<'a, ()> for UnnecessaryTransmute {
+    fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
+        diag.primary_message(fluent::mir_transform_unnecessary_transmute);
+        diag.span_suggestion(
+            self.span,
+            "replace this with",
+            self.sugg,
+            lint::Applicability::MachineApplicable,
+        );
+        self.help.map(|help| diag.help(help));
+    }
+}
+
 #[derive(LintDiagnostic)]
 #[diag(mir_transform_undefined_transmute)]
 #[note]
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 4d74ecddfb0..6977d23bd0e 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -125,6 +125,7 @@ declare_passes! {
     mod check_null : CheckNull;
     mod check_packed_ref : CheckPackedRef;
     mod check_undefined_transmutes : CheckUndefinedTransmutes;
+    mod check_unnecessary_transmutes: CheckUnnecessaryTransmutes;
     // This pass is public to allow external drivers to perform MIR cleanup
     pub mod cleanup_post_borrowck : CleanupPostBorrowck;
 
@@ -391,6 +392,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
             &Lint(check_const_item_mutation::CheckConstItemMutation),
             &Lint(function_item_references::FunctionItemReferences),
             &Lint(check_undefined_transmutes::CheckUndefinedTransmutes),
+            &Lint(check_unnecessary_transmutes::CheckUnnecessaryTransmutes),
             // What we need to do constant evaluation.
             &simplify::SimplifyCfg::Initial,
             &Lint(sanity_check::SanityCheck),
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index bc92b95ce71..02c164a706c 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -246,6 +246,10 @@ pub enum AutoDiff {
     /// Print the module after running autodiff and optimizations.
     PrintModFinal,
 
+    /// Print all passes scheduled by LLVM
+    PrintPasses,
+    /// Disable extra opt run after running autodiff
+    NoPostopt,
     /// Enzyme's loose type debug helper (can cause incorrect gradients!!)
     /// Usable in cases where Enzyme errors with `can not deduce type of X`.
     LooseTypes,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 36eee5f3086..5f4695fb184 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -711,7 +711,7 @@ mod desc {
     pub(crate) const parse_list: &str = "a space-separated list of strings";
     pub(crate) const parse_list_with_polarity: &str =
         "a comma-separated list of strings, with elements beginning with + or -";
-    pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Enable`, `PrintSteps`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfter`, `PrintModFinal`, `LooseTypes`, `Inline`";
+    pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Enable`, `PrintSteps`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfter`, `PrintModFinal`, `PrintPasses`, `NoPostopt`, `LooseTypes`, `Inline`";
     pub(crate) const parse_comma_list: &str = "a comma-separated list of strings";
     pub(crate) const parse_opt_comma_list: &str = parse_comma_list;
     pub(crate) const parse_number: &str = "a number";
@@ -1360,6 +1360,8 @@ pub mod parse {
                 "PrintModBefore" => AutoDiff::PrintModBefore,
                 "PrintModAfter" => AutoDiff::PrintModAfter,
                 "PrintModFinal" => AutoDiff::PrintModFinal,
+                "NoPostopt" => AutoDiff::NoPostopt,
+                "PrintPasses" => AutoDiff::PrintPasses,
                 "LooseTypes" => AutoDiff::LooseTypes,
                 "Inline" => AutoDiff::Inline,
                 _ => {
@@ -2098,6 +2100,8 @@ options! {
         `=PrintModBefore`
         `=PrintModAfter`
         `=PrintModFinal`
+        `=PrintPasses`,
+        `=NoPostopt`
         `=LooseTypes`
         `=Inline`
         Multiple options can be combined with commas."),
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 07005215e4f..69c8b9119ab 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -516,7 +516,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("zawrs", Unstable(sym::riscv_target_feature), &[]),
     ("zba", Stable, &[]),
     ("zbb", Stable, &[]),
-    ("zbc", Stable, &[]),
+    ("zbc", Stable, &["zbkc"]), // Zbc ⊃ Zbkc
     ("zbkb", Stable, &[]),
     ("zbkc", Stable, &[]),
     ("zbkx", Stable, &[]),
@@ -545,20 +545,20 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("zknd", Stable, &[]),
     ("zkne", Stable, &[]),
     ("zknh", Stable, &[]),
-    ("zkr", Stable, &["zicsr"]),
+    ("zkr", Stable, &[]),
     ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
     ("zksed", Stable, &[]),
     ("zksh", Stable, &[]),
     ("zkt", Stable, &[]),
     ("ztso", Unstable(sym::riscv_target_feature), &[]),
-    ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]),
+    ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), // Zvbb ⊃ Zvkb
     ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
     ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
     ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]),
     ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]),
     ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]),
     ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]),
-    ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zfhmin"]),
+    ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zve32f", "zfhmin"]), // Zvfh ⊃ Zvfhmin
     ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
     ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]),
     ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]),
@@ -567,7 +567,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]),
     ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]),
     ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]),
-    ("zvknhb", Unstable(sym::riscv_target_feature), &["zve64x"]),
+    ("zvknhb", Unstable(sym::riscv_target_feature), &["zvknha", "zve64x"]), // Zvknhb ⊃ Zvknha
     ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]),
     ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]),
     ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]),
diff --git a/library/alloctests/tests/fmt.rs b/library/alloctests/tests/fmt.rs
index c13074c53b7..a20e8c62336 100644
--- a/library/alloctests/tests/fmt.rs
+++ b/library/alloctests/tests/fmt.rs
@@ -1,6 +1,7 @@
 #![deny(warnings)]
 // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
 #![allow(static_mut_refs)]
+#![cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
 
 use std::cell::RefCell;
 use std::fmt::{self, Write};
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index ac808038f89..d820965a746 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -21,6 +21,7 @@ pub(super) const fn from_u32(i: u32) -> Option<char> {
 /// Converts a `u32` to a `char`, ignoring validity. See [`char::from_u32_unchecked`].
 #[inline]
 #[must_use]
+#[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
 pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
     // SAFETY: the caller must guarantee that `i` is a valid char value.
     unsafe {
@@ -221,6 +222,7 @@ impl FromStr for char {
 }
 
 #[inline]
+#[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
 const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
     // This is an optimized version of the check
     // (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF),
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index a01efb2adeb..a7563f918a2 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -1497,6 +1497,7 @@ pub const fn forget<T: ?Sized>(_: T);
 /// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.:
 ///
 /// ```
+/// # #![cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
 /// let raw_bytes = [0x78, 0x56, 0x34, 0x12];
 ///
 /// let num = unsafe {
@@ -2429,35 +2430,35 @@ pub unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> In
 /// Stabilized as [`f16::algebraic_add`], [`f32::algebraic_add`], [`f64::algebraic_add`] and [`f128::algebraic_add`].
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn fadd_algebraic<T: Copy>(a: T, b: T) -> T;
+pub const fn fadd_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Float subtraction that allows optimizations based on algebraic rules.
 ///
 /// Stabilized as [`f16::algebraic_sub`], [`f32::algebraic_sub`], [`f64::algebraic_sub`] and [`f128::algebraic_sub`].
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn fsub_algebraic<T: Copy>(a: T, b: T) -> T;
+pub const fn fsub_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Float multiplication that allows optimizations based on algebraic rules.
 ///
 /// Stabilized as [`f16::algebraic_mul`], [`f32::algebraic_mul`], [`f64::algebraic_mul`] and [`f128::algebraic_mul`].
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn fmul_algebraic<T: Copy>(a: T, b: T) -> T;
+pub const fn fmul_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Float division that allows optimizations based on algebraic rules.
 ///
 /// Stabilized as [`f16::algebraic_div`], [`f32::algebraic_div`], [`f64::algebraic_div`] and [`f128::algebraic_div`].
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn fdiv_algebraic<T: Copy>(a: T, b: T) -> T;
+pub const fn fdiv_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Float remainder that allows optimizations based on algebraic rules.
 ///
 /// Stabilized as [`f16::algebraic_rem`], [`f32::algebraic_rem`], [`f64::algebraic_rem`] and [`f128::algebraic_rem`].
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub fn frem_algebraic<T: Copy>(a: T, b: T) -> T;
+pub const fn frem_algebraic<T: Copy>(a: T, b: T) -> T;
 
 /// Returns the number of bits set in an integer type `T`
 ///
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index e25f7091c93..b1119d4899b 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -197,16 +197,22 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     pub const MAX: f128 = 1.18973149535723176508575932662800702e+4932_f128;
 
-    /// One greater than the minimum possible normal power of 2 exponent.
+    /// One greater than the minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
-    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all normal numbers representable by this type are
+    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
     #[unstable(feature = "f128", issue = "116909")]
     pub const MIN_EXP: i32 = -16_381;
-    /// Maximum possible power of 2 exponent.
+    /// One greater than the maximum possible power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
-    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact maximum possible power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all numbers representable by this type are
+    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
     #[unstable(feature = "f128", issue = "116909")]
     pub const MAX_EXP: i32 = 16_384;
 
@@ -904,6 +910,7 @@ impl f128 {
     #[inline]
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u128 {
         // SAFETY: `u128` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -951,6 +958,7 @@ impl f128 {
     #[inline]
     #[must_use]
     #[unstable(feature = "f128", issue = "116909")]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn from_bits(v: u128) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u128` is a plain old datatype so we can always transmute from it.
@@ -1374,8 +1382,9 @@ impl f128 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_add(self, rhs: f128) -> f128 {
+    pub const fn algebraic_add(self, rhs: f128) -> f128 {
         intrinsics::fadd_algebraic(self, rhs)
     }
 
@@ -1384,8 +1393,9 @@ impl f128 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_sub(self, rhs: f128) -> f128 {
+    pub const fn algebraic_sub(self, rhs: f128) -> f128 {
         intrinsics::fsub_algebraic(self, rhs)
     }
 
@@ -1394,8 +1404,9 @@ impl f128 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_mul(self, rhs: f128) -> f128 {
+    pub const fn algebraic_mul(self, rhs: f128) -> f128 {
         intrinsics::fmul_algebraic(self, rhs)
     }
 
@@ -1404,8 +1415,9 @@ impl f128 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_div(self, rhs: f128) -> f128 {
+    pub const fn algebraic_div(self, rhs: f128) -> f128 {
         intrinsics::fdiv_algebraic(self, rhs)
     }
 
@@ -1414,8 +1426,9 @@ impl f128 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_rem(self, rhs: f128) -> f128 {
+    pub const fn algebraic_rem(self, rhs: f128) -> f128 {
         intrinsics::frem_algebraic(self, rhs)
     }
 }
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index bd00ed0f4ed..54e38d9e1a6 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -192,16 +192,22 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     pub const MAX: f16 = 6.5504e+4_f16;
 
-    /// One greater than the minimum possible normal power of 2 exponent.
+    /// One greater than the minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
-    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all normal numbers representable by this type are
+    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
     #[unstable(feature = "f16", issue = "116909")]
     pub const MIN_EXP: i32 = -13;
-    /// Maximum possible power of 2 exponent.
+    /// One greater than the maximum possible power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
-    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact maximum possible power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all numbers representable by this type are
+    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
     #[unstable(feature = "f16", issue = "116909")]
     pub const MAX_EXP: i32 = 16;
 
@@ -892,6 +898,7 @@ impl f16 {
     #[inline]
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u16 {
         // SAFETY: `u16` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -938,6 +945,7 @@ impl f16 {
     #[inline]
     #[must_use]
     #[unstable(feature = "f16", issue = "116909")]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn from_bits(v: u16) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u16` is a plain old datatype so we can always transmute from it.
@@ -1350,8 +1358,9 @@ impl f16 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_add(self, rhs: f16) -> f16 {
+    pub const fn algebraic_add(self, rhs: f16) -> f16 {
         intrinsics::fadd_algebraic(self, rhs)
     }
 
@@ -1360,8 +1369,9 @@ impl f16 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_sub(self, rhs: f16) -> f16 {
+    pub const fn algebraic_sub(self, rhs: f16) -> f16 {
         intrinsics::fsub_algebraic(self, rhs)
     }
 
@@ -1370,8 +1380,9 @@ impl f16 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_mul(self, rhs: f16) -> f16 {
+    pub const fn algebraic_mul(self, rhs: f16) -> f16 {
         intrinsics::fmul_algebraic(self, rhs)
     }
 
@@ -1380,8 +1391,9 @@ impl f16 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_div(self, rhs: f16) -> f16 {
+    pub const fn algebraic_div(self, rhs: f16) -> f16 {
         intrinsics::fdiv_algebraic(self, rhs)
     }
 
@@ -1390,8 +1402,9 @@ impl f16 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_rem(self, rhs: f16) -> f16 {
+    pub const fn algebraic_rem(self, rhs: f16) -> f16 {
         intrinsics::frem_algebraic(self, rhs)
     }
 }
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index c95ad2d0f35..e66fd3bb52b 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -443,16 +443,22 @@ impl f32 {
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX: f32 = 3.40282347e+38_f32;
 
-    /// One greater than the minimum possible normal power of 2 exponent.
+    /// One greater than the minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
-    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all normal numbers representable by this type are
+    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_EXP: i32 = -125;
-    /// Maximum possible power of 2 exponent.
+    /// One greater than the maximum possible power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
-    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact maximum possible power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all numbers representable by this type are
+    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_EXP: i32 = 128;
 
@@ -710,8 +716,7 @@ impl f32 {
     pub const fn is_sign_negative(self) -> bool {
         // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
         // applies to zeros and NaNs as well.
-        // SAFETY: This is just transmuting to get the sign bit, it's fine.
-        unsafe { mem::transmute::<f32, u32>(self) & 0x8000_0000 != 0 }
+        self.to_bits() & 0x8000_0000 != 0
     }
 
     /// Returns the least number greater than `self`.
@@ -1097,6 +1102,7 @@ impl f32 {
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u32 {
         // SAFETY: `u32` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -1142,6 +1148,7 @@ impl f32 {
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
     #[must_use]
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn from_bits(v: u32) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u32` is a plain old datatype so we can always transmute from it.
@@ -1516,8 +1523,9 @@ impl f32 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_add(self, rhs: f32) -> f32 {
+    pub const fn algebraic_add(self, rhs: f32) -> f32 {
         intrinsics::fadd_algebraic(self, rhs)
     }
 
@@ -1526,8 +1534,9 @@ impl f32 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_sub(self, rhs: f32) -> f32 {
+    pub const fn algebraic_sub(self, rhs: f32) -> f32 {
         intrinsics::fsub_algebraic(self, rhs)
     }
 
@@ -1536,8 +1545,9 @@ impl f32 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_mul(self, rhs: f32) -> f32 {
+    pub const fn algebraic_mul(self, rhs: f32) -> f32 {
         intrinsics::fmul_algebraic(self, rhs)
     }
 
@@ -1546,8 +1556,9 @@ impl f32 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_div(self, rhs: f32) -> f32 {
+    pub const fn algebraic_div(self, rhs: f32) -> f32 {
         intrinsics::fdiv_algebraic(self, rhs)
     }
 
@@ -1556,8 +1567,9 @@ impl f32 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_rem(self, rhs: f32) -> f32 {
+    pub const fn algebraic_rem(self, rhs: f32) -> f32 {
         intrinsics::frem_algebraic(self, rhs)
     }
 }
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 16b762ed6f0..2d791437b28 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -442,16 +442,22 @@ impl f64 {
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX: f64 = 1.7976931348623157e+308_f64;
 
-    /// One greater than the minimum possible normal power of 2 exponent.
+    /// One greater than the minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
-    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all normal numbers representable by this type are
+    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_EXP: i32 = -1021;
-    /// Maximum possible power of 2 exponent.
+    /// One greater than the maximum possible power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
-    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact maximum possible power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all numbers representable by this type are
+    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_EXP: i32 = 1024;
 
@@ -718,8 +724,7 @@ impl f64 {
     pub const fn is_sign_negative(self) -> bool {
         // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
         // applies to zeros and NaNs as well.
-        // SAFETY: This is just transmuting to get the sign bit, it's fine.
-        unsafe { mem::transmute::<f64, u64>(self) & Self::SIGN_MASK != 0 }
+        self.to_bits() & Self::SIGN_MASK != 0
     }
 
     #[must_use]
@@ -1095,6 +1100,7 @@ impl f64 {
                   without modifying the original"]
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     #[inline]
     pub const fn to_bits(self) -> u64 {
         // SAFETY: `u64` is a plain old datatype so we can always transmute to it.
@@ -1141,6 +1147,7 @@ impl f64 {
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
     #[must_use]
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn from_bits(v: u64) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u64` is a plain old datatype so we can always transmute from it.
@@ -1515,8 +1522,9 @@ impl f64 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_add(self, rhs: f64) -> f64 {
+    pub const fn algebraic_add(self, rhs: f64) -> f64 {
         intrinsics::fadd_algebraic(self, rhs)
     }
 
@@ -1525,8 +1533,9 @@ impl f64 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_sub(self, rhs: f64) -> f64 {
+    pub const fn algebraic_sub(self, rhs: f64) -> f64 {
         intrinsics::fsub_algebraic(self, rhs)
     }
 
@@ -1535,8 +1544,9 @@ impl f64 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_mul(self, rhs: f64) -> f64 {
+    pub const fn algebraic_mul(self, rhs: f64) -> f64 {
         intrinsics::fmul_algebraic(self, rhs)
     }
 
@@ -1545,8 +1555,9 @@ impl f64 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_div(self, rhs: f64) -> f64 {
+    pub const fn algebraic_div(self, rhs: f64) -> f64 {
         intrinsics::fdiv_algebraic(self, rhs)
     }
 
@@ -1555,8 +1566,9 @@ impl f64 {
     /// See [algebraic operators](primitive@f32#algebraic-operators) for more info.
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "float_algebraic", issue = "136469")]
+    #[rustc_const_unstable(feature = "float_algebraic", issue = "136469")]
     #[inline]
-    pub fn algebraic_rem(self, rhs: f64) -> f64 {
+    pub const fn algebraic_rem(self, rhs: f64) -> f64 {
         intrinsics::frem_algebraic(self, rhs)
     }
 }
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 05d8216ac27..8d31a7b697a 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -3675,6 +3675,7 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute them to arrays of bytes
         #[must_use = "this returns the result of the operation, \
@@ -3778,6 +3779,7 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
         #[must_use]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute to them
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 3678bb091e7..bc6cb950816 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -3523,6 +3523,7 @@ macro_rules! uint_impl {
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
+        #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute them to arrays of bytes
         #[inline]
@@ -3624,6 +3625,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
         #[must_use]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute to them
diff --git a/library/std/src/sys/env_consts.rs b/library/std/src/sys/env_consts.rs
index 018d7954db2..9683fd47cf9 100644
--- a/library/std/src/sys/env_consts.rs
+++ b/library/std/src/sys/env_consts.rs
@@ -389,6 +389,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "exe";
 }
 
+#[cfg(target_os = "zkvm")]
+pub mod os {
+    pub const FAMILY: &str = "";
+    pub const OS: &str = "";
+    pub const DLL_PREFIX: &str = "";
+    pub const DLL_SUFFIX: &str = ".elf";
+    pub const DLL_EXTENSION: &str = "elf";
+    pub const EXE_SUFFIX: &str = ".elf";
+    pub const EXE_EXTENSION: &str = "elf";
+}
+
 // The fallback when none of the other gates match.
 #[else]
 pub mod os {
diff --git a/library/std/src/sys/pal/zkvm/env.rs b/library/std/src/sys/pal/zkvm/env.rs
deleted file mode 100644
index b85153642b1..00000000000
--- a/library/std/src/sys/pal/zkvm/env.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub mod os {
-    pub const FAMILY: &str = "";
-    pub const OS: &str = "";
-    pub const DLL_PREFIX: &str = "";
-    pub const DLL_SUFFIX: &str = ".elf";
-    pub const DLL_EXTENSION: &str = "elf";
-    pub const EXE_SUFFIX: &str = ".elf";
-    pub const EXE_EXTENSION: &str = "elf";
-}
diff --git a/library/stdarch b/library/stdarch
-Subproject 4666c7376f25a265c74535585d622da3da6dfeb
+Subproject 1245618ccf5b2df7ab1ebb0279b9f3f72667016
diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs
index 6a6731cafc5..fd4918961ad 100644
--- a/src/bootstrap/src/core/build_steps/suggest.rs
+++ b/src/bootstrap/src/core/build_steps/suggest.rs
@@ -13,7 +13,6 @@ pub fn suggest(builder: &Builder<'_>, run: bool) {
     let git_config = builder.config.git_config();
     let suggestions = builder
         .tool_cmd(Tool::SuggestTests)
-        .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository)
         .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch)
         .env("SUGGEST_TESTS_MERGE_COMMIT_EMAIL", git_config.git_merge_commit_email)
         .run_capture_stdout(builder)
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 096f7de6597..d4fccc535a6 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -2064,7 +2064,6 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         }
 
         let git_config = builder.config.git_config();
-        cmd.arg("--git-repository").arg(git_config.git_repository);
         cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
         cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
         cmd.force_coloring_in_ci();
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 419976c83b1..23b623d9bab 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -2963,7 +2963,6 @@ impl Config {
 
     pub fn git_config(&self) -> GitConfig<'_> {
         GitConfig {
-            git_repository: &self.stage0_metadata.config.git_repository,
             nightly_branch: &self.stage0_metadata.config.nightly_branch,
             git_merge_commit_email: &self.stage0_metadata.config.git_merge_commit_email,
         }
diff --git a/src/bootstrap/src/utils/tests/git.rs b/src/bootstrap/src/utils/tests/git.rs
index 99e0793af46..bd40f398c7b 100644
--- a/src/bootstrap/src/utils/tests/git.rs
+++ b/src/bootstrap/src/utils/tests/git.rs
@@ -135,7 +135,6 @@ impl GitCtx {
 
     fn git_config(&self) -> GitConfig<'_> {
         GitConfig {
-            git_repository: &self.git_repo,
             nightly_branch: &self.nightly_branch,
             git_merge_commit_email: &self.merge_bot_email,
         }
diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs
index 8d53a83ea31..438cd14389c 100644
--- a/src/build_helper/src/git.rs
+++ b/src/build_helper/src/git.rs
@@ -5,7 +5,6 @@ use crate::ci::CiEnv;
 
 #[derive(Debug)]
 pub struct GitConfig<'a> {
-    pub git_repository: &'a str,
     pub nightly_branch: &'a str,
     pub git_merge_commit_email: &'a str,
 }
diff --git a/src/build_helper/src/stage0_parser.rs b/src/build_helper/src/stage0_parser.rs
index 2a0c12a1c91..2723f4aa7b9 100644
--- a/src/build_helper/src/stage0_parser.rs
+++ b/src/build_helper/src/stage0_parser.rs
@@ -20,7 +20,6 @@ pub struct Stage0Config {
     pub artifacts_server: String,
     pub artifacts_with_llvm_assertions_server: String,
     pub git_merge_commit_email: String,
-    pub git_repository: String,
     pub nightly_branch: String,
 }
 
@@ -49,7 +48,6 @@ pub fn parse_stage0_file() -> Stage0 {
                 stage0.config.artifacts_with_llvm_assertions_server = value.to_owned()
             }
             "git_merge_commit_email" => stage0.config.git_merge_commit_email = value.to_owned(),
-            "git_repository" => stage0.config.git_repository = value.to_owned(),
             "nightly_branch" => stage0.config.nightly_branch = value.to_owned(),
 
             "compiler_date" => stage0.compiler.date = value.to_owned(),
diff --git a/src/stage0 b/src/stage0
index 6e86501a72a..06080e3a8c1 100644
--- a/src/stage0
+++ b/src/stage0
@@ -2,7 +2,6 @@ dist_server=https://static.rust-lang.org
 artifacts_server=https://ci-artifacts.rust-lang.org/rustc-builds
 artifacts_with_llvm_assertions_server=https://ci-artifacts.rust-lang.org/rustc-builds-alt
 git_merge_commit_email=bors@rust-lang.org
-git_repository=rust-lang/rust
 nightly_branch=master
 
 # The configuration above this comment is editable, and can be changed
diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs
index d679084ae44..680437cce4f 100644
--- a/src/tools/bump-stage0/src/main.rs
+++ b/src/tools/bump-stage0/src/main.rs
@@ -61,7 +61,6 @@ impl Tool {
             artifacts_server,
             artifacts_with_llvm_assertions_server,
             git_merge_commit_email,
-            git_repository,
             nightly_branch,
         } = &self.config;
 
@@ -72,7 +71,6 @@ impl Tool {
             artifacts_with_llvm_assertions_server
         ));
         file_content.push_str(&format!("git_merge_commit_email={}\n", git_merge_commit_email));
-        file_content.push_str(&format!("git_repository={}\n", git_repository));
         file_content.push_str(&format!("nightly_branch={}\n", nightly_branch));
 
         file_content.push_str("\n");
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
index c82276b358e..e696896538e 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
@@ -1,7 +1,13 @@
 //@aux-build:proc_macro_attr.rs
 
 #![warn(clippy::blocks_in_conditions)]
-#![allow(unused, clippy::needless_if, clippy::missing_transmute_annotations)]
+#![allow(
+    unused,
+    unnecessary_transmutes,
+    clippy::let_and_return,
+    clippy::needless_if,
+    clippy::missing_transmute_annotations
+)]
 #![warn(clippy::nonminimal_bool)]
 
 macro_rules! blocky {
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.rs b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
index 6a4a7c62106..8c8f3249b8a 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.rs
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
@@ -1,7 +1,13 @@
 //@aux-build:proc_macro_attr.rs
 
 #![warn(clippy::blocks_in_conditions)]
-#![allow(unused, clippy::needless_if, clippy::missing_transmute_annotations)]
+#![allow(
+    unused,
+    unnecessary_transmutes,
+    clippy::let_and_return,
+    clippy::needless_if,
+    clippy::missing_transmute_annotations
+)]
 #![warn(clippy::nonminimal_bool)]
 
 macro_rules! blocky {
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.stderr b/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
index e57eca5dcee..41ff59c683e 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
@@ -1,5 +1,5 @@
 error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> tests/ui/blocks_in_conditions.rs:25:5
+  --> tests/ui/blocks_in_conditions.rs:31:5
    |
 LL | /     if {
 LL | |
@@ -20,13 +20,13 @@ LL ~     }; if res {
    |
 
 error: omit braces around single expression condition
-  --> tests/ui/blocks_in_conditions.rs:37:8
+  --> tests/ui/blocks_in_conditions.rs:43:8
    |
 LL |     if { true } { 6 } else { 10 }
    |        ^^^^^^^^ help: try: `true`
 
 error: this boolean expression can be simplified
-  --> tests/ui/blocks_in_conditions.rs:43:8
+  --> tests/ui/blocks_in_conditions.rs:49:8
    |
 LL |     if true && x == 3 { 6 } else { 10 }
    |        ^^^^^^^^^^^^^^ help: try: `x == 3`
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1782.rs b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
index 4a1886c08af..776b0a93bf7 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1782.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![allow(dead_code, unused_variables, invalid_null_arguments)]
+#![allow(dead_code, unused_variables, invalid_null_arguments, unnecessary_transmutes)]
 #![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)]
 
 /// Should not trigger an ICE in `SpanlessEq` / `consts::constant`
diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs
index 8c8674ac356..2b8b6c539ad 100644
--- a/src/tools/clippy/tests/ui/transmute.rs
+++ b/src/tools/clippy/tests/ui/transmute.rs
@@ -3,6 +3,7 @@
 #![allow(
     dead_code,
     clippy::borrow_as_ptr,
+    unnecessary_transmutes,
     clippy::needless_lifetimes,
     clippy::missing_transmute_annotations
 )]
diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr
index 4219e09d2ab..1bb70151965 100644
--- a/src/tools/clippy/tests/ui/transmute.stderr
+++ b/src/tools/clippy/tests/ui/transmute.stderr
@@ -1,5 +1,5 @@
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:32:27
+  --> tests/ui/transmute.rs:33:27
    |
 LL |         let _: *const T = core::mem::transmute(t);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T`
@@ -8,61 +8,61 @@ LL |         let _: *const T = core::mem::transmute(t);
    = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:35:25
+  --> tests/ui/transmute.rs:36:25
    |
 LL |         let _: *mut T = core::mem::transmute(t);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:38:27
+  --> tests/ui/transmute.rs:39:27
    |
 LL |         let _: *const U = core::mem::transmute(t);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U`
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:46:27
+  --> tests/ui/transmute.rs:47:27
    |
 LL |         let _: Vec<i32> = core::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:49:27
+  --> tests/ui/transmute.rs:50:27
    |
 LL |         let _: Vec<i32> = core::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:52:27
+  --> tests/ui/transmute.rs:53:27
    |
 LL |         let _: Vec<i32> = std::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:55:27
+  --> tests/ui/transmute.rs:56:27
    |
 LL |         let _: Vec<i32> = std::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:58:27
+  --> tests/ui/transmute.rs:59:27
    |
 LL |         let _: Vec<i32> = my_transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from an integer to a pointer
-  --> tests/ui/transmute.rs:61:31
+  --> tests/ui/transmute.rs:62:31
    |
 LL |         let _: *const usize = std::mem::transmute(5_isize);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize`
 
 error: transmute from an integer to a pointer
-  --> tests/ui/transmute.rs:66:31
+  --> tests/ui/transmute.rs:67:31
    |
 LL |         let _: *const usize = std::mem::transmute(1 + 1usize);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize`
 
 error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`)
-  --> tests/ui/transmute.rs:98:24
+  --> tests/ui/transmute.rs:99:24
    |
 LL |         let _: Usize = core::mem::transmute(int_const_ptr);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,25 +71,25 @@ LL |         let _: Usize = core::mem::transmute(int_const_ptr);
    = help: to override `-D warnings` add `#[allow(clippy::crosspointer_transmute)]`
 
 error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
-  --> tests/ui/transmute.rs:101:24
+  --> tests/ui/transmute.rs:102:24
    |
 LL |         let _: Usize = core::mem::transmute(int_mut_ptr);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
-  --> tests/ui/transmute.rs:104:31
+  --> tests/ui/transmute.rs:105:31
    |
 LL |         let _: *const Usize = core::mem::transmute(my_int());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
-  --> tests/ui/transmute.rs:107:29
+  --> tests/ui/transmute.rs:108:29
    |
 LL |         let _: *mut Usize = core::mem::transmute(my_int());
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a `u8` to a `bool`
-  --> tests/ui/transmute.rs:114:28
+  --> tests/ui/transmute.rs:115:28
    |
 LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
@@ -98,7 +98,7 @@ LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]`
 
 error: transmute from a `u16` to a `f16`
-  --> tests/ui/transmute.rs:121:31
+  --> tests/ui/transmute.rs:122:31
    |
 LL |         let _: f16 = unsafe { std::mem::transmute(0_u16) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)`
@@ -107,97 +107,97 @@ LL |         let _: f16 = unsafe { std::mem::transmute(0_u16) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_float)]`
 
 error: transmute from a `i16` to a `f16`
-  --> tests/ui/transmute.rs:124:31
+  --> tests/ui/transmute.rs:125:31
    |
 LL |         let _: f16 = unsafe { std::mem::transmute(0_i16) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_i16 as u16)`
 
 error: transmute from a `u32` to a `f32`
-  --> tests/ui/transmute.rs:127:31
+  --> tests/ui/transmute.rs:128:31
    |
 LL |         let _: f32 = unsafe { std::mem::transmute(0_u32) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
 
 error: transmute from a `i32` to a `f32`
-  --> tests/ui/transmute.rs:130:31
+  --> tests/ui/transmute.rs:131:31
    |
 LL |         let _: f32 = unsafe { std::mem::transmute(0_i32) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)`
 
 error: transmute from a `u64` to a `f64`
-  --> tests/ui/transmute.rs:133:31
+  --> tests/ui/transmute.rs:134:31
    |
 LL |         let _: f64 = unsafe { std::mem::transmute(0_u64) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)`
 
 error: transmute from a `i64` to a `f64`
-  --> tests/ui/transmute.rs:136:31
+  --> tests/ui/transmute.rs:137:31
    |
 LL |         let _: f64 = unsafe { std::mem::transmute(0_i64) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
 
 error: transmute from a `u128` to a `f128`
-  --> tests/ui/transmute.rs:139:32
+  --> tests/ui/transmute.rs:140:32
    |
 LL |         let _: f128 = unsafe { std::mem::transmute(0_u128) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_u128)`
 
 error: transmute from a `i128` to a `f128`
-  --> tests/ui/transmute.rs:142:32
+  --> tests/ui/transmute.rs:143:32
    |
 LL |         let _: f128 = unsafe { std::mem::transmute(0_i128) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
 
 error: transmute from a `u16` to a `f16`
-  --> tests/ui/transmute.rs:147:39
+  --> tests/ui/transmute.rs:148:39
    |
 LL |         const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) };
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)`
 
 error: transmute from a `u32` to a `f32`
-  --> tests/ui/transmute.rs:150:39
+  --> tests/ui/transmute.rs:151:39
    |
 LL |         const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) };
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
 
 error: transmute from a `i64` to a `f64`
-  --> tests/ui/transmute.rs:153:39
+  --> tests/ui/transmute.rs:154:39
    |
 LL |         const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) };
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
 
 error: transmute from a `i128` to a `f128`
-  --> tests/ui/transmute.rs:156:41
+  --> tests/ui/transmute.rs:157:41
    |
 LL |         const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
 
 error: transmute from a `i16` to a `f16`
-  --> tests/ui/transmute.rs:160:22
+  --> tests/ui/transmute.rs:161:22
    |
 LL |             unsafe { std::mem::transmute(v) }
    |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(v as u16)`
 
 error: transmute from a `i32` to a `f32`
-  --> tests/ui/transmute.rs:165:22
+  --> tests/ui/transmute.rs:166:22
    |
 LL |             unsafe { std::mem::transmute(v) }
    |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(v as u32)`
 
 error: transmute from a `u64` to a `f64`
-  --> tests/ui/transmute.rs:170:22
+  --> tests/ui/transmute.rs:171:22
    |
 LL |             unsafe { std::mem::transmute(v) }
    |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(v)`
 
 error: transmute from a `u128` to a `f128`
-  --> tests/ui/transmute.rs:175:22
+  --> tests/ui/transmute.rs:176:22
    |
 LL |             unsafe { std::mem::transmute(v) }
    |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(v)`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:184:30
+  --> tests/ui/transmute.rs:185:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
@@ -206,121 +206,121 @@ LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:187:30
+  --> tests/ui/transmute.rs:188:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:190:31
+  --> tests/ui/transmute.rs:191:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:193:30
+  --> tests/ui/transmute.rs:194:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:196:30
+  --> tests/ui/transmute.rs:197:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:199:31
+  --> tests/ui/transmute.rs:200:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `f16` to a `[u8; 2]`
-  --> tests/ui/transmute.rs:202:30
+  --> tests/ui/transmute.rs:203:30
    |
 LL |             let _: [u8; 2] = std::mem::transmute(0.0f16);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
 
 error: transmute from a `f32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:205:30
+  --> tests/ui/transmute.rs:206:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0.0f32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
 
 error: transmute from a `f64` to a `[u8; 8]`
-  --> tests/ui/transmute.rs:208:30
+  --> tests/ui/transmute.rs:209:30
    |
 LL |             let _: [u8; 8] = std::mem::transmute(0.0f64);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
 
 error: transmute from a `f128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:211:31
+  --> tests/ui/transmute.rs:212:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0.0f128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:217:30
+  --> tests/ui/transmute.rs:218:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:220:30
+  --> tests/ui/transmute.rs:221:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:223:31
+  --> tests/ui/transmute.rs:224:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:226:30
+  --> tests/ui/transmute.rs:227:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:229:30
+  --> tests/ui/transmute.rs:230:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:232:31
+  --> tests/ui/transmute.rs:233:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `f16` to a `[u8; 2]`
-  --> tests/ui/transmute.rs:235:30
+  --> tests/ui/transmute.rs:236:30
    |
 LL |             let _: [u8; 2] = std::mem::transmute(0.0f16);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
 
 error: transmute from a `f32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:238:30
+  --> tests/ui/transmute.rs:239:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0.0f32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
 
 error: transmute from a `f64` to a `[u8; 8]`
-  --> tests/ui/transmute.rs:241:30
+  --> tests/ui/transmute.rs:242:30
    |
 LL |             let _: [u8; 8] = std::mem::transmute(0.0f64);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
 
 error: transmute from a `f128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:244:31
+  --> tests/ui/transmute.rs:245:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0.0f128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:253:28
+  --> tests/ui/transmute.rs:254:28
    |
 LL |     let _: &str = unsafe { std::mem::transmute(B) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -329,13 +329,13 @@ LL |     let _: &str = unsafe { std::mem::transmute(B) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]`
 
 error: transmute from a `&mut [u8]` to a `&mut str`
-  --> tests/ui/transmute.rs:256:32
+  --> tests/ui/transmute.rs:257:32
    |
 LL |     let _: &mut str = unsafe { std::mem::transmute(mb) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:259:30
+  --> tests/ui/transmute.rs:260:30
    |
 LL |     const _: &str = unsafe { std::mem::transmute(B) };
    |                              ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
index 1f97b997eaa..844445907d7 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_float_to_int)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 #![feature(f128)]
 #![feature(f16)]
 
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.rs b/src/tools/clippy/tests/ui/transmute_float_to_int.rs
index 788a7e1026c..a1f3b15bbfe 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.rs
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_float_to_int)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 #![feature(f128)]
 #![feature(f16)]
 
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char.fixed b/src/tools/clippy/tests/ui/transmute_int_to_char.fixed
index b5425a2e9e8..28644aa9ebb 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_char.fixed
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_int_to_char)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 
 fn int_to_char() {
     let _: char = unsafe { std::char::from_u32(0_u32).unwrap() };
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char.rs b/src/tools/clippy/tests/ui/transmute_int_to_char.rs
index b24bb177c9f..8c83ecc8914 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_char.rs
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_int_to_char)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 
 fn int_to_char() {
     let _: char = unsafe { std::mem::transmute(0_u32) };
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed
index e525751e306..e6e09a2be4b 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed
@@ -1,7 +1,7 @@
 #![no_std]
 #![feature(lang_items)]
 #![warn(clippy::transmute_int_to_char)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 
 use core::panic::PanicInfo;
 
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs
index 7cb508ceaf3..0f2106df00e 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs
@@ -1,7 +1,7 @@
 #![no_std]
 #![feature(lang_items)]
 #![warn(clippy::transmute_int_to_char)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 
 use core::panic::PanicInfo;
 
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index de93e2b99ee..e0132056d6c 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -399,7 +399,6 @@ pub struct Config {
     pub nocapture: bool,
 
     // Needed both to construct build_helper::git::GitConfig
-    pub git_repository: String,
     pub nightly_branch: String,
     pub git_merge_commit_email: String,
 
@@ -514,7 +513,6 @@ impl Config {
 
     pub fn git_config(&self) -> GitConfig<'_> {
         GitConfig {
-            git_repository: &self.git_repository,
             nightly_branch: &self.nightly_branch,
             git_merge_commit_email: &self.git_merge_commit_email,
         }
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 2525e0adc83..e7e5ff0ab00 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -175,7 +175,6 @@ impl ConfigBuilder {
             self.host.as_deref().unwrap_or("x86_64-unknown-linux-gnu"),
             "--target",
             self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"),
-            "--git-repository=",
             "--nightly-branch=",
             "--git-merge-commit-email=",
             "--minicore-path=",
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 7948a273c1e..0a3888a7d50 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -188,7 +188,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "run tests which rely on commit version being compiled into the binaries",
         )
         .optopt("", "edition", "default Rust edition", "EDITION")
-        .reqopt("", "git-repository", "name of the git repository", "ORG/REPO")
         .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH")
         .reqopt(
             "",
@@ -440,7 +439,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
         nocapture: matches.opt_present("no-capture"),
 
-        git_repository: matches.opt_str("git-repository").unwrap(),
         nightly_branch: matches.opt_str("nightly-branch").unwrap(),
         git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(),
 
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index a3525dcc77a..7d60a7e5c48 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -392,32 +392,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             #[rustfmt::skip]
-            | "fadd_algebraic"
-            | "fsub_algebraic"
-            | "fmul_algebraic"
-            | "fdiv_algebraic"
-            | "frem_algebraic"
-            => {
-                let [a, b] = check_intrinsic_arg_count(args)?;
-                let a = this.read_immediate(a)?;
-                let b = this.read_immediate(b)?;
-                let op = match intrinsic_name {
-                    "fadd_algebraic" => mir::BinOp::Add,
-                    "fsub_algebraic" => mir::BinOp::Sub,
-                    "fmul_algebraic" => mir::BinOp::Mul,
-                    "fdiv_algebraic" => mir::BinOp::Div,
-                    "frem_algebraic" => mir::BinOp::Rem,
-                    _ => bug!(),
-                };
-                let res = this.binary_op(op, &a, &b)?;
-                // `binary_op` already called `generate_nan` if needed.
-                // Apply a relative error of 4ULP to simulate non-deterministic precision loss
-                // due to optimizations.
-                let res = apply_random_float_error_to_imm(this, res, 2 /* log2(4) */)?;
-                this.write_immediate(*res, dest)?;
-            }
-
-            #[rustfmt::skip]
             | "fadd_fast"
             | "fsub_fast"
             | "fmul_fast"
diff --git a/src/tools/miri/tests/fail/validity/invalid_bool.rs b/src/tools/miri/tests/fail/validity/invalid_bool.rs
index 4f11bb2629f..bd448af834d 100644
--- a/src/tools/miri/tests/fail/validity/invalid_bool.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_bool.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 fn main() {
     let _b = unsafe { std::mem::transmute::<u8, bool>(2) }; //~ ERROR: expected a boolean
 }
diff --git a/src/tools/miri/tests/fail/validity/invalid_bool_op.rs b/src/tools/miri/tests/fail/validity/invalid_bool_op.rs
index fe9bb3bed7f..0cbe2d76dc6 100644
--- a/src/tools/miri/tests/fail/validity/invalid_bool_op.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_bool_op.rs
@@ -2,6 +2,7 @@
 // Make sure we find these even with many checks disabled.
 //@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
 
+#![allow(unnecessary_transmutes)]
 fn main() {
     let b = unsafe { std::mem::transmute::<u8, bool>(2) };
     let _x = b == std::hint::black_box(true); //~ ERROR: interpreting an invalid 8-bit value as a bool
diff --git a/src/tools/miri/tests/fail/validity/invalid_char.rs b/src/tools/miri/tests/fail/validity/invalid_char.rs
index 568892e5910..d57c933dac1 100644
--- a/src/tools/miri/tests/fail/validity/invalid_char.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_char.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 fn main() {
     assert!(std::char::from_u32(-1_i32 as u32).is_none());
     let _val = match unsafe { std::mem::transmute::<i32, char>(-1) } {
diff --git a/src/tools/miri/tests/fail/validity/invalid_char_op.rs b/src/tools/miri/tests/fail/validity/invalid_char_op.rs
index 69924822944..e3a5f837e18 100644
--- a/src/tools/miri/tests/fail/validity/invalid_char_op.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_char_op.rs
@@ -2,6 +2,7 @@
 // Make sure we find these even with many checks disabled.
 //@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
 
+#![allow(unnecessary_transmutes)]
 fn main() {
     let c = 0xFFFFFFu32;
     assert!(std::char::from_u32(c).is_none());
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index cd60b6bd563..575d70579a4 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -6,6 +6,7 @@
 #![feature(f16)]
 #![allow(arithmetic_overflow)]
 #![allow(internal_features)]
+#![allow(unnecessary_transmutes)]
 
 use std::any::type_name;
 use std::cmp::min;
diff --git a/src/tools/miri/tests/pass/issues/issue-miri-184.rs b/src/tools/miri/tests/pass/issues/issue-miri-184.rs
index 39c841403ef..964d850298f 100644
--- a/src/tools/miri/tests/pass/issues/issue-miri-184.rs
+++ b/src/tools/miri/tests/pass/issues/issue-miri-184.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 pub fn main() {
     let bytes: [u8; 8] = unsafe { ::std::mem::transmute(0u64) };
     let _val: &[u8] = &bytes;
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
index a629e2acfe9..882b5e3f795 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
@@ -368,7 +368,7 @@ unsafe fn load_m256i_word<T>(data: &[T], word_index: usize) -> __m256i {
 #[target_feature(enable = "avx512f")]
 unsafe fn load_m512i_word<T>(data: &[T], word_index: usize) -> __m512i {
     let byte_offset = word_index * 64 / size_of::<T>();
-    let pointer = data.as_ptr().add(byte_offset) as *const i32;
+    let pointer = data.as_ptr().add(byte_offset) as *const __m512i;
     _mm512_loadu_si512(black_box(pointer))
 }
 
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
index 6f7ab3b3c9f..be3f961e10f 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
@@ -1,5 +1,6 @@
 // We're testing x86 target specific features
 //@only-target: x86_64 i686
+#![allow(unnecessary_transmutes)]
 
 #[cfg(target_arch = "x86")]
 use std::arch::x86::*;
diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs
index ee212af3626..d84f8e9fa1b 100644
--- a/src/tools/suggest-tests/src/main.rs
+++ b/src/tools/suggest-tests/src/main.rs
@@ -6,7 +6,6 @@ use suggest_tests::get_suggestions;
 fn main() -> ExitCode {
     let modified_files = get_git_modified_files(
         &GitConfig {
-            git_repository: &env("SUGGEST_TESTS_GIT_REPOSITORY"),
             nightly_branch: &env("SUGGEST_TESTS_NIGHTLY_BRANCH"),
             git_merge_commit_email: &env("SUGGEST_TESTS_MERGE_COMMIT_EMAIL"),
         },
diff --git a/tests/codegen/autodiff/identical_fnc.rs b/tests/codegen/autodiff/identical_fnc.rs
new file mode 100644
index 00000000000..1c3277f52b4
--- /dev/null
+++ b/tests/codegen/autodiff/identical_fnc.rs
@@ -0,0 +1,45 @@
+//@ compile-flags: -Zautodiff=Enable -C opt-level=3  -Clto=fat
+//@ no-prefer-dynamic
+//@ needs-enzyme
+//
+// Each autodiff invocation creates a new placeholder function, which we will replace on llvm-ir
+// level. If a user tries to differentiate two identical functions within the same compilation unit,
+// then LLVM might merge them in release mode before AD. In that case we can't rewrite one of the
+// merged placeholder function anymore, and compilation would fail. We prevent this by disabling
+// LLVM's merge_function pass before AD. Here we implicetely test that our solution keeps working.
+// We also explicetly test that we keep running merge_function after AD, by checking for two
+// identical function calls in the LLVM-IR, while having two different calls in the Rust code.
+#![feature(autodiff)]
+
+use std::autodiff::autodiff;
+
+#[autodiff(d_square, Reverse, Duplicated, Active)]
+fn square(x: &f64) -> f64 {
+    x * x
+}
+
+#[autodiff(d_square2, Reverse, Duplicated, Active)]
+fn square2(x: &f64) -> f64 {
+    x * x
+}
+
+// CHECK:; identical_fnc::main
+// CHECK-NEXT:; Function Attrs:
+// CHECK-NEXT:define internal void @_ZN13identical_fnc4main17hf4dbc69c8d2f9130E()
+// CHECK-NEXT:start:
+// CHECK-NOT:br
+// CHECK-NOT:ret
+// CHECK:; call identical_fnc::d_square
+// CHECK-NEXT:  call fastcc void @_ZN13identical_fnc8d_square17h4c364207a2f8e06dE(double %x.val, ptr noalias noundef nonnull align 8 dereferenceable(8) %dx1)
+// CHECK-NEXT:; call identical_fnc::d_square
+// CHECK-NEXT:  call fastcc void @_ZN13identical_fnc8d_square17h4c364207a2f8e06dE(double %x.val, ptr noalias noundef nonnull align 8 dereferenceable(8) %dx2)
+
+fn main() {
+    let x = std::hint::black_box(3.0);
+    let mut dx1 = std::hint::black_box(1.0);
+    let mut dx2 = std::hint::black_box(1.0);
+    let _ = d_square(&x, &mut dx1, 1.0);
+    let _ = d_square2(&x, &mut dx2, 1.0);
+    assert_eq!(dx1, 6.0);
+    assert_eq!(dx2, 6.0);
+}
diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs
index 9187de56362..20f1a9aae70 100644
--- a/tests/ui/consts/const-eval/raw-bytes.rs
+++ b/tests/ui/consts/const-eval/raw-bytes.rs
@@ -2,7 +2,7 @@
 //@ ignore-endian-big
 // ignore-tidy-linelength
 //@ normalize-stderr: "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼" -> "╾ALLOC_ID$1╼"
-#![allow(invalid_value)]
+#![allow(invalid_value, unnecessary_transmutes)]
 #![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)]
 
 use std::mem;
diff --git a/tests/ui/consts/const-eval/transmute-const-promotion.rs b/tests/ui/consts/const-eval/transmute-const-promotion.rs
index 1f0240d4b5a..840334f43c0 100644
--- a/tests/ui/consts/const-eval/transmute-const-promotion.rs
+++ b/tests/ui/consts/const-eval/transmute-const-promotion.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 use std::mem;
 
 fn main() {
diff --git a/tests/ui/consts/const-eval/transmute-const-promotion.stderr b/tests/ui/consts/const-eval/transmute-const-promotion.stderr
index 3603db03bb2..eb2fed091c3 100644
--- a/tests/ui/consts/const-eval/transmute-const-promotion.stderr
+++ b/tests/ui/consts/const-eval/transmute-const-promotion.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/transmute-const-promotion.rs:4:37
+  --> $DIR/transmute-const-promotion.rs:5:37
    |
 LL |     let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
    |            ------------             ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
diff --git a/tests/ui/consts/const-eval/transmute-const.rs b/tests/ui/consts/const-eval/transmute-const.rs
index 1cfad00ca76..fb6cb77675f 100644
--- a/tests/ui/consts/const-eval/transmute-const.rs
+++ b/tests/ui/consts/const-eval/transmute-const.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 use std::mem;
 
 static FOO: bool = unsafe { mem::transmute(3u8) };
diff --git a/tests/ui/consts/const-eval/transmute-const.stderr b/tests/ui/consts/const-eval/transmute-const.stderr
index d72289487d7..35a5cabaa67 100644
--- a/tests/ui/consts/const-eval/transmute-const.stderr
+++ b/tests/ui/consts/const-eval/transmute-const.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/transmute-const.rs:3:1
+  --> $DIR/transmute-const.rs:4:1
    |
 LL | static FOO: bool = unsafe { mem::transmute(3u8) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
diff --git a/tests/ui/consts/const-eval/ub-enum.rs b/tests/ui/consts/const-eval/ub-enum.rs
index 5be444e667a..a5255ef95aa 100644
--- a/tests/ui/consts/const-eval/ub-enum.rs
+++ b/tests/ui/consts/const-eval/ub-enum.rs
@@ -3,7 +3,7 @@
 //@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
 //@ normalize-stderr: "0x0+" -> "0x0"
 #![feature(never_type)]
-#![allow(invalid_value)]
+#![allow(invalid_value, unnecessary_transmutes)]
 
 use std::mem;
 
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs
index a071a44272b..4e2defc1a09 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-linelength
-#![allow(unused)]
+#![allow(unused, unnecessary_transmutes)]
 #![feature(ptr_metadata)]
 
 use std::{ptr, mem};
diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
index 481f2ff88df..c3bd8301d5c 100644
--- a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
+++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
@@ -2,6 +2,7 @@
 //@ [no_flag] check-pass
 //@ [with_flag] compile-flags: -Zextra-const-ub-checks
 #![feature(never_type)]
+#![allow(unnecessary_transmutes)]
 
 use std::mem::transmute;
 use std::ptr::addr_of;
diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
index 0100aafb6b7..ea3b0e70b82 100644
--- a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
+++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
@@ -1,11 +1,11 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:29:20
+  --> $DIR/detect-extra-ub.rs:30:20
    |
 LL |     let _x: bool = transmute(3u8);
    |                    ^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:35:21
+  --> $DIR/detect-extra-ub.rs:36:21
    |
 LL |     let _x: usize = transmute(&3u8);
    |                     ^^^^^^^^^^^^^^^ constructing invalid value: encountered a pointer, but expected an integer
@@ -14,7 +14,7 @@ LL |     let _x: usize = transmute(&3u8);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:41:28
+  --> $DIR/detect-extra-ub.rs:42:28
    |
 LL |     let _x: PtrSizedEnum = transmute(&3u8);
    |                            ^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
@@ -23,7 +23,7 @@ LL |     let _x: PtrSizedEnum = transmute(&3u8);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:48:30
+  --> $DIR/detect-extra-ub.rs:49:30
    |
 LL |     let _x: (usize, usize) = transmute(x);
    |                              ^^^^^^^^^^^^ constructing invalid value at .0: encountered a pointer, but expected an integer
@@ -32,19 +32,19 @@ LL |     let _x: (usize, usize) = transmute(x);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:54:20
+  --> $DIR/detect-extra-ub.rs:55:20
    |
 LL |     let _x: &u32 = transmute(&[0u8; 4]);
    |                    ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:62:13
+  --> $DIR/detect-extra-ub.rs:63:13
    |
 LL |     let v = *addr_of!(data).cast::<UninhDiscriminant>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:82:16
+  --> $DIR/detect-extra-ub.rs:83:16
    |
 LL |     let _val = *(&mem as *const Align as *const [*const u8; 2]);
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a partial pointer or a mix of pointers
@@ -53,7 +53,7 @@ LL |     let _val = *(&mem as *const Align as *const [*const u8; 2]);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:97:16
+  --> $DIR/detect-extra-ub.rs:98:16
    |
 LL |     let _val = &*slice;
    |                ^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
diff --git a/tests/ui/consts/issue-69532.rs b/tests/ui/consts/issue-69532.rs
index 285cfe7213b..43ab1d6cca7 100644
--- a/tests/ui/consts/issue-69532.rs
+++ b/tests/ui/consts/issue-69532.rs
@@ -1,8 +1,8 @@
 //@ run-pass
 
 const fn make_nans() -> (f64, f64, f32, f32) {
-    let nan1: f64 = unsafe { std::mem::transmute(0x7FF0_0001_0000_0001u64) };
-    let nan2: f64 = unsafe { std::mem::transmute(0x7FF0_0000_0000_0001u64) };
+    let nan1 = f64::from_bits(0x7FF0_0001_0000_0001);
+    let nan2 = f64::from_bits(0x7FF0_0000_0000_0001);
 
     let nan1_32 = nan1 as f32;
     let nan2_32 = nan2 as f32;
diff --git a/tests/ui/issues/issue-25746-bool-transmute.rs b/tests/ui/issues/issue-25746-bool-transmute.rs
index f8cdc980daa..046dcf83f62 100644
--- a/tests/ui/issues/issue-25746-bool-transmute.rs
+++ b/tests/ui/issues/issue-25746-bool-transmute.rs
@@ -1,4 +1,5 @@
 //@ run-pass
+#![allow(unnecessary_transmutes)]
 use std::mem::transmute;
 
 fn main() {
diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs
index 7948f0d86d0..f40f06a0d36 100644
--- a/tests/ui/lint/invalid_null_args.rs
+++ b/tests/ui/lint/invalid_null_args.rs
@@ -1,19 +1,19 @@
 // check-fail
 // run-rustfix
+#![allow(unnecessary_transmutes)]
 
-use std::ptr;
-use std::mem;
+use std::{mem, ptr};
 
 unsafe fn null_ptr() {
     ptr::write(
-    //~^ ERROR calling this function with a null pointer is undefined behavior
+        //~^ ERROR calling this function with a null pointer is undefined behavior
         ptr::null_mut() as *mut u32,
         mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
     );
 
     let null_ptr = ptr::null_mut();
     ptr::write(
-    //~^ ERROR calling this function with a null pointer is undefined behavior
+        //~^ ERROR calling this function with a null pointer is undefined behavior
         null_ptr as *mut u32,
         mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
     );
@@ -38,10 +38,10 @@ unsafe fn null_ptr() {
     ptr::copy_nonoverlapping::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
     //~^ ERROR calling this function with a null pointer is undefined behavior
     ptr::copy_nonoverlapping::<usize>(
-    //~^ ERROR calling this function with a null pointer is undefined behavior
+        //~^ ERROR calling this function with a null pointer is undefined behavior
         ptr::NonNull::dangling().as_ptr(),
         ptr::null_mut(),
-        0
+        0,
     );
 
     #[derive(Copy, Clone)]
diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr
index f95bc2afa82..11c6270cfb7 100644
--- a/tests/ui/lint/invalid_null_args.stderr
+++ b/tests/ui/lint/invalid_null_args.stderr
@@ -117,7 +117,7 @@ LL | |
 LL | |         ptr::NonNull::dangling().as_ptr(),
 LL | |         ptr::null_mut(),
    | |         --------------- null pointer originates from here
-LL | |         0
+LL | |         0,
 LL | |     );
    | |_____^
    |
diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs
index 0d19d5b5347..b2ef27b833b 100644
--- a/tests/ui/lint/lint-ctypes-enum.rs
+++ b/tests/ui/lint/lint-ctypes-enum.rs
@@ -2,6 +2,8 @@
 #![deny(improper_ctypes)]
 #![feature(ptr_internals)]
 #![feature(transparent_unions)]
+#![feature(repr128)]
+#![allow(incomplete_features)]
 
 use std::num;
 
@@ -40,6 +42,20 @@ enum Isize {
     C,
 }
 
+#[repr(u128)]
+enum U128 {
+    A,
+    B,
+    C,
+}
+
+#[repr(i128)]
+enum I128 {
+    A,
+    B,
+    C,
+}
+
 #[repr(transparent)]
 struct TransparentStruct<T>(T, std::marker::PhantomData<Z>);
 
@@ -71,6 +87,8 @@ extern "C" {
     fn repr_c(x: ReprC);
     fn repr_u8(x: U8);
     fn repr_isize(x: Isize);
+    fn repr_u128(x: U128); //~ ERROR `extern` block uses type `U128`
+    fn repr_i128(x: I128); //~ ERROR `extern` block uses type `I128`
     fn option_ref(x: Option<&'static u8>);
     fn option_fn(x: Option<extern "C" fn()>);
     fn option_nonnull(x: Option<std::ptr::NonNull<u8>>);
diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr
index a491bd19605..d5fc844f756 100644
--- a/tests/ui/lint/lint-ctypes-enum.stderr
+++ b/tests/ui/lint/lint-ctypes-enum.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `U`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:68:14
+  --> $DIR/lint-ctypes-enum.rs:84:14
    |
 LL |     fn uf(x: U);
    |              ^ not FFI-safe
@@ -7,7 +7,7 @@ LL |     fn uf(x: U);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:9:1
+  --> $DIR/lint-ctypes-enum.rs:11:1
    |
 LL | enum U {
    | ^^^^^^
@@ -18,7 +18,7 @@ LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `B`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:69:14
+  --> $DIR/lint-ctypes-enum.rs:85:14
    |
 LL |     fn bf(x: B);
    |              ^ not FFI-safe
@@ -26,13 +26,13 @@ LL |     fn bf(x: B);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:12:1
+  --> $DIR/lint-ctypes-enum.rs:14:1
    |
 LL | enum B {
    | ^^^^^^
 
 error: `extern` block uses type `T`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:70:14
+  --> $DIR/lint-ctypes-enum.rs:86:14
    |
 LL |     fn tf(x: T);
    |              ^ not FFI-safe
@@ -40,13 +40,39 @@ LL |     fn tf(x: T);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:16:1
+  --> $DIR/lint-ctypes-enum.rs:18:1
    |
 LL | enum T {
    | ^^^^^^
 
+error: `extern` block uses type `U128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:90:21
+   |
+LL |     fn repr_u128(x: U128);
+   |                     ^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
+note: the type is defined here
+  --> $DIR/lint-ctypes-enum.rs:46:1
+   |
+LL | enum U128 {
+   | ^^^^^^^^^
+
+error: `extern` block uses type `I128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:91:21
+   |
+LL |     fn repr_i128(x: I128);
+   |                     ^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
+note: the type is defined here
+  --> $DIR/lint-ctypes-enum.rs:53:1
+   |
+LL | enum I128 {
+   | ^^^^^^^^^
+
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:82:31
+  --> $DIR/lint-ctypes-enum.rs:100:31
    |
 LL |     fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -54,7 +80,7 @@ LL |     fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:89:31
+  --> $DIR/lint-ctypes-enum.rs:107:31
    |
 LL |     fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -62,7 +88,7 @@ LL |     fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Option<TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:94:36
+  --> $DIR/lint-ctypes-enum.rs:112:36
    |
 LL |     fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -71,7 +97,7 @@ LL |     fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<Rust<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:96:28
+  --> $DIR/lint-ctypes-enum.rs:114:28
    |
 LL |     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -80,7 +106,7 @@ LL |     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<u8>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:97:21
+  --> $DIR/lint-ctypes-enum.rs:115:21
    |
 LL |     fn option_u8(x: Option<u8>);
    |                     ^^^^^^^^^^ not FFI-safe
@@ -89,7 +115,7 @@ LL |     fn option_u8(x: Option<u8>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:107:33
+  --> $DIR/lint-ctypes-enum.rs:125:33
    |
 LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -97,7 +123,7 @@ LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:114:33
+  --> $DIR/lint-ctypes-enum.rs:132:33
    |
 LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -105,7 +131,7 @@ LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:119:38
+  --> $DIR/lint-ctypes-enum.rs:137:38
    |
 LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>);
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -114,7 +140,7 @@ LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:121:30
+  --> $DIR/lint-ctypes-enum.rs:139:30
    |
 LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -123,7 +149,7 @@ LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:125:51
+  --> $DIR/lint-ctypes-enum.rs:143:51
    |
 LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -132,7 +158,7 @@ LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>,
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:127:53
+  --> $DIR/lint-ctypes-enum.rs:145:53
    |
 LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>);
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -141,7 +167,7 @@ LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:129:51
+  --> $DIR/lint-ctypes-enum.rs:147:51
    |
 LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -150,7 +176,7 @@ LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>,
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:132:49
+  --> $DIR/lint-ctypes-enum.rs:150:49
    |
 LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -159,7 +185,7 @@ LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Fi
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:134:30
+  --> $DIR/lint-ctypes-enum.rs:152:30
    |
 LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -168,7 +194,7 @@ LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:145:33
+  --> $DIR/lint-ctypes-enum.rs:163:33
    |
 LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -176,7 +202,7 @@ LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:152:33
+  --> $DIR/lint-ctypes-enum.rs:170:33
    |
 LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -184,7 +210,7 @@ LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:157:38
+  --> $DIR/lint-ctypes-enum.rs:175:38
    |
 LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>);
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -193,7 +219,7 @@ LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZe
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:159:30
+  --> $DIR/lint-ctypes-enum.rs:177:30
    |
 LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -202,7 +228,7 @@ LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:163:51
+  --> $DIR/lint-ctypes-enum.rs:181:51
    |
 LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -211,7 +237,7 @@ LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:165:53
+  --> $DIR/lint-ctypes-enum.rs:183:53
    |
 LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>);
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -220,7 +246,7 @@ LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:167:51
+  --> $DIR/lint-ctypes-enum.rs:185:51
    |
 LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -229,7 +255,7 @@ LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:170:49
+  --> $DIR/lint-ctypes-enum.rs:188:49
    |
 LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -238,7 +264,7 @@ LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:172:30
+  --> $DIR/lint-ctypes-enum.rs:190:30
    |
 LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -247,7 +273,7 @@ LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:174:27
+  --> $DIR/lint-ctypes-enum.rs:192:27
    |
 LL |     fn result_unit_t_e(x: Result<(), ()>);
    |                           ^^^^^^^^^^^^^^ not FFI-safe
@@ -255,5 +281,5 @@ LL |     fn result_unit_t_e(x: Result<(), ()>);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: aborting due to 27 previous errors
+error: aborting due to 29 previous errors
 
diff --git a/tests/ui/transmute/unnecessary-transmutation.fixed b/tests/ui/transmute/unnecessary-transmutation.fixed
new file mode 100644
index 00000000000..1a0df143cc5
--- /dev/null
+++ b/tests/ui/transmute/unnecessary-transmutation.fixed
@@ -0,0 +1,85 @@
+//@ run-rustfix
+#![deny(unnecessary_transmutes)]
+#![allow(unused_unsafe, unused_imports, unused_variables, unused_parens)]
+use std::mem::transmute;
+
+pub fn bytes_at_home(x: u32) -> [u8; 4] {
+    unsafe { u32::to_ne_bytes(x) }
+    //~^ ERROR
+}
+
+fn main() {
+    unsafe {
+        let x: u16 = u16::from_ne_bytes(*b"01");
+        //~^ ERROR
+        let x: [u8; 2] = u16::to_ne_bytes(x);
+        //~^ ERROR
+        let x: u32 = u32::from_ne_bytes(*b"0123");
+        //~^ ERROR
+        let x: [u8; 4] = u32::to_ne_bytes(x);
+        //~^ ERROR
+        let x: u64 = u64::from_ne_bytes(*b"feriscat");
+        //~^ ERROR
+        let x: [u8; 8] = u64::to_ne_bytes(x);
+        //~^ ERROR
+
+        let y: i16 = i16::from_ne_bytes(*b"01");
+        //~^ ERROR
+        let y: [u8; 2] = i16::to_ne_bytes(y);
+        //~^ ERROR
+        let y: i32 = i32::from_ne_bytes(*b"0123");
+        //~^ ERROR
+        let y: [u8; 4] = i32::to_ne_bytes(y);
+        //~^ ERROR
+        let y: i64 = i64::from_ne_bytes(*b"feriscat");
+        //~^ ERROR
+        let y: [u8; 8] = i64::to_ne_bytes(y);
+        //~^ ERROR
+
+        let z: f32 = f32::from_ne_bytes(*b"0123");
+        //~^ ERROR
+        let z: [u8; 4] = f32::to_ne_bytes(z);
+        //~^ ERROR
+        let z: f64 = f64::from_ne_bytes(*b"feriscat");
+        //~^ ERROR
+        let z: [u8; 8] = f64::to_ne_bytes(z);
+        //~^ ERROR
+
+        let y: u32 = u32::from('🦀');
+        //~^ ERROR
+        let y: char = char::from_u32_unchecked(y);
+        //~^ ERROR
+
+        let x: u16 = i16::cast_unsigned(8i16);
+        //~^ ERROR
+        let x: i16 = u16::cast_signed(x);
+        //~^ ERROR
+        let x: u32 = i32::cast_unsigned(4i32);
+        //~^ ERROR
+        let x: i32 = u32::cast_signed(x);
+        //~^ ERROR
+        let x: u64 = i64::cast_unsigned(7i64);
+        //~^ ERROR
+        let x: i64 = u64::cast_signed(x);
+        //~^ ERROR
+
+        let y: f32 = f32::from_bits(1u32);
+        //~^ ERROR
+        let y: u32 = f32::to_bits(y);
+        //~^ ERROR
+        let y: f64 = f64::from_bits(3u64);
+        //~^ ERROR
+        let y: u64 = f64::to_bits(2.0);
+        //~^ ERROR
+
+        let z: bool = (1u8 == 1);
+        //~^ ERROR
+        let z: u8 = (z) as u8;
+        //~^ ERROR
+
+        let z: bool = transmute(1i8);
+        // no error!
+        let z: i8 = (z) as i8;
+        //~^ ERROR
+    }
+}
diff --git a/tests/ui/transmute/unnecessary-transmutation.rs b/tests/ui/transmute/unnecessary-transmutation.rs
new file mode 100644
index 00000000000..6b979263c56
--- /dev/null
+++ b/tests/ui/transmute/unnecessary-transmutation.rs
@@ -0,0 +1,85 @@
+//@ run-rustfix
+#![deny(unnecessary_transmutes)]
+#![allow(unused_unsafe, unused_imports, unused_variables, unused_parens)]
+use std::mem::transmute;
+
+pub fn bytes_at_home(x: u32) -> [u8; 4] {
+    unsafe { transmute(x) }
+    //~^ ERROR
+}
+
+fn main() {
+    unsafe {
+        let x: u16 = transmute(*b"01");
+        //~^ ERROR
+        let x: [u8; 2] = transmute(x);
+        //~^ ERROR
+        let x: u32 = transmute(*b"0123");
+        //~^ ERROR
+        let x: [u8; 4] = transmute(x);
+        //~^ ERROR
+        let x: u64 = transmute(*b"feriscat");
+        //~^ ERROR
+        let x: [u8; 8] = transmute(x);
+        //~^ ERROR
+
+        let y: i16 = transmute(*b"01");
+        //~^ ERROR
+        let y: [u8; 2] = transmute(y);
+        //~^ ERROR
+        let y: i32 = transmute(*b"0123");
+        //~^ ERROR
+        let y: [u8; 4] = transmute(y);
+        //~^ ERROR
+        let y: i64 = transmute(*b"feriscat");
+        //~^ ERROR
+        let y: [u8; 8] = transmute(y);
+        //~^ ERROR
+
+        let z: f32 = transmute(*b"0123");
+        //~^ ERROR
+        let z: [u8; 4] = transmute(z);
+        //~^ ERROR
+        let z: f64 = transmute(*b"feriscat");
+        //~^ ERROR
+        let z: [u8; 8] = transmute(z);
+        //~^ ERROR
+
+        let y: u32 = transmute('🦀');
+        //~^ ERROR
+        let y: char = transmute(y);
+        //~^ ERROR
+
+        let x: u16 = transmute(8i16);
+        //~^ ERROR
+        let x: i16 = transmute(x);
+        //~^ ERROR
+        let x: u32 = transmute(4i32);
+        //~^ ERROR
+        let x: i32 = transmute(x);
+        //~^ ERROR
+        let x: u64 = transmute(7i64);
+        //~^ ERROR
+        let x: i64 = transmute(x);
+        //~^ ERROR
+
+        let y: f32 = transmute(1u32);
+        //~^ ERROR
+        let y: u32 = transmute(y);
+        //~^ ERROR
+        let y: f64 = transmute(3u64);
+        //~^ ERROR
+        let y: u64 = transmute(2.0);
+        //~^ ERROR
+
+        let z: bool = transmute(1u8);
+        //~^ ERROR
+        let z: u8 = transmute(z);
+        //~^ ERROR
+
+        let z: bool = transmute(1i8);
+        // no error!
+        let z: i8 = transmute(z);
+        //~^ ERROR
+    }
+}
diff --git a/tests/ui/transmute/unnecessary-transmutation.stderr b/tests/ui/transmute/unnecessary-transmutation.stderr
new file mode 100644
index 00000000000..b661aa13c98
--- /dev/null
+++ b/tests/ui/transmute/unnecessary-transmutation.stderr
@@ -0,0 +1,235 @@
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:7:14
+   |
+LL |     unsafe { transmute(x) }
+   |              ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+note: the lint level is defined here
+  --> $DIR/unnecessary-transmutation.rs:2:9
+   |
+LL | #![deny(unnecessary_transmutes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:13:22
+   |
+LL |         let x: u16 = transmute(*b"01");
+   |                      ^^^^^^^^^^^^^^^^^ help: replace this with: `u16::from_ne_bytes(*b"01")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:15:26
+   |
+LL |         let x: [u8; 2] = transmute(x);
+   |                          ^^^^^^^^^^^^ help: replace this with: `u16::to_ne_bytes(x)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:17:22
+   |
+LL |         let x: u32 = transmute(*b"0123");
+   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `u32::from_ne_bytes(*b"0123")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:19:26
+   |
+LL |         let x: [u8; 4] = transmute(x);
+   |                          ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:21:22
+   |
+LL |         let x: u64 = transmute(*b"feriscat");
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `u64::from_ne_bytes(*b"feriscat")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:23:26
+   |
+LL |         let x: [u8; 8] = transmute(x);
+   |                          ^^^^^^^^^^^^ help: replace this with: `u64::to_ne_bytes(x)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:26:22
+   |
+LL |         let y: i16 = transmute(*b"01");
+   |                      ^^^^^^^^^^^^^^^^^ help: replace this with: `i16::from_ne_bytes(*b"01")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:28:26
+   |
+LL |         let y: [u8; 2] = transmute(y);
+   |                          ^^^^^^^^^^^^ help: replace this with: `i16::to_ne_bytes(y)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:30:22
+   |
+LL |         let y: i32 = transmute(*b"0123");
+   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `i32::from_ne_bytes(*b"0123")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:32:26
+   |
+LL |         let y: [u8; 4] = transmute(y);
+   |                          ^^^^^^^^^^^^ help: replace this with: `i32::to_ne_bytes(y)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:34:22
+   |
+LL |         let y: i64 = transmute(*b"feriscat");
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `i64::from_ne_bytes(*b"feriscat")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:36:26
+   |
+LL |         let y: [u8; 8] = transmute(y);
+   |                          ^^^^^^^^^^^^ help: replace this with: `i64::to_ne_bytes(y)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:39:22
+   |
+LL |         let z: f32 = transmute(*b"0123");
+   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `f32::from_ne_bytes(*b"0123")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:41:26
+   |
+LL |         let z: [u8; 4] = transmute(z);
+   |                          ^^^^^^^^^^^^ help: replace this with: `f32::to_ne_bytes(z)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:43:22
+   |
+LL |         let z: f64 = transmute(*b"feriscat");
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `f64::from_ne_bytes(*b"feriscat")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:45:26
+   |
+LL |         let z: [u8; 8] = transmute(z);
+   |                          ^^^^^^^^^^^^ help: replace this with: `f64::to_ne_bytes(z)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:48:22
+   |
+LL |         let y: u32 = transmute('🦀');
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🦀')`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:50:23
+   |
+LL |         let y: char = transmute(y);
+   |                       ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(y)`
+   |
+   = help: consider `char::from_u32(…).unwrap()`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:53:22
+   |
+LL |         let x: u16 = transmute(8i16);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i16::cast_unsigned(8i16)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:55:22
+   |
+LL |         let x: i16 = transmute(x);
+   |                      ^^^^^^^^^^^^ help: replace this with: `u16::cast_signed(x)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:57:22
+   |
+LL |         let x: u32 = transmute(4i32);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i32::cast_unsigned(4i32)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:59:22
+   |
+LL |         let x: i32 = transmute(x);
+   |                      ^^^^^^^^^^^^ help: replace this with: `u32::cast_signed(x)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:61:22
+   |
+LL |         let x: u64 = transmute(7i64);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i64::cast_unsigned(7i64)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:63:22
+   |
+LL |         let x: i64 = transmute(x);
+   |                      ^^^^^^^^^^^^ help: replace this with: `u64::cast_signed(x)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:66:22
+   |
+LL |         let y: f32 = transmute(1u32);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `f32::from_bits(1u32)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:68:22
+   |
+LL |         let y: u32 = transmute(y);
+   |                      ^^^^^^^^^^^^ help: replace this with: `f32::to_bits(y)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:70:22
+   |
+LL |         let y: f64 = transmute(3u64);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(3u64)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:72:22
+   |
+LL |         let y: u64 = transmute(2.0);
+   |                      ^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(2.0)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:75:23
+   |
+LL |         let z: bool = transmute(1u8);
+   |                       ^^^^^^^^^^^^^^ help: replace this with: `(1u8 == 1)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:77:21
+   |
+LL |         let z: u8 = transmute(z);
+   |                     ^^^^^^^^^^^^ help: replace this with: `(z) as u8`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:82:21
+   |
+LL |         let z: i8 = transmute(z);
+   |                     ^^^^^^^^^^^^ help: replace this with: `(z) as i8`
+
+error: aborting due to 32 previous errors
+