Skip to content

Commit

Permalink
Simplify iml_for_transparent_wrapper! macro
Browse files Browse the repository at this point in the history
Signed-off-by: Joe Richey <[email protected]>
  • Loading branch information
josephlr committed Apr 4, 2024
1 parent 72f6694 commit 5f07d61
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 71 deletions.
36 changes: 18 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3967,12 +3967,12 @@ safety_comment! {
assert_unaligned!(PhantomData<()>, PhantomData<u8>, PhantomData<u64>);
}

impl_for_transparent_wrapper!(T: NoCell => NoCell for Wrapping<T>);
impl_for_transparent_wrapper!(T: TryFromBytes => TryFromBytes for Wrapping<T>);
impl_for_transparent_wrapper!(T: FromZeros => FromZeros for Wrapping<T>);
impl_for_transparent_wrapper!(T: FromBytes => FromBytes for Wrapping<T>);
impl_for_transparent_wrapper!(T: IntoBytes => IntoBytes for Wrapping<T>);
impl_for_transparent_wrapper!(T: Unaligned => Unaligned for Wrapping<T>);
impl_for_transparent_wrapper!(T => NoCell for Wrapping<T> [T]);
impl_for_transparent_wrapper!(T => TryFromBytes for Wrapping<T> [T]);
impl_for_transparent_wrapper!(T => FromZeros for Wrapping<T> [T]);
impl_for_transparent_wrapper!(T => FromBytes for Wrapping<T> [T]);
impl_for_transparent_wrapper!(T => IntoBytes for Wrapping<T> [T]);
impl_for_transparent_wrapper!(T => Unaligned for Wrapping<T> [T]);
assert_unaligned!(Wrapping<()>, Wrapping<u8>);

safety_comment! {
Expand All @@ -3984,23 +3984,23 @@ safety_comment! {
unsafe_impl!(T => FromBytes for MaybeUninit<T>);
}

impl_for_transparent_wrapper!(T: NoCell => NoCell for MaybeUninit<T>);
impl_for_transparent_wrapper!(T: Unaligned => Unaligned for MaybeUninit<T>);
impl_for_transparent_wrapper!(T => NoCell for MaybeUninit<T> [T]);
impl_for_transparent_wrapper!(T => Unaligned for MaybeUninit<T> [T]);
assert_unaligned!(MaybeUninit<()>, MaybeUninit<u8>);

impl_for_transparent_wrapper!(T: ?Sized + NoCell => NoCell for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + FromZeros => FromZeros for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized => NoCell for ManuallyDrop<T> [T]);
impl_for_transparent_wrapper!(T: ?Sized => TryFromBytes for ManuallyDrop<T> [T]);
impl_for_transparent_wrapper!(T: ?Sized => FromZeros for ManuallyDrop<T> [T]);
impl_for_transparent_wrapper!(T: ?Sized => FromBytes for ManuallyDrop<T> [T]);
impl_for_transparent_wrapper!(T: ?Sized => IntoBytes for ManuallyDrop<T> [T]);
impl_for_transparent_wrapper!(T: ?Sized => Unaligned for ManuallyDrop<T> [T]);
assert_unaligned!(ManuallyDrop<()>, ManuallyDrop<u8>);

// TODO(#5): Implement `FromZeros` and `FromBytes` when `T: ?Sized`.
impl_for_transparent_wrapper!(T: FromZeros => FromZeros for UnsafeCell<T>);
impl_for_transparent_wrapper!(T: FromBytes => FromBytes for UnsafeCell<T>);
impl_for_transparent_wrapper!(T: ?Sized + IntoBytes => IntoBytes for UnsafeCell<T>);
impl_for_transparent_wrapper!(T: ?Sized + Unaligned => Unaligned for UnsafeCell<T>);
impl_for_transparent_wrapper!(T => FromZeros for UnsafeCell<T> [T]);
impl_for_transparent_wrapper!(T => FromBytes for UnsafeCell<T> [T]);
impl_for_transparent_wrapper!(T: ?Sized => IntoBytes for UnsafeCell<T> [T]);
impl_for_transparent_wrapper!(T: ?Sized => Unaligned for UnsafeCell<T> [T]);
assert_unaligned!(UnsafeCell<()>, UnsafeCell<u8>);

// SAFETY: See safety comment in `is_bit_valid` impl.
Expand Down
64 changes: 11 additions & 53 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ macro_rules! unsafe_impl {
macro_rules! impl_for_transparent_wrapper {
(
$(#[$attr:meta])*
$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?
=> $trait:ident for $ty:ty $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
$($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?)? =>
$trait:ident for $ty:ty [$inner:ty]
) => {
$(#[$attr])*
#[allow(non_local_definitions)]
// SAFETY:
// - We explicitly add a `$tyvar: $trait` bound (regardless of what
// - We explicitly add a `$inner: $trait` bound (regardless of what
// bounds the caller has provided).
// - Inside of `only_derive_is_allowed_to_implement_this_trait`, `f` is
// generic over the any `I: Invariants`, and is generic over the same
Expand All @@ -228,74 +228,32 @@ macro_rules! impl_for_transparent_wrapper {
//
// Each `@is_transparent_wrapper` arm contains its own safety comment
// which explains why its bounds are sound.
unsafe impl<$tyvar: $($(? $optbound +)* $($bound +)*)? $trait> $trait for $ty {
unsafe impl<$($tyvar: $($(? $optbound +)* $($bound +)*)?)?> $trait for $ty where
$inner: $trait
{
#[allow(dead_code, clippy::missing_inline_in_public_items)]
fn only_derive_is_allowed_to_implement_this_trait() {
use crate::{pointer::invariant::Invariants, util::*};

impl_for_transparent_wrapper!(@is_transparent_wrapper $trait);

fn f<I: Invariants, $tyvar $(: $(? $optbound +)* $($bound +)*)?>() {
is_transparent_wrapper::<I, $tyvar, $ty>();
fn f<I: Invariants, $($tyvar $(: $(? $optbound +)* $($bound +)*)?)?>() {
is_transparent_wrapper::<I, $inner, $ty>();
}
}

impl_for_transparent_wrapper!(
@is_bit_valid
<$tyvar: $($(? $optbound +)* $($bound +)*)?>
$(<$tyvar: $($(? $optbound +)* $($bound +)*)?>)?
$trait for $ty
);
}
};
(
$(#[$attr:meta])*
for $ty:ty [$inner:ty] $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
) => {};
(
$(#[$attr:meta])*
$trait:ident $(, $traits:ident)* for $ty:ty [$inner:ty] $(; |$candidate:ident $(: MaybeAligned<$ref_repr:ty>)? $(: Maybe<$ptr_repr:ty>)?| $is_bit_valid:expr)?
$trait:ident for $ty:ty [$inner:ty]
) => {
impl_for_transparent_wrapper!(
$(#[$attr])*
$($traits),* for $ty [$inner] $(; |$candidate $(: MaybeAligned<$ref_repr>)? $(: Maybe<$ptr_repr>)?| $is_bit_valid:expr)?
);

$(#[$attr])*
#[allow(non_local_definitions)]
// SAFETY:
// - We explicitly add a `$tyvar: $trait` bound (regardless of what
// bounds the caller has provided).
// - Inside of `only_derive_is_allowed_to_implement_this_trait`, `f` is
// generic over the any `I: Invariants`.
// - `f` can only compile if its internal call to
// `is_transparent_wrapper` compiles.
//
// The definition of `is_transparent_wrapper<I, T, W>` is generated by
// each `@is_transparent_wrapper` macro arm. Each arm is parameterized
// by `$trait`, and emits bounds which are sufficient to ensure that
// this is a sound implementation of `$trait for W` *so long as* `T:
// $trait`. In `f`, we call `is_transparent_wrapper<I, $inner, $ty>`,
// and so if this code compiles, that guarantees that `$ty` satisfies
// the same bounds so long as `$inner: $trait`. Thus, so long as the
// bounds emitted by the `@is_transparent_wrapper` arm are sound, then
// this entire impl is sound.
//
// Each `@is_transparent_wrapper` arm contains its own safety comment
// which explains why its bounds are sound.
unsafe impl $trait for $ty {
#[allow(dead_code, clippy::missing_inline_in_public_items)]
fn only_derive_is_allowed_to_implement_this_trait() {
use crate::{pointer::invariant::Invariants, util::*};

impl_for_transparent_wrapper!(@is_transparent_wrapper $trait);

fn f<I: Invariants>() {
is_transparent_wrapper::<I, $inner, $ty>();
}
}

impl_for_transparent_wrapper!(@is_bit_valid $trait for $ty);
}
impl_for_transparent_wrapper!($(#[$attr])* => $trait for $ty [$inner]);
};
(@is_transparent_wrapper NoCell) => {
// SAFETY: `W: TransparentWrapper<UnsafeCellVariance=Covariant>`
Expand Down

0 comments on commit 5f07d61

Please sign in to comment.