about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-04-24 17:19:42 +0200
committerGitHub <noreply@github.com>2025-04-24 17:19:42 +0200
commit53afa97eb79041572e5c6f07297f4e40f27e972b (patch)
tree519be6cf3b8edf11ed53cbecf1122e4205c78a4d /library
parent3c877f6a477380ed61155d3bf816df09c9e05b9e (diff)
parent6921a51b4c30d495f8768340d22c44a89e63a782 (diff)
downloadrust-53afa97eb79041572e5c6f07297f4e40f27e972b.tar.gz
rust-53afa97eb79041572e5c6f07297f4e40f27e972b.zip
Rollup merge of #136083 - bend-n:⃤⃤, r=lcnr
Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc

implements #136067

Rust has helper methods for many kinds of safe transmutes, for example integer<->bytes. This is a lint against using transmute for these cases.

```rs
fn bytes_at_home(x: [u8; 4]) -> u32 {
   transmute(x)
}

// other examples
transmute::<[u8; 2], u16>();
transmute::<[u8; 8], f64>();
transmute::<u32, [u8; 4]>();
transmute::<char, u32>();
transmute::<u32, char>();
```
It would be handy to suggest `u32::from_ne_bytes(x)`.
This is implemented for `[u8; _]` -> `{float int}`

This also implements the cases:
`fXX` <-> `uXX` = `{from_bits, to_bits}`
`uXX` -> `iXX` via `cast_unsigned` and `cast_signed`
{`char` -> `u32`, `bool` -> `n8`} via `from`
`u32` -> `char` via `from_u32_unchecked` (note: notes `from_u32().unwrap()`) (contested)
`u8` -> `bool` via `==` (debatable)

---
try-job: aarch64-gnu
try-job: test-various
Diffstat (limited to 'library')
-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
m---------library/stdarch0
10 files changed, 18 insertions, 4 deletions
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 e25f7091c93..3061ec208ba 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -904,6 +904,7 @@ impl f128 {
     #[inline]
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u128 {
         // SAFETY: `u128` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -951,6 +952,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 bd00ed0f4ed..ced5b51d262 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -892,6 +892,7 @@ impl f16 {
     #[inline]
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u16 {
         // SAFETY: `u16` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -938,6 +939,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 c95ad2d0f35..84b0128bb69 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`.
@@ -1097,6 +1096,7 @@ impl f32 {
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u32 {
         // SAFETY: `u32` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -1142,6 +1142,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 16b762ed6f0..2197e804aa8 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]
@@ -1095,6 +1094,7 @@ impl f64 {
                   without modifying the original"]
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     #[inline]
     pub const fn to_bits(self) -> u64 {
         // SAFETY: `u64` is a plain old datatype so we can always transmute to it.
@@ -1141,6 +1141,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/library/stdarch b/library/stdarch
-Subproject 4666c7376f25a265c74535585d622da3da6dfeb
+Subproject 1245618ccf5b2df7ab1ebb0279b9f3f72667016