Skip to content

Commit 9efc290

Browse files
committed
add float
1 parent f2e4ff1 commit 9efc290

File tree

8 files changed

+38
-53
lines changed

8 files changed

+38
-53
lines changed

compiler/rustc_mir_transform/src/check_redundant_transmutes.rs

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use rustc_middle::mir::visit::Visitor;
22
use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind};
3-
use rustc_middle::ty::{Ty, TyCtxt, UintTy};
3+
use rustc_middle::ty::{TyCtxt, UintTy};
44
use rustc_session::lint::builtin::REDUNDANT_TRANSMUTATION;
55
use rustc_span::source_map::Spanned;
66
use rustc_span::{Span, sym};
77
use rustc_type_ir::TyKind::*;
88

9-
use crate::errors;
9+
use crate::errors::RedundantTransmute as Error;
1010

1111
/// Check for transmutes that overlap with stdlib methods.
1212
/// For example, transmuting `[u8; 4]` to `u32`.
@@ -36,64 +36,48 @@ impl<'a, 'tcx> RedundantTransmutesChecker<'a, 'tcx> {
3636
function: &Operand<'tcx>,
3737
arg: String,
3838
span: Span,
39-
) -> Option<errors::RedundantTransmute> {
39+
) -> Option<Error> {
4040
let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder();
4141
let [input] = fn_sig.inputs() else { return None };
4242

43-
// Checks if `x` is `[u8; _]`
44-
let is_u8s = |x: Ty<'tcx>| matches!(x.kind(), Array(t, _) if *t.kind() == Uint(UintTy::U8));
45-
// dont check the length; transmute does that for us.
46-
if is_u8s(*input) && matches!(fn_sig.output().kind(), Uint(..) | Float(_) | Int(_)) {
47-
// FIXME: get the whole expression out?
48-
return Some(errors::RedundantTransmute {
43+
let err = |sugg| Error { span, sugg, help: None };
44+
45+
Some(match (input.kind(), fn_sig.output().kind()) {
46+
// dont check the length; transmute does that for us.
47+
(Array(t, _), Uint(_) | Float(_) | Int(_)) if *t.kind() == Uint(UintTy::U8) => Error {
4948
sugg: format!("{}::from_ne_bytes({arg})", fn_sig.output()),
5049
help: Some(
5150
"there's also `from_le_bytes` and `from_ne_bytes` if you expect a particular byte order",
5251
),
5352
span,
54-
});
55-
}
56-
if is_u8s(fn_sig.output()) && matches!(input.kind(), Uint(..) | Float(_) | Int(_)) {
57-
return Some(errors::RedundantTransmute {
53+
},
54+
(Uint(_) | Float(_) | Int(_), Array(t, _)) if *t.kind() == Uint(UintTy::U8) => Error {
5855
sugg: format!("{input}::to_ne_bytes({arg})"),
5956
help: Some(
6057
"there's also `to_le_bytes` and `to_ne_bytes` if you expect a particular byte order",
6158
),
6259
span,
63-
});
64-
}
65-
match input.kind() {
60+
},
6661
// char → u32
67-
Char => matches!(fn_sig.output().kind(), Uint(UintTy::U32))
68-
.then(|| errors::RedundantTransmute::new(format!("({arg}) as u32"), span)),
62+
(Char, Uint(UintTy::U32)) => err(format!("({arg}) as u32")),
6963
// u32 → char
70-
Uint(UintTy::U32) if *fn_sig.output().kind() == Char => {
71-
Some(errors::RedundantTransmute {
72-
sugg: format!("char::from_u32_unchecked({arg})"),
73-
help: Some("consider `char::from_u32(…).unwrap()`"),
74-
span,
75-
})
76-
}
64+
(Uint(UintTy::U32), Char) => Error {
65+
sugg: format!("char::from_u32_unchecked({arg})"),
66+
help: Some("consider `char::from_u32(…).unwrap()`"),
67+
span,
68+
},
7769
// uNN → iNN
78-
Uint(ty) if matches!(fn_sig.output().kind(), Int(..)) => {
79-
Some(errors::RedundantTransmute::new(
80-
format!("{}::cast_signed({arg})", ty.name_str()),
81-
span,
82-
))
83-
}
70+
(Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())),
8471
// iNN → uNN
85-
Int(ty) if matches!(fn_sig.output().kind(), Uint(..)) => {
86-
Some(errors::RedundantTransmute::new(
87-
format!("{}::cast_unsigned({arg})", ty.name_str()),
88-
span,
89-
))
90-
}
72+
(Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())),
73+
// fNN → uNN
74+
(Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())),
75+
// uNN → fNN
76+
(Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())),
9177
// bool → { uNN, iNN }
92-
Bool if matches!(fn_sig.output().kind(), Int(..) | Uint(..)) => Some(
93-
errors::RedundantTransmute::new(format!("({arg}) as {}", fn_sig.output()), span),
94-
),
95-
_ => None,
96-
}
78+
(Bool, Int(..) | Uint(..)) => err(format!("({arg}) as {}", fn_sig.output())),
79+
_ => return None,
80+
})
9781
}
9882
}
9983

compiler/rustc_mir_transform/src/errors.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,6 @@ pub(crate) struct RedundantTransmute {
164164
pub help: Option<&'static str>,
165165
}
166166

167-
impl RedundantTransmute {
168-
pub(crate) fn new(sugg: String, span: Span) -> Self {
169-
Self { span, sugg, help: None }
170-
}
171-
}
172-
173167
// Needed for def_path_str
174168
impl<'a> LintDiagnostic<'a, ()> for RedundantTransmute {
175169
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {

library/core/src/num/f128.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,7 @@ impl f128 {
901901
#[inline]
902902
#[unstable(feature = "f128", issue = "116909")]
903903
#[must_use = "this returns the result of the operation, without modifying the original"]
904+
#[cfg_attr(not(bootstrap), allow(redundant_transmutation))]
904905
pub const fn to_bits(self) -> u128 {
905906
// SAFETY: `u128` is a plain old datatype so we can always transmute to it.
906907
unsafe { mem::transmute(self) }
@@ -948,6 +949,7 @@ impl f128 {
948949
#[inline]
949950
#[must_use]
950951
#[unstable(feature = "f128", issue = "116909")]
952+
#[cfg_attr(not(bootstrap), allow(redundant_transmutation))]
951953
pub const fn from_bits(v: u128) -> Self {
952954
// It turns out the safety issues with sNaN were overblown! Hooray!
953955
// SAFETY: `u128` is a plain old datatype so we can always transmute from it.

library/core/src/num/f16.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,7 @@ impl f16 {
889889
#[inline]
890890
#[unstable(feature = "f16", issue = "116909")]
891891
#[must_use = "this returns the result of the operation, without modifying the original"]
892+
#[cfg_attr(not(bootstrap), allow(redundant_transmutation))]
892893
pub const fn to_bits(self) -> u16 {
893894
// SAFETY: `u16` is a plain old datatype so we can always transmute to it.
894895
unsafe { mem::transmute(self) }
@@ -935,6 +936,7 @@ impl f16 {
935936
#[inline]
936937
#[must_use]
937938
#[unstable(feature = "f16", issue = "116909")]
939+
#[cfg_attr(not(bootstrap), allow(redundant_transmutation))]
938940
pub const fn from_bits(v: u16) -> Self {
939941
// It turns out the safety issues with sNaN were overblown! Hooray!
940942
// SAFETY: `u16` is a plain old datatype so we can always transmute from it.

library/core/src/num/f32.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,8 +708,7 @@ impl f32 {
708708
pub const fn is_sign_negative(self) -> bool {
709709
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
710710
// applies to zeros and NaNs as well.
711-
// SAFETY: This is just transmuting to get the sign bit, it's fine.
712-
unsafe { mem::transmute::<f32, u32>(self) & 0x8000_0000 != 0 }
711+
self.to_bits() & 0x8000_0000 != 0
713712
}
714713

715714
/// Returns the least number greater than `self`.
@@ -1093,6 +1092,7 @@ impl f32 {
10931092
#[stable(feature = "float_bits_conv", since = "1.20.0")]
10941093
#[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
10951094
#[inline]
1095+
#[cfg_attr(not(bootstrap), allow(redundant_transmutation))]
10961096
pub const fn to_bits(self) -> u32 {
10971097
// SAFETY: `u32` is a plain old datatype so we can always transmute to it.
10981098
unsafe { mem::transmute(self) }
@@ -1138,6 +1138,7 @@ impl f32 {
11381138
#[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
11391139
#[must_use]
11401140
#[inline]
1141+
#[cfg_attr(not(bootstrap), allow(redundant_transmutation))]
11411142
pub const fn from_bits(v: u32) -> Self {
11421143
// It turns out the safety issues with sNaN were overblown! Hooray!
11431144
// SAFETY: `u32` is a plain old datatype so we can always transmute from it.

library/core/src/num/f64.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -716,8 +716,7 @@ impl f64 {
716716
pub const fn is_sign_negative(self) -> bool {
717717
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
718718
// applies to zeros and NaNs as well.
719-
// SAFETY: This is just transmuting to get the sign bit, it's fine.
720-
unsafe { mem::transmute::<f64, u64>(self) & Self::SIGN_MASK != 0 }
719+
self.to_bits() & Self::SIGN_MASK != 0
721720
}
722721

723722
#[must_use]
@@ -1092,6 +1091,7 @@ impl f64 {
10921091
without modifying the original"]
10931092
#[stable(feature = "float_bits_conv", since = "1.20.0")]
10941093
#[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
1094+
#[cfg_attr(not(bootstrap), allow(redundant_transmutation))]
10951095
#[inline]
10961096
pub const fn to_bits(self) -> u64 {
10971097
// SAFETY: `u64` is a plain old datatype so we can always transmute to it.
@@ -1138,6 +1138,7 @@ impl f64 {
11381138
#[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
11391139
#[must_use]
11401140
#[inline]
1141+
#[cfg_attr(not(bootstrap), allow(redundant_transmutation))]
11411142
pub const fn from_bits(v: u64) -> Self {
11421143
// It turns out the safety issues with sNaN were overblown! Hooray!
11431144
// SAFETY: `u64` is a plain old datatype so we can always transmute from it.

tests/ui/consts/const-eval/transmute-const-promotion.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(redundant_transmutation)]
12
use std::mem;
23

34
fn main() {

tests/ui/consts/const-eval/transmute-const-promotion.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0716]: temporary value dropped while borrowed
2-
--> $DIR/transmute-const-promotion.rs:4:37
2+
--> $DIR/transmute-const-promotion.rs:5:37
33
|
44
LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
55
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use

0 commit comments

Comments
 (0)