From 9a27279008a0f841625f31d0afb963c9839629df Mon Sep 17 00:00:00 2001 From: zachs18 <8355914+zachs18@users.noreply.github.com> Date: Tue, 28 May 2024 17:52:54 +0000 Subject: [PATCH] Allow generics in `derive(ByteEq, ByteHash)`. (#219) 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. --- derive/src/lib.rs | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index ee8f235..cfe6270 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -377,7 +377,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}; @@ -389,6 +389,17 @@ pub fn derive_contiguous( /// c: f32, /// } /// ``` +/// +/// ```rust +/// # use bytemuck_derive::ByteEq; +/// # use bytemuck::NoUninit; +/// #[derive(Copy, Clone, ByteEq)] +/// #[repr(C)] +/// struct Test { +/// a: [u32; N], +/// } +/// unsafe impl NoUninit for Test {} +/// ``` #[proc_macro_derive(ByteEq)] pub fn derive_byte_eq( input: proc_macro::TokenStream, @@ -396,16 +407,17 @@ pub fn derive_byte_eq( 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 { } }) } @@ -418,7 +430,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}; @@ -430,6 +442,17 @@ pub fn derive_byte_eq( /// c: f32, /// } /// ``` +/// +/// ```rust +/// # use bytemuck_derive::ByteHash; +/// # use bytemuck::NoUninit; +/// #[derive(Copy, Clone, ByteHash)] +/// #[repr(C)] +/// struct Test { +/// a: [u32; N], +/// } +/// unsafe impl NoUninit for Test {} +/// ``` #[proc_macro_derive(ByteHash)] pub fn derive_byte_hash( input: proc_macro::TokenStream, @@ -437,9 +460,10 @@ pub fn derive_byte_hash( 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(&self, state: &mut H) { ::core::hash::Hash::hash_slice(#crate_name::bytes_of(self), state)