From d6f05c6a89e7bbaafc2ca30f845de488cd5a8978 Mon Sep 17 00:00:00 2001 From: SabrinaJewson Date: Wed, 30 Mar 2022 18:47:50 +0100 Subject: [PATCH] Don't warn int-to-char transmutes in const contexts --- clippy_lints/src/transmute/mod.rs | 9 ++-- .../src/transmute/transmute_int_to_char.rs | 3 +- tests/ui/transmute.rs | 4 ++ tests/ui/transmute.stderr | 42 +++++++++---------- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 02569bd3a..342f23f03 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -410,9 +410,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id(); if cx.tcx.is_diagnostic_item(sym::transmute, def_id); then { - // Avoid suggesting from/to bits and dereferencing raw pointers in const contexts. - // See https://github.com/rust-lang/rust/issues/73736 for progress on making them `const fn`. - // And see https://github.com/rust-lang/rust/issues/51911 for dereferencing raw pointers. + // Avoid suggesting non-const operations in const contexts: + // - from/to bits (https://github.com/rust-lang/rust/issues/73736) + // - dereferencing raw pointers (https://github.com/rust-lang/rust/issues/51911) + // - char conversions (https://github.com/rust-lang/rust/issues/89259) let const_context = in_constant(cx, e.hir_id); let from_ty = cx.typeck_results().expr_ty_adjusted(arg); @@ -427,7 +428,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let linted = wrong_transmute::check(cx, e, from_ty, to_ty) | crosspointer_transmute::check(cx, e, from_ty, to_ty) | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, qpath) - | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg) + | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg) | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) diff --git a/clippy_lints/src/transmute/transmute_int_to_char.rs b/clippy_lints/src/transmute/transmute_int_to_char.rs index 3eb07b689..9e1823c37 100644 --- a/clippy_lints/src/transmute/transmute_int_to_char.rs +++ b/clippy_lints/src/transmute/transmute_int_to_char.rs @@ -15,9 +15,10 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, + const_context: bool, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::Int(ty::IntTy::I32) | ty::Uint(ty::UintTy::U32), &ty::Char) => { + (ty::Int(ty::IntTy::I32) | ty::Uint(ty::UintTy::U32), &ty::Char) if !const_context => { span_lint_and_then( cx, TRANSMUTE_INT_TO_CHAR, diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 9b681a79a..54f9727d8 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -73,6 +73,10 @@ fn crosspointer() { fn int_to_char() { let _: char = unsafe { std::mem::transmute(0_u32) }; let _: char = unsafe { std::mem::transmute(0_i32) }; + + // These shouldn't warn + const _: char = unsafe { std::mem::transmute(0_u32) }; + const _: char = unsafe { std::mem::transmute(0_i32) }; } #[warn(clippy::transmute_int_to_bool)] diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 86537153e..5c60fc2d5 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -107,7 +107,7 @@ LL | let _: char = unsafe { std::mem::transmute(0_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()` error: transmute from a `u8` to a `bool` - --> $DIR/transmute.rs:80:28 + --> $DIR/transmute.rs:84:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -115,7 +115,7 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = note: `-D clippy::transmute-int-to-bool` implied by `-D warnings` error: transmute from a `u32` to a `f32` - --> $DIR/transmute.rs:86:31 + --> $DIR/transmute.rs:90:31 | LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` @@ -123,25 +123,25 @@ LL | let _: f32 = unsafe { std::mem::transmute(0_u32) }; = note: `-D clippy::transmute-int-to-float` implied by `-D warnings` error: transmute from a `i32` to a `f32` - --> $DIR/transmute.rs:87:31 + --> $DIR/transmute.rs:91: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` - --> $DIR/transmute.rs:88:31 + --> $DIR/transmute.rs:92: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` - --> $DIR/transmute.rs:89:31 + --> $DIR/transmute.rs:93:31 | LL | let _: f64 = unsafe { std::mem::transmute(0_i64) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` error: transmute from a `u8` to a `[u8; 1]` - --> $DIR/transmute.rs:109:30 + --> $DIR/transmute.rs:113:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` @@ -149,85 +149,85 @@ LL | let _: [u8; 1] = std::mem::transmute(0u8); = note: `-D clippy::transmute-num-to-bytes` implied by `-D warnings` error: transmute from a `u32` to a `[u8; 4]` - --> $DIR/transmute.rs:110:30 + --> $DIR/transmute.rs:114: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]` - --> $DIR/transmute.rs:111:31 + --> $DIR/transmute.rs:115: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]` - --> $DIR/transmute.rs:112:30 + --> $DIR/transmute.rs:116: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]` - --> $DIR/transmute.rs:113:30 + --> $DIR/transmute.rs:117: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]` - --> $DIR/transmute.rs:114:31 + --> $DIR/transmute.rs:118:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `f32` to a `[u8; 4]` - --> $DIR/transmute.rs:115:30 + --> $DIR/transmute.rs:119: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]` - --> $DIR/transmute.rs:116:30 + --> $DIR/transmute.rs:120: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 `u8` to a `[u8; 1]` - --> $DIR/transmute.rs:121:30 + --> $DIR/transmute.rs:125: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]` - --> $DIR/transmute.rs:122:30 + --> $DIR/transmute.rs:126: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]` - --> $DIR/transmute.rs:123:31 + --> $DIR/transmute.rs:127: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]` - --> $DIR/transmute.rs:124:30 + --> $DIR/transmute.rs:128: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]` - --> $DIR/transmute.rs:125:30 + --> $DIR/transmute.rs:129: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]` - --> $DIR/transmute.rs:126:31 + --> $DIR/transmute.rs:130:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `&[u8]` to a `&str` - --> $DIR/transmute.rs:134:28 + --> $DIR/transmute.rs:138:28 | LL | let _: &str = unsafe { std::mem::transmute(b) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()` @@ -235,7 +235,7 @@ LL | let _: &str = unsafe { std::mem::transmute(b) }; = note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings` error: transmute from a `&mut [u8]` to a `&mut str` - --> $DIR/transmute.rs:135:32 + --> $DIR/transmute.rs:139:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`