Don't lint useless_transmute on types with erased regions

This commit is contained in:
Jason Newcomb 2022-03-18 00:58:03 -04:00
parent 2466a0507c
commit 9c9cca3e66
3 changed files with 85 additions and 71 deletions

View file

@ -4,7 +4,7 @@ use clippy_utils::sugg;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty::{self, Ty, TypeFoldable};
/// Checks for `useless_transmute` lint.
/// Returns `true` if it's triggered, otherwise returns `false`.
@ -16,7 +16,7 @@ pub(super) fn check<'tcx>(
arg: &'tcx Expr<'_>,
) -> bool {
match (&from_ty.kind(), &to_ty.kind()) {
_ if from_ty == to_ty => {
_ if from_ty == to_ty && !from_ty.has_erased_regions() => {
span_lint(
cx,
USELESS_TRANSMUTE,
@ -26,28 +26,31 @@ pub(super) fn check<'tcx>(
true
},
(ty::Ref(_, rty, rty_mutbl), ty::RawPtr(ptr_ty)) => {
span_lint_and_then(
cx,
USELESS_TRANSMUTE,
e.span,
"transmute from a reference to a pointer",
|diag| {
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
let rty_and_mut = ty::TypeAndMut {
ty: *rty,
mutbl: *rty_mutbl,
};
// No way to give the correct suggestion here. Avoid linting for now.
if !rty.has_erased_regions() {
span_lint_and_then(
cx,
USELESS_TRANSMUTE,
e.span,
"transmute from a reference to a pointer",
|diag| {
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
let rty_and_mut = ty::TypeAndMut {
ty: *rty,
mutbl: *rty_mutbl,
};
let sugg = if *ptr_ty == rty_and_mut {
arg.as_ty(to_ty)
} else {
arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty)
};
let sugg = if *ptr_ty == rty_and_mut {
arg.as_ty(to_ty)
} else {
arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty)
};
diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified);
}
},
);
diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified);
}
},
);
}
true
},
(ty::Int(_) | ty::Uint(_), ty::RawPtr(_)) => {

View file

@ -16,7 +16,8 @@ fn my_vec() -> MyVec<i32> {
#[allow(clippy::needless_lifetimes, clippy::transmute_ptr_to_ptr)]
#[warn(clippy::useless_transmute)]
unsafe fn _generic<'a, T, U: 'a>(t: &'a T) {
let _: &'a T = core::intrinsics::transmute(t);
// FIXME: should lint
// let _: &'a T = core::intrinsics::transmute(t);
let _: &'a U = core::intrinsics::transmute(t);
@ -48,6 +49,22 @@ fn useless() {
let _ = (1 + 1_usize) as *const usize;
}
unsafe fn _f<'a, 'b>(x: &'a u32) -> &'b u32 {
std::mem::transmute(x)
}
unsafe fn _f2<'a, 'b>(x: *const (dyn Iterator<Item = u32> + 'a)) -> *const (dyn Iterator<Item = u32> + 'b) {
std::mem::transmute(x)
}
unsafe fn _f3<'a, 'b>(x: fn(&'a u32)) -> fn(&'b u32) {
std::mem::transmute(x)
}
unsafe fn _f4<'a, 'b>(x: std::borrow::Cow<'a, str>) -> std::borrow::Cow<'b, str> {
std::mem::transmute(x)
}
}
struct Usize(usize);

View file

@ -1,73 +1,67 @@
error: transmute from a type (`&T`) to itself
--> $DIR/transmute.rs:19:20
error: transmute from a reference to a pointer
--> $DIR/transmute.rs:24:23
|
LL | let _: &'a T = core::intrinsics::transmute(t);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | let _: *const T = core::intrinsics::transmute(t);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T`
|
= note: `-D clippy::useless-transmute` implied by `-D warnings`
error: transmute from a reference to a pointer
--> $DIR/transmute.rs:23:23
|
LL | let _: *const T = core::intrinsics::transmute(t);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T`
error: transmute from a reference to a pointer
--> $DIR/transmute.rs:25:21
--> $DIR/transmute.rs:26:21
|
LL | let _: *mut T = core::intrinsics::transmute(t);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T`
error: transmute from a reference to a pointer
--> $DIR/transmute.rs:27:23
--> $DIR/transmute.rs:28:23
|
LL | let _: *const U = core::intrinsics::transmute(t);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U`
error: transmute from a type (`std::vec::Vec<i32>`) to itself
--> $DIR/transmute.rs:33:27
--> $DIR/transmute.rs:34:27
|
LL | let _: Vec<i32> = core::intrinsics::transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`std::vec::Vec<i32>`) to itself
--> $DIR/transmute.rs:35:27
--> $DIR/transmute.rs:36:27
|
LL | let _: Vec<i32> = core::mem::transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`std::vec::Vec<i32>`) to itself
--> $DIR/transmute.rs:37:27
--> $DIR/transmute.rs:38:27
|
LL | let _: Vec<i32> = std::intrinsics::transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`std::vec::Vec<i32>`) to itself
--> $DIR/transmute.rs:39:27
--> $DIR/transmute.rs:40:27
|
LL | let _: Vec<i32> = std::mem::transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`std::vec::Vec<i32>`) to itself
--> $DIR/transmute.rs:41:27
--> $DIR/transmute.rs:42:27
|
LL | let _: Vec<i32> = my_transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^
error: transmute from an integer to a pointer
--> $DIR/transmute.rs:43:31
--> $DIR/transmute.rs:44: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
--> $DIR/transmute.rs:47:31
--> $DIR/transmute.rs:48: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`)
--> $DIR/transmute.rs:62:24
--> $DIR/transmute.rs:79:24
|
LL | let _: Usize = core::intrinsics::transmute(int_const_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -75,25 +69,25 @@ LL | let _: Usize = core::intrinsics::transmute(int_const_ptr);
= note: `-D clippy::crosspointer-transmute` implied by `-D warnings`
error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
--> $DIR/transmute.rs:64:24
--> $DIR/transmute.rs:81:24
|
LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
--> $DIR/transmute.rs:66:31
--> $DIR/transmute.rs:83:31
|
LL | let _: *const Usize = core::intrinsics::transmute(my_int());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
--> $DIR/transmute.rs:68:29
--> $DIR/transmute.rs:85:29
|
LL | let _: *mut Usize = core::intrinsics::transmute(my_int());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: transmute from a `u32` to a `char`
--> $DIR/transmute.rs:74:28
--> $DIR/transmute.rs:91:28
|
LL | let _: char = unsafe { std::mem::transmute(0_u32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()`
@ -101,13 +95,13 @@ LL | let _: char = unsafe { std::mem::transmute(0_u32) };
= note: `-D clippy::transmute-int-to-char` implied by `-D warnings`
error: transmute from a `i32` to a `char`
--> $DIR/transmute.rs:75:28
--> $DIR/transmute.rs:92:28
|
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:84:28
--> $DIR/transmute.rs:101:28
|
LL | let _: bool = unsafe { std::mem::transmute(0_u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
@ -115,7 +109,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:90:31
--> $DIR/transmute.rs:107:31
|
LL | let _: f32 = unsafe { std::mem::transmute(0_u32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
@ -123,25 +117,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:91:31
--> $DIR/transmute.rs:108: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:92:31
--> $DIR/transmute.rs:109: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:93:31
--> $DIR/transmute.rs:110: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:113:30
--> $DIR/transmute.rs:130:30
|
LL | let _: [u8; 1] = std::mem::transmute(0u8);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
@ -149,85 +143,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:114:30
--> $DIR/transmute.rs:131: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:115:31
--> $DIR/transmute.rs:132: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:116:30
--> $DIR/transmute.rs:133: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:117:30
--> $DIR/transmute.rs:134: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:118:31
--> $DIR/transmute.rs:135: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:119:30
--> $DIR/transmute.rs:136: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:120:30
--> $DIR/transmute.rs:137: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:125:30
--> $DIR/transmute.rs:142: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:126:30
--> $DIR/transmute.rs:143: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:127:31
--> $DIR/transmute.rs:144: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:128:30
--> $DIR/transmute.rs:145: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:129:30
--> $DIR/transmute.rs:146: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:130:31
--> $DIR/transmute.rs:147: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:140:28
--> $DIR/transmute.rs:157:28
|
LL | let _: &str = unsafe { std::mem::transmute(B) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@ -235,16 +229,16 @@ 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:141:32
--> $DIR/transmute.rs:158: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`
--> $DIR/transmute.rs:142:30
--> $DIR/transmute.rs:159:30
|
LL | const _: &str = unsafe { std::mem::transmute(B) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
error: aborting due to 39 previous errors
error: aborting due to 38 previous errors