diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs index 70c2a73ce6ef..157755b38cef 100644 --- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet; use clippy_utils::{std_or_core, sugg}; use rustc_errors::Applicability; -use rustc_hir::{Expr, Mutability}; +use rustc_hir::{Expr, ExprKind, Mutability, Node}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; @@ -58,11 +58,21 @@ pub(super) fn check<'tcx>( let sugg_paren = arg .as_ty(Ty::new_ptr(cx.tcx, ty_from, from_mutbl)) .as_ty(Ty::new_ptr(cx.tcx, ty_to, to_mutbl)); - let sugg = if to_mutbl == Mutability::Mut { + let mut sugg = if to_mutbl == Mutability::Mut { sugg_paren.mut_addr_deref() } else { sugg_paren.addr_deref() }; + // If the expression is a receiver of some kind of a projection, we'll need to wrap the + // replacement in parens + if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id) + && let ExprKind::Index(recv, ..) + | ExprKind::Field(recv, _) + | ExprKind::MethodCall(_, recv, ..) = parent.kind + && recv.hir_id == e.hir_id + { + sugg = sugg.maybe_paren(); + } diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); } }, diff --git a/tests/ui/transmute_ptr_to_ptr.fixed b/tests/ui/transmute_ptr_to_ptr.fixed index 476e7e35a1f6..e0557ad9add6 100644 --- a/tests/ui/transmute_ptr_to_ptr.fixed +++ b/tests/ui/transmute_ptr_to_ptr.fixed @@ -1,5 +1,12 @@ #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)] +#![allow( + clippy::borrow_as_ptr, + clippy::missing_transmute_annotations, + clippy::let_unit_value, + clippy::unnecessary_mut_passed, + mutable_transmutes, + invalid_reference_casting +)] use std::mem::transmute; @@ -117,4 +124,24 @@ fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) { } } +fn issue15003(bs: &[u8]) { + unsafe { + (&mut *(bs as *const [u8] as *mut [u8]))[4] = 42; + //~^ transmute_ptr_to_ptr + let _ = (&mut *(bs as *const [u8] as *mut [u8])).len(); + //~^ transmute_ptr_to_ptr + // NOTE: need to transmute into something we can then index into + let _ = (&mut *(bs as *const [u8] as *mut (u8, [u8]))).0; + //~^ transmute_ptr_to_ptr + + // Don't add parens if the expression is not the receiver + struct S; + impl S { + fn foo(self, _: &mut [u8]) {} + } + let _ = S.foo(&mut *(bs as *const [u8] as *mut [u8])); + //~^ transmute_ptr_to_ptr + } +} + fn main() {} diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs index 7356668bcab5..7395f23678e4 100644 --- a/tests/ui/transmute_ptr_to_ptr.rs +++ b/tests/ui/transmute_ptr_to_ptr.rs @@ -1,5 +1,12 @@ #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)] +#![allow( + clippy::borrow_as_ptr, + clippy::missing_transmute_annotations, + clippy::let_unit_value, + clippy::unnecessary_mut_passed, + mutable_transmutes, + invalid_reference_casting +)] use std::mem::transmute; @@ -117,4 +124,24 @@ fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) { } } +fn issue15003(bs: &[u8]) { + unsafe { + transmute::<&[u8], &mut [u8]>(bs)[4] = 42; + //~^ transmute_ptr_to_ptr + let _ = transmute::<&[u8], &mut [u8]>(bs).len(); + //~^ transmute_ptr_to_ptr + // NOTE: need to transmute into something we can then index into + let _ = transmute::<&[u8], &mut (u8, [u8])>(bs).0; + //~^ transmute_ptr_to_ptr + + // Don't add parens if the expression is not the receiver + struct S; + impl S { + fn foo(self, _: &mut [u8]) {} + } + let _ = S.foo(transmute::<&[u8], &mut [u8]>(bs)); + //~^ transmute_ptr_to_ptr + } +} + fn main() {} diff --git a/tests/ui/transmute_ptr_to_ptr.stderr b/tests/ui/transmute_ptr_to_ptr.stderr index c8db4fe214fd..51f983e18ab0 100644 --- a/tests/ui/transmute_ptr_to_ptr.stderr +++ b/tests/ui/transmute_ptr_to_ptr.stderr @@ -1,5 +1,5 @@ error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:32:29 + --> tests/ui/transmute_ptr_to_ptr.rs:39:29 | LL | let _: *const f32 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + let _: *const f32 = ptr.cast::(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:35:27 + --> tests/ui/transmute_ptr_to_ptr.rs:42:27 | LL | let _: *mut f32 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -25,37 +25,37 @@ LL + let _: *mut f32 = mut_ptr.cast::(); | error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:39:23 + --> tests/ui/transmute_ptr_to_ptr.rs:46:23 | LL | let _: &f32 = transmute(&1u32); | ^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:42:23 + --> tests/ui/transmute_ptr_to_ptr.rs:49:23 | LL | let _: &f32 = transmute(&1f64); | ^^^^^^^^^^^^^^^^ help: try: `&*(&1f64 as *const f64 as *const f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:47:27 + --> tests/ui/transmute_ptr_to_ptr.rs:54:27 | LL | let _: &mut f32 = transmute(&mut 1u32); | ^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:50:37 + --> tests/ui/transmute_ptr_to_ptr.rs:57:37 | LL | let _: &GenericParam = transmute(&GenericParam { t: 1u32 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` error: transmute from a reference to a reference - --> tests/ui/transmute_ptr_to_ptr.rs:54:27 + --> tests/ui/transmute_ptr_to_ptr.rs:61:27 | LL | let u8_ref: &u8 = transmute(u64_ref); | ^^^^^^^^^^^^^^^^^^ help: try: `&*(u64_ref as *const u64 as *const u8)` error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:57:29 + --> tests/ui/transmute_ptr_to_ptr.rs:64:29 | LL | let _: *const u32 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL + let _: *const u32 = mut_ptr.cast_const(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:60:27 + --> tests/ui/transmute_ptr_to_ptr.rs:67:27 | LL | let _: *mut u32 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL + let _: *mut u32 = ptr.cast_mut(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:72:14 + --> tests/ui/transmute_ptr_to_ptr.rs:79:14 | LL | unsafe { transmute(v) } | ^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL + unsafe { v as *const &() } | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:87:28 + --> tests/ui/transmute_ptr_to_ptr.rs:94:28 | LL | let _: *const i8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL + let _: *const i8 = ptr as *const i8; | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:95:28 + --> tests/ui/transmute_ptr_to_ptr.rs:102:28 | LL | let _: *const i8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -115,7 +115,7 @@ LL + let _: *const i8 = ptr.cast::(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:103:26 + --> tests/ui/transmute_ptr_to_ptr.rs:110:26 | LL | let _: *mut u8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL + let _: *mut u8 = ptr as *mut u8; | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:105:28 + --> tests/ui/transmute_ptr_to_ptr.rs:112:28 | LL | let _: *const u8 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -139,7 +139,7 @@ LL + let _: *const u8 = mut_ptr as *const u8; | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:113:26 + --> tests/ui/transmute_ptr_to_ptr.rs:120:26 | LL | let _: *mut u8 = transmute(ptr); | ^^^^^^^^^^^^^^ @@ -151,7 +151,7 @@ LL + let _: *mut u8 = ptr.cast_mut(); | error: transmute from a pointer to a pointer - --> tests/ui/transmute_ptr_to_ptr.rs:115:28 + --> tests/ui/transmute_ptr_to_ptr.rs:122:28 | LL | let _: *const u8 = transmute(mut_ptr); | ^^^^^^^^^^^^^^^^^^ @@ -162,5 +162,29 @@ LL - let _: *const u8 = transmute(mut_ptr); LL + let _: *const u8 = mut_ptr.cast_const(); | -error: aborting due to 16 previous errors +error: transmute from a reference to a reference + --> tests/ui/transmute_ptr_to_ptr.rs:129:9 + | +LL | transmute::<&[u8], &mut [u8]>(bs)[4] = 42; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&mut *(bs as *const [u8] as *mut [u8]))` + +error: transmute from a reference to a reference + --> tests/ui/transmute_ptr_to_ptr.rs:131:17 + | +LL | let _ = transmute::<&[u8], &mut [u8]>(bs).len(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&mut *(bs as *const [u8] as *mut [u8]))` + +error: transmute from a reference to a reference + --> tests/ui/transmute_ptr_to_ptr.rs:134:17 + | +LL | let _ = transmute::<&[u8], &mut (u8, [u8])>(bs).0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&mut *(bs as *const [u8] as *mut (u8, [u8])))` + +error: transmute from a reference to a reference + --> tests/ui/transmute_ptr_to_ptr.rs:142:23 + | +LL | let _ = S.foo(transmute::<&[u8], &mut [u8]>(bs)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(bs as *const [u8] as *mut [u8])` + +error: aborting due to 20 previous errors