Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc

This commit is contained in:
bendn 2025-03-31 15:50:56 +07:00
parent c02a4f0852
commit c8c074288a
No known key found for this signature in database
GPG Key ID: 0D9D3A2A3B2A93D6
52 changed files with 687 additions and 100 deletions

View File

@ -1,6 +1,6 @@
#![feature(no_core, unboxed_closures)]
#![no_core]
#![allow(dead_code)]
#![allow(dead_code, unnecessary_transmutes)]
extern crate mini_core;

View File

@ -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() {

View File

@ -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,
@ -4909,6 +4910,30 @@ declare_lint! {
"detects pointer to integer transmutes in const functions and associated constants",
}
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.

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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]

View File

@ -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),

View File

@ -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};

View File

@ -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),

View File

@ -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 {

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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`

View File

@ -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`

View File

@ -3,6 +3,7 @@
#![allow(
dead_code,
clippy::borrow_as_ptr,
unnecessary_transmutes,
clippy::needless_lifetimes,
clippy::missing_transmute_annotations
)]

View File

@ -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)`

View File

@ -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)]

View File

@ -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)]

View File

@ -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() };

View File

@ -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) };

View File

@ -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;

View File

@ -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;

View File

@ -1,3 +1,4 @@
#![allow(unnecessary_transmutes)]
fn main() {
let _b = unsafe { std::mem::transmute::<u8, bool>(2) }; //~ ERROR: expected a boolean
}

View File

@ -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

View File

@ -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) } {

View File

@ -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());

View File

@ -6,6 +6,7 @@
#![feature(f16)]
#![allow(arithmetic_overflow)]
#![allow(internal_features)]
#![allow(unnecessary_transmutes)]
use std::any::type_name;
use std::cmp::min;

View File

@ -1,3 +1,4 @@
#![allow(unnecessary_transmutes)]
pub fn main() {
let bytes: [u8; 8] = unsafe { ::std::mem::transmute(0u64) };
let _val: &[u8] = &bytes;

View File

@ -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))
}

View File

@ -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::*;

View File

@ -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;

View File

@ -1,3 +1,4 @@
#![allow(unnecessary_transmutes)]
use std::mem;
fn main() {

View File

@ -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

View File

@ -1,3 +1,4 @@
#![allow(unnecessary_transmutes)]
use std::mem;
static FOO: bool = unsafe { mem::transmute(3u8) };

View File

@ -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

View File

@ -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;

View File

@ -1,5 +1,5 @@
// ignore-tidy-linelength
#![allow(unused)]
#![allow(unused, unnecessary_transmutes)]
#![feature(ptr_metadata)]
use std::{ptr, mem};

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -1,4 +1,5 @@
//@ run-pass
#![allow(unnecessary_transmutes)]
use std::mem::transmute;
fn main() {

View File

@ -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)]

View File

@ -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 | | );
| |_____^
|

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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