about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbendn <bend.n@outlook.com>2025-03-31 15:50:56 +0700
committerbendn <bend.n@outlook.com>2025-04-24 13:14:36 +0700
commitc8c074288a277df21a52aded322dfa25bc283f64 (patch)
tree272448f60986d3f18b5269162658319dcaf70bc8
parentc02a4f0852e6665cf3df3867982021383f5615df (diff)
downloadrust-c8c074288a277df21a52aded322dfa25bc283f64.tar.gz
rust-c8c074288a277df21a52aded322dfa25bc283f64.zip
Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc
-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_lint_defs/src/builtin.rs25
-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--library/alloctests/tests/fmt.rs1
-rw-r--r--library/core/src/char/convert.rs2
-rw-r--r--library/core/src/intrinsics/mod.rs1
-rw-r--r--library/core/src/num/f128.rs2
-rw-r--r--library/core/src/num/f16.rs2
-rw-r--r--library/core/src/num/f32.rs5
-rw-r--r--library/core/src/num/f64.rs5
-rw-r--r--library/core/src/num/int_macros.rs2
-rw-r--r--library/core/src/num/uint_macros.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/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--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/transmute/unnecessary-transmutation.fixed85
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.rs85
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.stderr235
52 files changed, 687 insertions, 100 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_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_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/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..79f300c295b 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 {
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 2ee25969289..81781bb2be4 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -903,6 +903,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) }
@@ -950,6 +951,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.
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 69882d13c17..bbde9e5ae39 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -891,6 +891,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) }
@@ -937,6 +938,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.
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 7e056a6c1f3..77e6c0975d4 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -710,8 +710,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`.
@@ -1096,6 +1095,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) }
@@ -1141,6 +1141,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.
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index b9ebbb1d764..89cec28626c 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -718,8 +718,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]
@@ -1094,6 +1093,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.
@@ -1140,6 +1140,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.
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/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/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/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/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
+