From f0fe9947edbecf460f88ac8eca9d03d518330cd9 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 04:11:15 +0000 Subject: [PATCH] Resolve clippy::multiple_unsafe_ops_per_block violations --- src/byte_slice.rs | 17 +++++++++-------- src/layout.rs | 15 ++++++++------- src/pointer/ptr.rs | 5 +---- src/pointer/transmute.rs | 7 ------- src/util/macros.rs | 39 ++++++++++++++++++++++++++------------- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/byte_slice.rs b/src/byte_slice.rs index 4e42769014..d66cb7c19a 100644 --- a/src/byte_slice.rs +++ b/src/byte_slice.rs @@ -212,10 +212,11 @@ unsafe impl SplitByteSlice for &[u8] { unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { // SAFETY: By contract on caller, `mid` is not greater than // `bytes.len()`. - #[allow(clippy::multiple_unsafe_ops_per_block)] - unsafe { - (<[u8]>::get_unchecked(self, ..mid), <[u8]>::get_unchecked(self, mid..)) - } + let left = unsafe { <[u8]>::get_unchecked(self, ..mid) }; + // SAFETY: By contract on caller, `mid` is not greater than + // `bytes.len()`. + let right = unsafe { <[u8]>::get_unchecked(self, mid..) }; + (left, right) } } @@ -288,10 +289,10 @@ unsafe impl SplitByteSlice for &mut [u8] { // `isize::MAX`, by invariant on `self`. // // [1] https://doc.rust-lang.org/std/slice/fn.from_raw_parts_mut.html#safety - #[allow(clippy::multiple_unsafe_ops_per_block)] - unsafe { - (from_raw_parts_mut(l_ptr, l_len), from_raw_parts_mut(r_ptr, r_len)) - } + let left = unsafe { from_raw_parts_mut(l_ptr, l_len) }; + // SAFETY: See above. + let right = unsafe { from_raw_parts_mut(r_ptr, r_len) }; + (left, right) } } diff --git a/src/layout.rs b/src/layout.rs index 14419623bd..bf2718f31c 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -903,10 +903,12 @@ mod cast_from_raw { // Since the caller promises that `src_meta` is valid `Src` // metadata, this math will not overflow, and the returned value // will describe a `Dst` of the same size. - #[allow(unstable_name_collisions, clippy::multiple_unsafe_ops_per_block)] + #[allow(unstable_name_collisions)] + let product = unsafe { src_meta.unchecked_mul(self.elem_multiple) }; + // SAFETY: See above. + #[allow(unstable_name_collisions)] unsafe { - self.offset_delta_elems - .unchecked_add(src_meta.unchecked_mul(self.elem_multiple)) + self.offset_delta_elems.unchecked_add(product) } } } @@ -1504,10 +1506,9 @@ mod tests { } // SAFETY: `ptr` points to a valid `T`. - #[allow(clippy::multiple_unsafe_ops_per_block)] - let (size, align) = unsafe { - (mem::size_of_val_raw(ptr.as_ptr()), mem::align_of_val_raw(ptr.as_ptr())) - }; + let size = unsafe { mem::size_of_val_raw(ptr.as_ptr()) }; + // SAFETY: See above. + let align = unsafe { mem::align_of_val_raw(ptr.as_ptr()) }; // Avoid expensive allocation when running under Miri. let assert_msg = if !cfg!(miri) { diff --git a/src/pointer/ptr.rs b/src/pointer/ptr.rs index 7ada17bd7d..ec8059478f 100644 --- a/src/pointer/ptr.rs +++ b/src/pointer/ptr.rs @@ -913,10 +913,7 @@ mod _casts { // to `cast` which either reference a zero-sized byte range or // reference a byte range which is entirely contained inside of an // allocated object. - #[allow(clippy::multiple_unsafe_ops_per_block)] - unsafe { - self.transmute_unchecked(cast) - } + unsafe { self.transmute_unchecked(cast) } } /// Casts to a different (unsized) target type. diff --git a/src/pointer/transmute.rs b/src/pointer/transmute.rs index c1fa540af1..42df54e1d9 100644 --- a/src/pointer/transmute.rs +++ b/src/pointer/transmute.rs @@ -365,13 +365,11 @@ where // // `ManuallyDrop` is guaranteed to have the same layout and bit validity as // `T` -#[allow(clippy::multiple_unsafe_ops_per_block)] const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => ManuallyDrop) }; // SAFETY: // - `Unalign` promises to have the same size as `T`. // - `Unalign` promises to have the same validity as `T`. -#[allow(clippy::multiple_unsafe_ops_per_block)] const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T => Unalign) }; // SAFETY: `Unalign` promises to have the same size and validity as `T`. // Given `u: &Unalign`, it is already possible to obtain `let t = @@ -379,7 +377,6 @@ const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T => Unalign) }; // returned `&T` must point to the same referent as `u`, and thus it must be // sound for these two references to exist at the same time since it's already // possible for safe code to get into this state. -#[allow(clippy::multiple_unsafe_ops_per_block)] const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Unalign) }; // SAFETY: @@ -404,7 +401,6 @@ const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Unalign) }; // #[repr(transparent)] // pub struct Wrapping(pub T); // ``` -#[allow(clippy::multiple_unsafe_ops_per_block)] const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T => Wrapping) }; // SAFETY: By the preceding safety proof, `Wrapping` and `T` have the same @@ -412,7 +408,6 @@ const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T => Wrapping) }; // `w: &Wrapping`, it's possible to do `let t = &w.t`, which means that it's // already possible for safe code to obtain a `&Wrapping` and a `&T` pointing // to the same referent at the same time. Thus, this must be sound. -#[allow(clippy::multiple_unsafe_ops_per_block)] const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Wrapping) }; // SAFETY: @@ -426,7 +421,6 @@ const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Wrapping) }; // `UnsafeCell` has the same in-memory representation as its inner type // `T`. A consequence of this guarantee is that it is possible to convert // between `T` and `UnsafeCell`. -#[allow(clippy::multiple_unsafe_ops_per_block)] const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => UnsafeCell) }; // SAFETY: @@ -448,7 +442,6 @@ const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => UnsafeC // `UnsafeCell` has the same in-memory representation as its inner type // `T`. A consequence of this guarantee is that it is possible to convert // between `T` and `UnsafeCell`. -#[allow(clippy::multiple_unsafe_ops_per_block)] const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => Cell) }; impl_transitive_transmute_from!(T: ?Sized => Cell => T => UnsafeCell); diff --git a/src/util/macros.rs b/src/util/macros.rs index a20e838f92..82699a4fef 100644 --- a/src/util/macros.rs +++ b/src/util/macros.rs @@ -21,15 +21,14 @@ /// must only return `true` if its argument refers to a valid `$ty`. macro_rules! unsafe_impl { // Implement `$trait` for `$ty` with no bounds. - ($(#[$attr:meta])* $ty:ty: $trait:ident $(; |$candidate:ident| $is_bit_valid:expr)?) => {{ - crate::util::macros::__unsafe(); - - $(#[$attr])* - // SAFETY: The caller promises that this is sound. - unsafe impl $trait for $ty { - unsafe_impl!(@method $trait $(; |$candidate| $is_bit_valid)?); - } - }}; + ($(#[$attr:meta])* $ty:ty: $trait:ident $(; |$candidate:ident| $is_bit_valid:expr)?) => { + unsafe_impl!( + @inner + check + $(#[$attr])* + => $trait for $ty $(; |$candidate| $is_bit_valid)? + ); + }; // Implement all `$traits` for `$ty` with no bounds. // @@ -54,11 +53,17 @@ macro_rules! unsafe_impl { }; (@impl_traits_with_packed_attrs $attrs:tt $ty:ty: $($traits:ident),*) => {{ - $( unsafe_impl!(@unpack_attrs $attrs $ty: $traits); )* + crate::util::macros::__unsafe(); + $( unsafe_impl!(@unpack_attrs_no_check $attrs $ty: $traits); )* }}; - (@unpack_attrs { $(#[$attrs:meta])* } $ty:ty: $traits:ident) => { - unsafe_impl!($(#[$attrs])* $ty: $traits); + (@unpack_attrs_no_check { $(#[$attrs:meta])* } $ty:ty: $traits:ident) => { + unsafe_impl!( + @inner + no_check + $(#[$attrs])* + => $traits for $ty + ); }; // This arm is identical to the following one, except it contains a @@ -94,6 +99,7 @@ macro_rules! unsafe_impl { ) => { unsafe_impl!( @inner + check $(#[$attr])* @const $constname: $constty, $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)* @@ -107,6 +113,7 @@ macro_rules! unsafe_impl { ) => {{ unsafe_impl!( @inner + check $(#[$attr])* $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)* => $trait for $ty $(; |$candidate| $is_bit_valid)? @@ -114,12 +121,13 @@ macro_rules! unsafe_impl { }}; ( @inner + $check:tt $(#[$attr:meta])* $(@const $constname:ident : $constty:ident,)* $($tyvar:ident $(: $(? $optbound:ident +)* + $($bound:ident +)* )?,)* => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)? ) => {{ - crate::util::macros::__unsafe(); + unsafe_impl!(@unsafe_check $check); $(#[$attr])* #[allow(non_local_definitions)] @@ -129,6 +137,9 @@ macro_rules! unsafe_impl { } }}; + (@unsafe_check check) => { crate::util::macros::__unsafe(); }; + (@unsafe_check no_check) => {}; + (@method TryFromBytes ; |$candidate:ident| $is_bit_valid:expr) => { #[allow(clippy::missing_inline_in_public_items, dead_code)] #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))] @@ -741,6 +752,7 @@ macro_rules! unsafe_impl_for_transparent_wrapper { #[inline(always)] fn cast_from_raw(t: PtrInner<'_, T>) -> PtrInner<'_, $wrapper> { // SAFETY: See previous safety comment. + #[allow(clippy::multiple_unsafe_ops_per_block)] unsafe { cast!(t) } } } @@ -749,6 +761,7 @@ macro_rules! unsafe_impl_for_transparent_wrapper { #[inline(always)] fn cast_from_raw(t: PtrInner<'_, $wrapper>) -> PtrInner<'_, T> { // SAFETY: See previous safety comment. + #[allow(clippy::multiple_unsafe_ops_per_block)] unsafe { cast!(t) } } }