Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/byte_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
}

Expand Down
15 changes: 8 additions & 7 deletions src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down Expand Up @@ -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) {
Expand Down
5 changes: 1 addition & 4 deletions src/pointer/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 0 additions & 7 deletions src/pointer/transmute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,21 +365,18 @@ where
//
// `ManuallyDrop<T>` 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<T>) };

// SAFETY:
// - `Unalign<T>` promises to have the same size as `T`.
// - `Unalign<T>` promises to have the same validity as `T`.
#[allow(clippy::multiple_unsafe_ops_per_block)]
const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T => Unalign<T>) };
// SAFETY: `Unalign<T>` promises to have the same size and validity as `T`.
// Given `u: &Unalign<T>`, it is already possible to obtain `let t =
// u.try_deref().unwrap()`. Because `Unalign<T>` has the same size as `T`, the
// 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<T>) };

// SAFETY:
Expand All @@ -404,15 +401,13 @@ const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Unalign<T>) };
// #[repr(transparent)]
// pub struct Wrapping<T>(pub T);
// ```
#[allow(clippy::multiple_unsafe_ops_per_block)]
const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T => Wrapping<T>) };

// SAFETY: By the preceding safety proof, `Wrapping<T>` and `T` have the same
// layout and bit validity. Since a `Wrapping<T>`'s `T` field is `pub`, given
// `w: &Wrapping<T>`, it's possible to do `let t = &w.t`, which means that it's
// already possible for safe code to obtain a `&Wrapping<T>` 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<T>) };

// SAFETY:
Expand All @@ -426,7 +421,6 @@ const _: () = unsafe { unsafe_impl_invariants_eq!(T => T, Wrapping<T>) };
// `UnsafeCell<T>` 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<T>`.
#[allow(clippy::multiple_unsafe_ops_per_block)]
const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => UnsafeCell<T>) };

// SAFETY:
Expand All @@ -448,7 +442,6 @@ const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => UnsafeC
// `UnsafeCell<T>` 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<T>`.
#[allow(clippy::multiple_unsafe_ops_per_block)]
const _: () = unsafe { unsafe_impl_for_transparent_wrapper!(T: ?Sized => Cell<T>) };

impl_transitive_transmute_from!(T: ?Sized => Cell<T> => T => UnsafeCell<T>);
Expand Down
39 changes: 26 additions & 13 deletions src/util/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
Expand All @@ -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
Expand Down Expand Up @@ -94,6 +99,7 @@ macro_rules! unsafe_impl {
) => {
unsafe_impl!(
@inner
check
$(#[$attr])*
@const $constname: $constty,
$($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
Expand All @@ -107,19 +113,21 @@ macro_rules! unsafe_impl {
) => {{
unsafe_impl!(
@inner
check
$(#[$attr])*
$($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
=> $trait for $ty $(; |$candidate| $is_bit_valid)?
);
}};
(
@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)]
Expand All @@ -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))]
Expand Down Expand Up @@ -741,6 +752,7 @@ macro_rules! unsafe_impl_for_transparent_wrapper {
#[inline(always)]
fn cast_from_raw(t: PtrInner<'_, T>) -> PtrInner<'_, $wrapper<T>> {
// SAFETY: See previous safety comment.
#[allow(clippy::multiple_unsafe_ops_per_block)]
unsafe { cast!(t) }
}
}
Expand All @@ -749,6 +761,7 @@ macro_rules! unsafe_impl_for_transparent_wrapper {
#[inline(always)]
fn cast_from_raw(t: PtrInner<'_, $wrapper<T>>) -> PtrInner<'_, T> {
// SAFETY: See previous safety comment.
#[allow(clippy::multiple_unsafe_ops_per_block)]
unsafe { cast!(t) }
}
}
Expand Down
Loading