From 5e819bbfd66e91cf3bcad720af936e0b56843e3c Mon Sep 17 00:00:00 2001 From: Arc8ne Date: Fri, 27 Jun 2025 17:11:16 +0800 Subject: [PATCH 1/2] Make `transmute_ptr_to_ref` suggestion work correctly with some outer expression types and add a few new test cases to verify this. --- .../src/transmute/transmute_ptr_to_ref.rs | 19 ++++++- tests/ui/transmute_ptr_to_ref.fixed | 50 +++++++++++++++++++ tests/ui/transmute_ptr_to_ref.rs | 50 +++++++++++++++++++ tests/ui/transmute_ptr_to_ref.stderr | 26 +++++++++- 4 files changed, 142 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index e58212fae15c..d5eb919392a9 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -4,7 +4,7 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg; use rustc_errors::Applicability; -use rustc_hir::{self as hir, Expr, GenericArg, Mutability, Path, TyKind}; +use rustc_hir::{self as hir, Expr, ExprKind, GenericArg, Mutability, Path, TyKind, Node}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -59,7 +59,22 @@ pub(super) fn check<'tcx>( sugg::make_unop(deref, arg.as_ty(format!("{cast} {to_ref_ty}"))).to_string() }; - diag.span_suggestion(e.span, "try", sugg, app); + if let Node::Expr( + Expr { + kind: ExprKind::Call( + Expr { + kind: ExprKind::Call(..), + .. + }, + .. + ), + .. + } + ) = cx.tcx.parent_hir_node(e.hir_id) { + diag.span_suggestion(e.span, "try", format!("({sugg})"), app); + } else { + diag.span_suggestion(e.span, "try", sugg, app); + } }, ); true diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed index 61e3ac2fe88e..ad248aaaad41 100644 --- a/tests/ui/transmute_ptr_to_ref.fixed +++ b/tests/ui/transmute_ptr_to_ref.fixed @@ -106,4 +106,54 @@ unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { } } +unsafe fn _issue1754() { + let mut_num_func_ptr: *mut std::ffi::c_void = std::ptr::null_mut(); + + let num: u32 = 0; + + // If pointer cast is supported by MSRV. + unsafe { + // Not recommended. + (&mut *mut_num_func_ptr.cast::>())(&num); + //~^ transmute_ptr_to_ref + + // Recommended. + (&mut *mut_num_func_ptr.cast::>())(&num); + } + + // If pointer cast is not supported by MSRV. + #[clippy::msrv = "1.37"] + unsafe { + // Not recommended. + (&mut *(mut_num_func_ptr as *mut Box))(&num); + //~^ transmute_ptr_to_ref + + // Recommended. + (&mut *(mut_num_func_ptr as *mut Box))(&num); + }; + + let num_func_ptr: *const std::ffi::c_void = std::ptr::null_mut(); + + // If pointer cast is supported by MSRV. + unsafe { + // Not recommended. + (&*num_func_ptr.cast::>())(&num); + //~^ transmute_ptr_to_ref + + // Recommended. + (&*num_func_ptr.cast::>())(&num); + } + + // If pointer cast is not supported by MSRV. + #[clippy::msrv = "1.37"] + unsafe { + // Not recommended. + (&*(num_func_ptr as *const Box))(&num); + //~^ transmute_ptr_to_ref + + // Recommended. + (&*(num_func_ptr as *const Box))(&num); + }; +} + fn main() {} diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs index 48e2f527b554..5f19804d761a 100644 --- a/tests/ui/transmute_ptr_to_ref.rs +++ b/tests/ui/transmute_ptr_to_ref.rs @@ -106,4 +106,54 @@ unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 { } } +unsafe fn _issue1754() { + let mut_num_func_ptr: *mut std::ffi::c_void = std::ptr::null_mut(); + + let num: u32 = 0; + + // If pointer cast is supported by MSRV. + unsafe { + // Not recommended. + std::mem::transmute::<*mut std::ffi::c_void, &mut Box>(mut_num_func_ptr)(&num); + //~^ transmute_ptr_to_ref + + // Recommended. + (&mut *mut_num_func_ptr.cast::>())(&num); + } + + // If pointer cast is not supported by MSRV. + #[clippy::msrv = "1.37"] + unsafe { + // Not recommended. + std::mem::transmute::<*mut std::ffi::c_void, &mut Box>(mut_num_func_ptr)(&num); + //~^ transmute_ptr_to_ref + + // Recommended. + (&mut *(mut_num_func_ptr as *mut Box))(&num); + }; + + let num_func_ptr: *const std::ffi::c_void = std::ptr::null_mut(); + + // If pointer cast is supported by MSRV. + unsafe { + // Not recommended. + std::mem::transmute::<*const std::ffi::c_void, &Box>(num_func_ptr)(&num); + //~^ transmute_ptr_to_ref + + // Recommended. + (&*num_func_ptr.cast::>())(&num); + } + + // If pointer cast is not supported by MSRV. + #[clippy::msrv = "1.37"] + unsafe { + // Not recommended. + std::mem::transmute::<*const std::ffi::c_void, &Box>(num_func_ptr)(&num); + //~^ transmute_ptr_to_ref + + // Recommended. + (&*(num_func_ptr as *const Box))(&num); + }; +} + fn main() {} diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr index 7685c345c861..e9d4b60cb4aa 100644 --- a/tests/ui/transmute_ptr_to_ref.stderr +++ b/tests/ui/transmute_ptr_to_ref.stderr @@ -133,5 +133,29 @@ error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32 LL | _ => std::mem::transmute::<_, &&'b u32>(x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)` -error: aborting due to 22 previous errors +error: transmute from a pointer type (`*mut std::ffi::c_void`) to a reference type (`&mut std::boxed::Box std::ops::FnMut(&'a u32)>`) + --> tests/ui/transmute_ptr_to_ref.rs:117:9 + | +LL | std::mem::transmute::<*mut std::ffi::c_void, &mut Box>(mut_num_func_ptr)(&num); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&mut *mut_num_func_ptr.cast::>())` + +error: transmute from a pointer type (`*mut std::ffi::c_void`) to a reference type (`&mut std::boxed::Box std::ops::FnMut(&'a u32)>`) + --> tests/ui/transmute_ptr_to_ref.rs:128:9 + | +LL | std::mem::transmute::<*mut std::ffi::c_void, &mut Box>(mut_num_func_ptr)(&num); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&mut *(mut_num_func_ptr as *mut Box))` + +error: transmute from a pointer type (`*const std::ffi::c_void`) to a reference type (`&std::boxed::Box std::ops::Fn(&'a u32)>`) + --> tests/ui/transmute_ptr_to_ref.rs:140:9 + | +LL | std::mem::transmute::<*const std::ffi::c_void, &Box>(num_func_ptr)(&num); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&*num_func_ptr.cast::>())` + +error: transmute from a pointer type (`*const std::ffi::c_void`) to a reference type (`&std::boxed::Box std::ops::Fn(&'a u32)>`) + --> tests/ui/transmute_ptr_to_ref.rs:151:9 + | +LL | std::mem::transmute::<*const std::ffi::c_void, &Box>(num_func_ptr)(&num); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&*(num_func_ptr as *const Box))` + +error: aborting due to 26 previous errors From 6b0daf71163f60a5de9cc54c033f04068ce7c4cf Mon Sep 17 00:00:00 2001 From: Arc8ne Date: Fri, 27 Jun 2025 17:29:07 +0800 Subject: [PATCH 2/2] Format code. --- .../src/transmute/transmute_ptr_to_ref.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index d5eb919392a9..708361e3fe78 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -4,7 +4,7 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg; use rustc_errors::Applicability; -use rustc_hir::{self as hir, Expr, ExprKind, GenericArg, Mutability, Path, TyKind, Node}; +use rustc_hir::{self as hir, Expr, ExprKind, GenericArg, Mutability, Node, Path, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -59,18 +59,18 @@ pub(super) fn check<'tcx>( sugg::make_unop(deref, arg.as_ty(format!("{cast} {to_ref_ty}"))).to_string() }; - if let Node::Expr( - Expr { - kind: ExprKind::Call( + if let Node::Expr(Expr { + kind: + ExprKind::Call( Expr { kind: ExprKind::Call(..), .. }, - .. + .., ), - .. - } - ) = cx.tcx.parent_hir_node(e.hir_id) { + .. + }) = cx.tcx.parent_hir_node(e.hir_id) + { diag.span_suggestion(e.span, "try", format!("({sugg})"), app); } else { diag.span_suggestion(e.span, "try", sugg, app);