Skip to content

Commit e91d82e

Browse files
committed
Auto merge of #13143 - Alexendoo:transmute-ptr-to-ptr-suggestions, r=y21
Suggest `.cast`/`.cast_const`/`.cast_mut` in `transmute_ptr_as_ptr` Essentially pre-applies `ptr_as_ptr` - #6372 (comment) changelog: none
2 parents bd1224d + 7010d3c commit e91d82e

11 files changed

+309
-84
lines changed

Diff for: clippy_lints/src/casts/ptr_cast_constness.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use clippy_utils::sugg::Sugg;
44
use rustc_errors::Applicability;
55
use rustc_hir::{Expr, Mutability};
66
use rustc_lint::LateContext;
7-
use rustc_middle::ty::{self, Ty};
7+
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
88

99
use super::PTR_CAST_CONSTNESS;
1010

@@ -24,6 +24,7 @@ pub(super) fn check<'tcx>(
2424
(Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)
2525
)
2626
&& from_ty == to_ty
27+
&& !from_ty.has_erased_regions()
2728
{
2829
let sugg = Sugg::hir(cx, cast_expr, "_");
2930
let constness = match *to_mutbl {

Diff for: clippy_lints/src/transmute/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
617617
| missing_transmute_annotations::check(cx, path, from_ty, to_ty, e.hir_id)
618618
| transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context)
619619
| transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
620-
| transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)
620+
| transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, &self.msrv)
621621
| transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
622622
| transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
623623
| transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)

Diff for: clippy_lints/src/transmute/transmute_ptr_to_ptr.rs

+38-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use super::TRANSMUTE_PTR_TO_PTR;
2+
use clippy_config::msrvs::{self, Msrv};
23
use clippy_utils::diagnostics::span_lint_and_then;
34
use clippy_utils::sugg;
45
use rustc_errors::Applicability;
56
use rustc_hir::Expr;
67
use rustc_lint::LateContext;
7-
use rustc_middle::ty::{self, Ty};
8+
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
89

910
/// Checks for `transmute_ptr_to_ptr` lint.
1011
/// Returns `true` if it's triggered, otherwise returns `false`.
@@ -14,18 +15,50 @@ pub(super) fn check<'tcx>(
1415
from_ty: Ty<'tcx>,
1516
to_ty: Ty<'tcx>,
1617
arg: &'tcx Expr<'_>,
18+
msrv: &Msrv,
1719
) -> bool {
18-
match (&from_ty.kind(), &to_ty.kind()) {
19-
(ty::RawPtr(_, _), ty::RawPtr(to_ty, to_mutbl)) => {
20+
match (from_ty.kind(), to_ty.kind()) {
21+
(ty::RawPtr(from_pointee_ty, from_mutbl), ty::RawPtr(to_pointee_ty, to_mutbl)) => {
2022
span_lint_and_then(
2123
cx,
2224
TRANSMUTE_PTR_TO_PTR,
2325
e.span,
2426
"transmute from a pointer to a pointer",
2527
|diag| {
2628
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
27-
let sugg = arg.as_ty(Ty::new_ptr(cx.tcx, *to_ty, *to_mutbl));
28-
diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
29+
if from_mutbl == to_mutbl
30+
&& to_pointee_ty.is_sized(cx.tcx, cx.param_env)
31+
&& msrv.meets(msrvs::POINTER_CAST)
32+
{
33+
diag.span_suggestion_verbose(
34+
e.span,
35+
"use `pointer::cast` instead",
36+
format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_par()),
37+
Applicability::MaybeIncorrect,
38+
);
39+
} else if from_pointee_ty == to_pointee_ty
40+
&& let Some(method) = match (from_mutbl, to_mutbl) {
41+
(ty::Mutability::Not, ty::Mutability::Mut) => Some("cast_mut"),
42+
(ty::Mutability::Mut, ty::Mutability::Not) => Some("cast_const"),
43+
_ => None,
44+
}
45+
&& !from_pointee_ty.has_erased_regions()
46+
&& msrv.meets(msrvs::POINTER_CAST_CONSTNESS)
47+
{
48+
diag.span_suggestion_verbose(
49+
e.span,
50+
format!("use `pointer::{method}` instead"),
51+
format!("{}.{method}()", arg.maybe_par()),
52+
Applicability::MaybeIncorrect,
53+
);
54+
} else {
55+
diag.span_suggestion_verbose(
56+
e.span,
57+
"use an `as` cast instead",
58+
arg.as_ty(to_ty),
59+
Applicability::MaybeIncorrect,
60+
);
61+
}
2962
}
3063
},
3164
);

Diff for: tests/ui/ptr_cast_constness.fixed

+4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ fn main() {
4646
let _ = external!($ptr as *const u32);
4747
}
4848

49+
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
50+
v as _
51+
}
52+
4953
#[clippy::msrv = "1.64"]
5054
fn _msrv_1_64() {
5155
let ptr: *const u32 = &42_u32;

Diff for: tests/ui/ptr_cast_constness.rs

+4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ fn main() {
4646
let _ = external!($ptr as *const u32);
4747
}
4848

49+
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
50+
v as _
51+
}
52+
4953
#[clippy::msrv = "1.64"]
5054
fn _msrv_1_64() {
5155
let ptr: *const u32 = &42_u32;

Diff for: tests/ui/ptr_cast_constness.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ LL | let _ = mut_ptr as *const u32;
3232
| ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
3333

3434
error: `as` casting between raw pointers while changing only its constness
35-
--> tests/ui/ptr_cast_constness.rs:64:13
35+
--> tests/ui/ptr_cast_constness.rs:68:13
3636
|
3737
LL | let _ = ptr as *mut u32;
3838
| ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
3939

4040
error: `as` casting between raw pointers while changing only its constness
41-
--> tests/ui/ptr_cast_constness.rs:65:13
41+
--> tests/ui/ptr_cast_constness.rs:69:13
4242
|
4343
LL | let _ = mut_ptr as *const u32;
4444
| ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`

Diff for: tests/ui/transmute_ptr_to_ptr.fixed

+56-23
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
#![warn(clippy::transmute_ptr_to_ptr)]
22
#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
33

4+
use std::mem::transmute;
5+
46
// Make sure we can modify lifetimes, which is one of the recommended uses
57
// of transmute
68

79
// Make sure we can do static lifetime transmutes
810
unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T {
9-
std::mem::transmute::<&'a T, &'static T>(t)
11+
transmute::<&'a T, &'static T>(t)
1012
}
1113

1214
// Make sure we can do non-static lifetime transmutes
1315
unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T {
14-
std::mem::transmute::<&'a T, &'b T>(t)
16+
transmute::<&'a T, &'b T>(t)
1517
}
1618

1719
struct LifetimeParam<'a> {
@@ -27,47 +29,78 @@ fn transmute_ptr_to_ptr() {
2729
let mut_ptr = &mut 1u32 as *mut u32;
2830
unsafe {
2931
// pointer-to-pointer transmutes; bad
30-
let _: *const f32 = ptr as *const f32;
31-
//~^ ERROR: transmute from a pointer to a pointer
32-
//~| NOTE: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
33-
let _: *mut f32 = mut_ptr as *mut f32;
34-
//~^ ERROR: transmute from a pointer to a pointer
32+
let _: *const f32 = ptr.cast::<f32>();
33+
//~^ transmute_ptr_to_ptr
34+
let _: *mut f32 = mut_ptr.cast::<f32>();
35+
//~^ transmute_ptr_to_ptr
3536
// ref-ref transmutes; bad
3637
let _: &f32 = &*(&1u32 as *const u32 as *const f32);
37-
//~^ ERROR: transmute from a reference to a reference
38+
//~^ transmute_ptr_to_ptr
3839
let _: &f32 = &*(&1f64 as *const f64 as *const f32);
39-
//~^ ERROR: transmute from a reference to a reference
40+
//~^ transmute_ptr_to_ptr
4041
//:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not
4142
// the same type
4243
let _: &mut f32 = &mut *(&mut 1u32 as *mut u32 as *mut f32);
43-
//~^ ERROR: transmute from a reference to a reference
44+
//~^ transmute_ptr_to_ptr
4445
let _: &GenericParam<f32> = &*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>);
45-
//~^ ERROR: transmute from a reference to a reference
46+
//~^ transmute_ptr_to_ptr
4647
let u64_ref: &u64 = &0u64;
47-
let u8_ref: &u8 = unsafe { &*(u64_ref as *const u64 as *const u8) };
48-
//~^ ERROR: transmute from a reference to a reference
48+
let u8_ref: &u8 = &*(u64_ref as *const u64 as *const u8);
49+
//~^ transmute_ptr_to_ptr
50+
let _: *const u32 = mut_ptr.cast_const();
51+
//~^ transmute_ptr_to_ptr
52+
let _: *mut u32 = ptr.cast_mut();
53+
//~^ transmute_ptr_to_ptr
4954
}
5055

51-
// these are recommendations for solving the above; if these lint we need to update
52-
// those suggestions
53-
let _ = ptr as *const f32;
54-
let _ = mut_ptr as *mut f32;
55-
let _ = unsafe { &*(&1u32 as *const u32 as *const f32) };
56-
let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) };
57-
5856
// transmute internal lifetimes, should not lint
5957
let s = "hello world".to_owned();
6058
let lp = LifetimeParam { s: &s };
61-
let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) };
62-
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) };
59+
let _: &LifetimeParam<'static> = unsafe { transmute(&lp) };
60+
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) };
61+
}
62+
63+
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
64+
unsafe { v as *const &() }
65+
//~^ transmute_ptr_to_ptr
6366
}
6467

6568
// dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959)
6669
const _: &() = {
6770
struct Zst;
6871
let zst = &Zst;
6972

70-
unsafe { std::mem::transmute::<&'static Zst, &'static ()>(zst) }
73+
unsafe { transmute::<&'static Zst, &'static ()>(zst) }
7174
};
7275

76+
#[clippy::msrv = "1.37"]
77+
fn msrv_1_37(ptr: *const u8) {
78+
unsafe {
79+
let _: *const i8 = ptr as *const i8;
80+
}
81+
}
82+
83+
#[clippy::msrv = "1.38"]
84+
fn msrv_1_38(ptr: *const u8) {
85+
unsafe {
86+
let _: *const i8 = ptr.cast::<i8>();
87+
}
88+
}
89+
90+
#[clippy::msrv = "1.64"]
91+
fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) {
92+
unsafe {
93+
let _: *mut u8 = ptr as *mut u8;
94+
let _: *const u8 = mut_ptr as *const u8;
95+
}
96+
}
97+
98+
#[clippy::msrv = "1.65"]
99+
fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) {
100+
unsafe {
101+
let _: *mut u8 = ptr.cast_mut();
102+
let _: *const u8 = mut_ptr.cast_const();
103+
}
104+
}
105+
73106
fn main() {}

Diff for: tests/ui/transmute_ptr_to_ptr.rs

+60-27
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
#![warn(clippy::transmute_ptr_to_ptr)]
22
#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
33

4+
use std::mem::transmute;
5+
46
// Make sure we can modify lifetimes, which is one of the recommended uses
57
// of transmute
68

79
// Make sure we can do static lifetime transmutes
810
unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T {
9-
std::mem::transmute::<&'a T, &'static T>(t)
11+
transmute::<&'a T, &'static T>(t)
1012
}
1113

1214
// Make sure we can do non-static lifetime transmutes
1315
unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T {
14-
std::mem::transmute::<&'a T, &'b T>(t)
16+
transmute::<&'a T, &'b T>(t)
1517
}
1618

1719
struct LifetimeParam<'a> {
@@ -27,47 +29,78 @@ fn transmute_ptr_to_ptr() {
2729
let mut_ptr = &mut 1u32 as *mut u32;
2830
unsafe {
2931
// pointer-to-pointer transmutes; bad
30-
let _: *const f32 = std::mem::transmute(ptr);
31-
//~^ ERROR: transmute from a pointer to a pointer
32-
//~| NOTE: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
33-
let _: *mut f32 = std::mem::transmute(mut_ptr);
34-
//~^ ERROR: transmute from a pointer to a pointer
32+
let _: *const f32 = transmute(ptr);
33+
//~^ transmute_ptr_to_ptr
34+
let _: *mut f32 = transmute(mut_ptr);
35+
//~^ transmute_ptr_to_ptr
3536
// ref-ref transmutes; bad
36-
let _: &f32 = std::mem::transmute(&1u32);
37-
//~^ ERROR: transmute from a reference to a reference
38-
let _: &f32 = std::mem::transmute(&1f64);
39-
//~^ ERROR: transmute from a reference to a reference
37+
let _: &f32 = transmute(&1u32);
38+
//~^ transmute_ptr_to_ptr
39+
let _: &f32 = transmute(&1f64);
40+
//~^ transmute_ptr_to_ptr
4041
//:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not
4142
// the same type
42-
let _: &mut f32 = std::mem::transmute(&mut 1u32);
43-
//~^ ERROR: transmute from a reference to a reference
44-
let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
45-
//~^ ERROR: transmute from a reference to a reference
43+
let _: &mut f32 = transmute(&mut 1u32);
44+
//~^ transmute_ptr_to_ptr
45+
let _: &GenericParam<f32> = transmute(&GenericParam { t: 1u32 });
46+
//~^ transmute_ptr_to_ptr
4647
let u64_ref: &u64 = &0u64;
47-
let u8_ref: &u8 = unsafe { std::mem::transmute(u64_ref) };
48-
//~^ ERROR: transmute from a reference to a reference
48+
let u8_ref: &u8 = transmute(u64_ref);
49+
//~^ transmute_ptr_to_ptr
50+
let _: *const u32 = transmute(mut_ptr);
51+
//~^ transmute_ptr_to_ptr
52+
let _: *mut u32 = transmute(ptr);
53+
//~^ transmute_ptr_to_ptr
4954
}
5055

51-
// these are recommendations for solving the above; if these lint we need to update
52-
// those suggestions
53-
let _ = ptr as *const f32;
54-
let _ = mut_ptr as *mut f32;
55-
let _ = unsafe { &*(&1u32 as *const u32 as *const f32) };
56-
let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) };
57-
5856
// transmute internal lifetimes, should not lint
5957
let s = "hello world".to_owned();
6058
let lp = LifetimeParam { s: &s };
61-
let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) };
62-
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) };
59+
let _: &LifetimeParam<'static> = unsafe { transmute(&lp) };
60+
let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) };
61+
}
62+
63+
fn lifetime_to_static(v: *mut &()) -> *const &'static () {
64+
unsafe { transmute(v) }
65+
//~^ transmute_ptr_to_ptr
6366
}
6467

6568
// dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959)
6669
const _: &() = {
6770
struct Zst;
6871
let zst = &Zst;
6972

70-
unsafe { std::mem::transmute::<&'static Zst, &'static ()>(zst) }
73+
unsafe { transmute::<&'static Zst, &'static ()>(zst) }
7174
};
7275

76+
#[clippy::msrv = "1.37"]
77+
fn msrv_1_37(ptr: *const u8) {
78+
unsafe {
79+
let _: *const i8 = transmute(ptr);
80+
}
81+
}
82+
83+
#[clippy::msrv = "1.38"]
84+
fn msrv_1_38(ptr: *const u8) {
85+
unsafe {
86+
let _: *const i8 = transmute(ptr);
87+
}
88+
}
89+
90+
#[clippy::msrv = "1.64"]
91+
fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) {
92+
unsafe {
93+
let _: *mut u8 = transmute(ptr);
94+
let _: *const u8 = transmute(mut_ptr);
95+
}
96+
}
97+
98+
#[clippy::msrv = "1.65"]
99+
fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) {
100+
unsafe {
101+
let _: *mut u8 = transmute(ptr);
102+
let _: *const u8 = transmute(mut_ptr);
103+
}
104+
}
105+
73106
fn main() {}

0 commit comments

Comments
 (0)