Skip to content

Commit

Permalink
Allow generics in derive(ByteEq, ByteHash). (Lokathor#219)
Browse files Browse the repository at this point in the history
Note that the ergonomics are still not great, since `NoUninit` is also required to use `derive(ByteEq, ByteHash)`, and `derive(NoUninit)` doesn't support generics,
but that *explicitly* doesn't support generics, instead of silently ignoring generics like `derive(ByteEq, ByteHash)` used to, so this is strictly an improvement.
  • Loading branch information
zachs18 committed Jun 6, 2024
1 parent 2d07496 commit 62f1a5e
Showing 1 changed file with 29 additions and 5 deletions.
34 changes: 29 additions & 5 deletions bytemuck_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ pub fn derive_contiguous(
/// also does not implement `StructuralPartialEq` / `StructuralEq` like
/// `PartialEq` / `Eq` would. This means you can't pattern match on the values.
///
/// ## Example
/// ## Examples
///
/// ```rust
/// # use bytemuck_derive::{ByteEq, NoUninit};
Expand All @@ -402,23 +402,35 @@ pub fn derive_contiguous(
/// c: f32,
/// }
/// ```
///
/// ```rust
/// # use bytemuck_derive::ByteEq;
/// # use bytemuck::NoUninit;
/// #[derive(Copy, Clone, ByteEq)]
/// #[repr(C)]
/// struct Test<const N: usize> {
/// a: [u32; N],
/// }
/// unsafe impl<const N: usize> NoUninit for Test<N> {}
/// ```
#[proc_macro_derive(ByteEq)]
pub fn derive_byte_eq(
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let crate_name = bytemuck_crate_name(&input);
let ident = input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

proc_macro::TokenStream::from(quote! {
impl ::core::cmp::PartialEq for #ident {
impl #impl_generics ::core::cmp::PartialEq for #ident #ty_generics #where_clause {
#[inline]
#[must_use]
fn eq(&self, other: &Self) -> bool {
#crate_name::bytes_of(self) == #crate_name::bytes_of(other)
}
}
impl ::core::cmp::Eq for #ident { }
impl #impl_generics ::core::cmp::Eq for #ident #ty_generics #where_clause { }
})
}

Expand All @@ -431,7 +443,7 @@ pub fn derive_byte_eq(
///
/// The hash does not match the standard library's `Hash` derive.
///
/// ## Example
/// ## Examples
///
/// ```rust
/// # use bytemuck_derive::{ByteHash, NoUninit};
Expand All @@ -443,16 +455,28 @@ pub fn derive_byte_eq(
/// c: f32,
/// }
/// ```
///
/// ```rust
/// # use bytemuck_derive::ByteHash;
/// # use bytemuck::NoUninit;
/// #[derive(Copy, Clone, ByteHash)]
/// #[repr(C)]
/// struct Test<const N: usize> {
/// a: [u32; N],
/// }
/// unsafe impl<const N: usize> NoUninit for Test<N> {}
/// ```
#[proc_macro_derive(ByteHash)]
pub fn derive_byte_hash(
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let crate_name = bytemuck_crate_name(&input);
let ident = input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

proc_macro::TokenStream::from(quote! {
impl ::core::hash::Hash for #ident {
impl #impl_generics ::core::hash::Hash for #ident #ty_generics #where_clause {
#[inline]
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
::core::hash::Hash::hash_slice(#crate_name::bytes_of(self), state)
Expand Down

0 comments on commit 62f1a5e

Please sign in to comment.