-
Notifications
You must be signed in to change notification settings - Fork 142
Closed
Labels
experience-hardThis issue is hard, and requires a lot of experienceThis issue is hard, and requires a lot of experience
Description
We ought to be able to simplify the code generated by zerocopy-derive's AsBytes impl by adding the following module to zerocopy:
/// Utilities used by `zerocopy-derive`.
///
/// These are defined in `zerocopy` rather than in code generated by
/// `zerocopy-derive` so that they can be compiled once rather than recompiled
/// for every pair of type and trait (in other words, if they were defined in
/// generated code, then deriving `AsBytes` and `FromBytes` on three different
/// types would result in the code in question being emitted and compiled six
/// different times).
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub mod derive_util {
/// Implemented for `Bool<true>`.
pub trait True {}
/// A boolean constant value which can be used in type bounds.
pub struct Bool<const TERM: bool>();
impl True for Bool<true> {}
/// Does the struct type `$t` have padding?
///
/// `$ts` is the list of the type of every field in `$t`. `$t` must be a
/// struct type, or else `has_padding!`'s result may be meaningless.
///
/// Note that `has_padding!`'s results are independent of `repr` since they
/// only consider the size of the type and the sizes of the fields. Whatever
/// the repr, the size of the type already takes into account any padding
/// that the compiler has decided to add. Note that while this is *probably*
/// also true of `repr(rust)`, the author is not confident of that fact, and
/// it should not be relied upon for soundness.
#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`.
#[macro_export]
macro_rules! has_padding {
($t:ty, $($ts:ty),*) => {
core::mem::size_of::<$t>() > 0 $(+ core::mem::size_of::<$ts>())*
};
}
}Then, for a type like:
#[derive(AsBytes)]
#[repr(C)]
struct Foo(u8, u16);...we'd emit an impl like:
unsafe impl AsBytes for Foo where Bool<{!zerocopy::has_padding!(Foo, u8, u16)}>: True {
fn only_derive_is_allowed_to_implement_this_trait()
where
Self: Sized,
{}
}Notably, this ought to make it a very simple change to support type parameters by emitting code like:
unsafe impl AsBytes for Bar<T> where Bool<{!zerocopy::has_padding!(Bar<T>, T)}>: True {
fn only_derive_is_allowed_to_implement_this_trait()
where
Self: Sized,
{}
}Of course, that code isn't a supported use of const generics today, but whenever it is in the future, the change will be simple.
We might be able to use a similar technique to simplify impls of other traits as well.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
experience-hardThis issue is hard, and requires a lot of experienceThis issue is hard, and requires a lot of experience