From 8373bb17d6f9ccb00171f788bbc1379bffc61f68 Mon Sep 17 00:00:00 2001 From: bendn Date: Tue, 29 Apr 2025 13:51:45 +0700 Subject: [PATCH] use uX::from instead of _ as uX in non - const contexts --- .../src/check_unnecessary_transmutes.rs | 19 ++- .../transmute/unnecessary-transmutation.fixed | 24 +++- .../ui/transmute/unnecessary-transmutation.rs | 20 ++++ .../unnecessary-transmutation.stderr | 113 +++++++++++------- 4 files changed, 130 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs index 0514de3ea13fb..1a3715465ad4e 100644 --- a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs +++ b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs @@ -30,6 +30,7 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> { function: &Operand<'tcx>, arg: String, span: Span, + is_in_const: bool, ) -> Option { let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder(); let [input] = fn_sig.inputs() else { return None }; @@ -97,8 +98,14 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> { )), // 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())), + // bool → { x8 } in const context since `From::from` is not const yet + // FIXME: is it possible to know when the parentheses arent necessary? + // FIXME(const_traits): Remove this when From::from is constified? + (Bool, Int(..) | Uint(..)) if is_in_const => { + err(format!("({arg}) as {}", fn_sig.output())) + } + // " using `x8::from` + (Bool, Int(..) | Uint(..)) => err(format!("{}::from({arg})", fn_sig.output())), _ => return None, }) } @@ -114,7 +121,13 @@ impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> { && self.tcx.is_intrinsic(func_def_id, sym::transmute) && let span = self.body.source_info(location).span && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(arg) - && let Some(lint) = self.is_unnecessary_transmute(func, snippet, span) + && let def_id = self.body.source.def_id() + && let Some(lint) = self.is_unnecessary_transmute( + func, + snippet, + span, + self.tcx.hir_body_const_context(def_id.expect_local()).is_some(), + ) && 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/tests/ui/transmute/unnecessary-transmutation.fixed b/tests/ui/transmute/unnecessary-transmutation.fixed index f6478c5aa5c2f..08010ec8b84e4 100644 --- a/tests/ui/transmute/unnecessary-transmutation.fixed +++ b/tests/ui/transmute/unnecessary-transmutation.fixed @@ -8,7 +8,27 @@ pub fn bytes_at_home(x: u32) -> [u8; 4] { //~^ ERROR } +pub const fn intinator_const(from: bool) -> u8 { + unsafe { (from) as u8 } + //~^ ERROR +} + +pub static X: u8 = unsafe { (true) as u8 }; +//~^ ERROR +pub const Y: u8 = unsafe { (true) as u8 }; +//~^ ERROR + +pub struct Z {} +impl Z { + pub const fn intinator_assoc(x: bool) -> u8 { + unsafe { (x) as u8 } + //~^ ERROR + } +} + fn main() { + const { unsafe { (true) as u8 } }; + //~^ ERROR unsafe { let x: u16 = u16::from_ne_bytes(*b"01"); //~^ ERROR @@ -83,12 +103,12 @@ fn main() { let z: bool = transmute(1u8); // clippy - let z: u8 = (z) as u8; + let z: u8 = u8::from(z); //~^ ERROR let z: bool = transmute(1i8); // clippy - let z: i8 = (z) as i8; + let z: i8 = i8::from(z); //~^ ERROR } } diff --git a/tests/ui/transmute/unnecessary-transmutation.rs b/tests/ui/transmute/unnecessary-transmutation.rs index ab0af03acc2ec..43eefb97dc28f 100644 --- a/tests/ui/transmute/unnecessary-transmutation.rs +++ b/tests/ui/transmute/unnecessary-transmutation.rs @@ -8,7 +8,27 @@ pub fn bytes_at_home(x: u32) -> [u8; 4] { //~^ ERROR } +pub const fn intinator_const(from: bool) -> u8 { + unsafe { transmute(from) } + //~^ ERROR +} + +pub static X: u8 = unsafe { transmute(true) }; +//~^ ERROR +pub const Y: u8 = unsafe { transmute(true) }; +//~^ ERROR + +pub struct Z {} +impl Z { + pub const fn intinator_assoc(x: bool) -> u8 { + unsafe { transmute(x) } + //~^ ERROR + } +} + fn main() { + const { unsafe { transmute::<_, u8>(true) } }; + //~^ ERROR unsafe { let x: u16 = transmute(*b"01"); //~^ ERROR diff --git a/tests/ui/transmute/unnecessary-transmutation.stderr b/tests/ui/transmute/unnecessary-transmutation.stderr index 59e933bbc81b9..602e964f5b2bd 100644 --- a/tests/ui/transmute/unnecessary-transmutation.stderr +++ b/tests/ui/transmute/unnecessary-transmutation.stderr @@ -1,10 +1,9 @@ error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:7:14 + --> $DIR/unnecessary-transmutation.rs:16:29 | -LL | unsafe { transmute(x) } - | ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)` +LL | pub static X: u8 = unsafe { transmute(true) }; + | ^^^^^^^^^^^^^^^ help: replace this with: `(true) as u8` | - = 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 | @@ -12,7 +11,33 @@ LL | #![deny(unnecessary_transmutes)] | ^^^^^^^^^^^^^^^^^^^^^^ error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:13:22 + --> $DIR/unnecessary-transmutation.rs:18:28 + | +LL | pub const Y: u8 = unsafe { transmute(true) }; + | ^^^^^^^^^^^^^^^ help: replace this with: `(true) as u8` + +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 + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:12:14 + | +LL | unsafe { transmute(from) } + | ^^^^^^^^^^^^^^^ help: replace this with: `(from) as u8` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:24:18 + | +LL | unsafe { transmute(x) } + | ^^^^^^^^^^^^ help: replace this with: `(x) as u8` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:33:22 | LL | let x: u16 = transmute(*b"01"); | ^^^^^^^^^^^^^^^^^ help: replace this with: `u16::from_ne_bytes(*b"01")` @@ -20,7 +45,7 @@ LL | let x: u16 = transmute(*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 + --> $DIR/unnecessary-transmutation.rs:35:26 | LL | let x: [u8; 2] = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u16::to_ne_bytes(x)` @@ -28,7 +53,7 @@ LL | let x: [u8; 2] = transmute(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 + --> $DIR/unnecessary-transmutation.rs:37:22 | LL | let x: u32 = transmute(*b"0123"); | ^^^^^^^^^^^^^^^^^^^ help: replace this with: `u32::from_ne_bytes(*b"0123")` @@ -36,7 +61,7 @@ LL | let x: u32 = transmute(*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 + --> $DIR/unnecessary-transmutation.rs:39:26 | LL | let x: [u8; 4] = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)` @@ -44,7 +69,7 @@ LL | let x: [u8; 4] = transmute(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 + --> $DIR/unnecessary-transmutation.rs:41:22 | LL | let x: u64 = transmute(*b"feriscat"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `u64::from_ne_bytes(*b"feriscat")` @@ -52,7 +77,7 @@ LL | let x: u64 = transmute(*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 + --> $DIR/unnecessary-transmutation.rs:43:26 | LL | let x: [u8; 8] = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u64::to_ne_bytes(x)` @@ -60,7 +85,7 @@ LL | let x: [u8; 8] = transmute(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 + --> $DIR/unnecessary-transmutation.rs:46:22 | LL | let y: i16 = transmute(*b"01"); | ^^^^^^^^^^^^^^^^^ help: replace this with: `i16::from_ne_bytes(*b"01")` @@ -68,7 +93,7 @@ LL | let y: i16 = transmute(*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 + --> $DIR/unnecessary-transmutation.rs:48:26 | LL | let y: [u8; 2] = transmute(y); | ^^^^^^^^^^^^ help: replace this with: `i16::to_ne_bytes(y)` @@ -76,7 +101,7 @@ LL | let y: [u8; 2] = transmute(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 + --> $DIR/unnecessary-transmutation.rs:50:22 | LL | let y: i32 = transmute(*b"0123"); | ^^^^^^^^^^^^^^^^^^^ help: replace this with: `i32::from_ne_bytes(*b"0123")` @@ -84,7 +109,7 @@ LL | let y: i32 = transmute(*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 + --> $DIR/unnecessary-transmutation.rs:52:26 | LL | let y: [u8; 4] = transmute(y); | ^^^^^^^^^^^^ help: replace this with: `i32::to_ne_bytes(y)` @@ -92,7 +117,7 @@ LL | let y: [u8; 4] = transmute(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 + --> $DIR/unnecessary-transmutation.rs:54:22 | LL | let y: i64 = transmute(*b"feriscat"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `i64::from_ne_bytes(*b"feriscat")` @@ -100,7 +125,7 @@ LL | let y: i64 = transmute(*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 + --> $DIR/unnecessary-transmutation.rs:56:26 | LL | let y: [u8; 8] = transmute(y); | ^^^^^^^^^^^^ help: replace this with: `i64::to_ne_bytes(y)` @@ -108,7 +133,7 @@ LL | let y: [u8; 8] = transmute(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 + --> $DIR/unnecessary-transmutation.rs:59:22 | LL | let z: f32 = transmute(*b"0123"); | ^^^^^^^^^^^^^^^^^^^ help: replace this with: `f32::from_ne_bytes(*b"0123")` @@ -116,7 +141,7 @@ LL | let z: f32 = transmute(*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 + --> $DIR/unnecessary-transmutation.rs:61:26 | LL | let z: [u8; 4] = transmute(z); | ^^^^^^^^^^^^ help: replace this with: `f32::to_ne_bytes(z)` @@ -124,7 +149,7 @@ LL | let z: [u8; 4] = transmute(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 + --> $DIR/unnecessary-transmutation.rs:63:22 | LL | let z: f64 = transmute(*b"feriscat"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `f64::from_ne_bytes(*b"feriscat")` @@ -132,7 +157,7 @@ LL | let z: f64 = transmute(*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 + --> $DIR/unnecessary-transmutation.rs:65:26 | LL | let z: [u8; 8] = transmute(z); | ^^^^^^^^^^^^ help: replace this with: `f64::to_ne_bytes(z)` @@ -140,13 +165,13 @@ LL | let z: [u8; 8] = transmute(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 + --> $DIR/unnecessary-transmutation.rs:68:22 | LL | let y: u32 = transmute('🦀'); | ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🦀')` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:50:23 + --> $DIR/unnecessary-transmutation.rs:70:23 | LL | let y: char = transmute(y); | ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(y)` @@ -154,13 +179,13 @@ LL | let y: char = transmute(y); = help: consider `char::from_u32(…).unwrap()` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:52:22 + --> $DIR/unnecessary-transmutation.rs:72:22 | LL | let y: i32 = transmute('🐱'); | ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🐱').cast_signed()` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:54:23 + --> $DIR/unnecessary-transmutation.rs:74:23 | LL | let y: char = transmute(y); | ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(i32::cast_unsigned(y))` @@ -168,88 +193,94 @@ LL | let y: char = transmute(y); = help: consider `char::from_u32(i32::cast_unsigned(…)).unwrap()` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:57:22 + --> $DIR/unnecessary-transmutation.rs:77:22 | LL | let x: u16 = transmute(8i16); | ^^^^^^^^^^^^^^^ help: replace this with: `i16::cast_unsigned(8i16)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:59:22 + --> $DIR/unnecessary-transmutation.rs:79:22 | LL | let x: i16 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u16::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:61:22 + --> $DIR/unnecessary-transmutation.rs:81:22 | LL | let x: u32 = transmute(4i32); | ^^^^^^^^^^^^^^^ help: replace this with: `i32::cast_unsigned(4i32)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:63:22 + --> $DIR/unnecessary-transmutation.rs:83:22 | LL | let x: i32 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u32::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:65:22 + --> $DIR/unnecessary-transmutation.rs:85:22 | LL | let x: u64 = transmute(7i64); | ^^^^^^^^^^^^^^^ help: replace this with: `i64::cast_unsigned(7i64)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:67:22 + --> $DIR/unnecessary-transmutation.rs:87:22 | LL | let x: i64 = transmute(x); | ^^^^^^^^^^^^ help: replace this with: `u64::cast_signed(x)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:70:22 + --> $DIR/unnecessary-transmutation.rs:90:22 | LL | let y: f32 = transmute(1u32); | ^^^^^^^^^^^^^^^ help: replace this with: `f32::from_bits(1u32)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:72:22 + --> $DIR/unnecessary-transmutation.rs:92:22 | LL | let y: u32 = transmute(y); | ^^^^^^^^^^^^ help: replace this with: `f32::to_bits(y)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:74:22 + --> $DIR/unnecessary-transmutation.rs:94:22 | LL | let y: f64 = transmute(3u64); | ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(3u64)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:76:22 + --> $DIR/unnecessary-transmutation.rs:96:22 | LL | let y: u64 = transmute(2.0); | ^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(2.0)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:79:22 + --> $DIR/unnecessary-transmutation.rs:99:22 | LL | let y: f64 = transmute(1i64); | ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(i64::cast_unsigned(1i64))` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:81:22 + --> $DIR/unnecessary-transmutation.rs:101:22 | LL | let y: i64 = transmute(1f64); | ^^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(1f64).cast_signed()` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:86:21 + --> $DIR/unnecessary-transmutation.rs:106:21 | LL | let z: u8 = transmute(z); - | ^^^^^^^^^^^^ help: replace this with: `(z) as u8` + | ^^^^^^^^^^^^ help: replace this with: `u8::from(z)` error: unnecessary transmute - --> $DIR/unnecessary-transmutation.rs:91:21 + --> $DIR/unnecessary-transmutation.rs:111:21 | LL | let z: i8 = transmute(z); - | ^^^^^^^^^^^^ help: replace this with: `(z) as i8` + | ^^^^^^^^^^^^ help: replace this with: `i8::from(z)` + +error: unnecessary transmute + --> $DIR/unnecessary-transmutation.rs:30:22 + | +LL | const { unsafe { transmute::<_, u8>(true) } }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `(true) as u8` -error: aborting due to 35 previous errors +error: aborting due to 40 previous errors