diff --git a/derive/src/traits.rs b/derive/src/traits.rs index 65aca40..89fc6c4 100644 --- a/derive/src/traits.rs +++ b/derive/src/traits.rs @@ -25,13 +25,17 @@ pub trait Derivable { fn implies_trait(_crate_name: &TokenStream) -> Option { None } - fn asserts(_input: &DeriveInput, _crate_name: &TokenStream) -> Result { + fn asserts( + _input: &DeriveInput, _crate_name: &TokenStream, + ) -> Result { Ok(quote!()) } fn check_attributes(_ty: &Data, _attributes: &[Attribute]) -> Result<()> { Ok(()) } - fn trait_impl(_input: &DeriveInput, _crate_name: &TokenStream) -> Result<(TokenStream, TokenStream)> { + fn trait_impl( + _input: &DeriveInput, _crate_name: &TokenStream, + ) -> Result<(TokenStream, TokenStream)> { Ok((quote!(), quote!())) } fn requires_where_clause() -> bool { @@ -49,7 +53,9 @@ impl Derivable for Pod { Ok(syn::parse_quote!(#crate_name::Pod)) } - fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result { + fn asserts( + input: &DeriveInput, crate_name: &TokenStream, + ) -> Result { let repr = get_repr(&input.attrs)?; let completly_packed = @@ -106,10 +112,14 @@ impl Derivable for AnyBitPattern { Some(quote!(#crate_name::Zeroable)) } - fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result { + fn asserts( + input: &DeriveInput, crate_name: &TokenStream, + ) -> Result { match &input.data { Data::Union(_) => Ok(quote!()), // unions are always `AnyBitPattern` - Data::Struct(_) => generate_fields_are_trait(input, Self::ident(input, crate_name)?), + Data::Struct(_) => { + generate_fields_are_trait(input, Self::ident(input, crate_name)?) + } Data::Enum(_) => { bail!("Deriving AnyBitPattern is not supported for enums") } @@ -128,7 +138,7 @@ impl Derivable for Zeroable { let repr = get_repr(attributes)?; match ty { Data::Struct(_) => Ok(()), - Data::Enum(DataEnum { variants,.. }) => { + Data::Enum(DataEnum { variants, .. }) => { if !repr.repr.is_integer() { bail!("Zeroable requires the enum to be an explicit #[repr(Int)]") } @@ -151,15 +161,19 @@ impl Derivable for Zeroable { } Ok(()) - }, - Data::Union(_) => Ok(()) + } + Data::Union(_) => Ok(()), } } - fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result { + fn asserts( + input: &DeriveInput, crate_name: &TokenStream, + ) -> Result { match &input.data { Data::Union(_) => Ok(quote!()), // unions are always `Zeroable` - Data::Struct(_) => generate_fields_are_trait(input, Self::ident(input, crate_name)?), + Data::Struct(_) => { + generate_fields_are_trait(input, Self::ident(input, crate_name)?) + } Data::Enum(_) => Ok(quote!()), } } @@ -192,7 +206,9 @@ impl Derivable for NoUninit { } } - fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result { + fn asserts( + input: &DeriveInput, crate_name: &TokenStream, + ) -> Result { if !input.generics.params.is_empty() { bail!("NoUninit cannot be derived for structs containing generic parameters because the padding requirements can't be verified for generic structs"); } @@ -219,7 +235,9 @@ impl Derivable for NoUninit { } } - fn trait_impl(_input: &DeriveInput, _crate_name: &TokenStream) -> Result<(TokenStream, TokenStream)> { + fn trait_impl( + _input: &DeriveInput, _crate_name: &TokenStream, + ) -> Result<(TokenStream, TokenStream)> { Ok((quote!(), quote!())) } } @@ -255,7 +273,9 @@ impl Derivable for CheckedBitPattern { } } - fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result { + fn asserts( + input: &DeriveInput, crate_name: &TokenStream, + ) -> Result { if !input.generics.params.is_empty() { bail!("CheckedBitPattern cannot be derived for structs containing generic parameters"); } @@ -267,15 +287,23 @@ impl Derivable for CheckedBitPattern { Ok(assert_fields_are_maybe_pod) } - Data::Enum(_) => Ok(quote!()), /* nothing needed, already guaranteed OK by NoUninit */ + Data::Enum(_) => Ok(quote!()), /* nothing needed, already guaranteed + * OK by NoUninit */ Data::Union(_) => bail!("Internal error in CheckedBitPattern derive"), /* shouldn't be possible since we already error in attribute check for this case */ } } - fn trait_impl(input: &DeriveInput, crate_name: &TokenStream) -> Result<(TokenStream, TokenStream)> { + fn trait_impl( + input: &DeriveInput, crate_name: &TokenStream, + ) -> Result<(TokenStream, TokenStream)> { match &input.data { Data::Struct(DataStruct { fields, .. }) => { - generate_checked_bit_pattern_struct(&input.ident, fields, &input.attrs, crate_name) + generate_checked_bit_pattern_struct( + &input.ident, + fields, + &input.attrs, + crate_name, + ) } Data::Enum(DataEnum { variants, .. }) => { generate_checked_bit_pattern_enum(input, variants, crate_name) @@ -322,7 +350,9 @@ impl Derivable for TransparentWrapper { Ok(syn::parse_quote!(#crate_name::TransparentWrapper<#ty>)) } - fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result { + fn asserts( + input: &DeriveInput, crate_name: &TokenStream, + ) -> Result { let (impl_generics, _ty_generics, where_clause) = input.generics.split_for_impl(); let fields = get_struct_fields(input)?; @@ -390,7 +420,9 @@ impl Derivable for Contiguous { Ok(syn::parse_quote!(#crate_name::Contiguous)) } - fn trait_impl(input: &DeriveInput, _crate_name: &TokenStream) -> Result<(TokenStream, TokenStream)> { + fn trait_impl( + input: &DeriveInput, _crate_name: &TokenStream, + ) -> Result<(TokenStream, TokenStream)> { let repr = get_repr(&input.attrs)?; let integer_ty = if let Some(integer_ty) = repr.repr.as_integer() { @@ -431,19 +463,19 @@ impl Derivable for Contiguous { let min_lit = LitInt::new(&format!("{}", min), input.span()); let max_lit = LitInt::new(&format!("{}", max), input.span()); - // `from_integer` and `into_integer` are usually provided by the trait's default implementation. - // We override this implementation because it goes through `transmute_copy`, which can lead to - // inefficient assembly as seen in https://github.com/Lokathor/bytemuck/issues/175 . + // `from_integer` and `into_integer` are usually provided by the trait's + // default implementation. We override this implementation because it + // goes through `transmute_copy`, which can lead to inefficient assembly as seen in https://github.com/Lokathor/bytemuck/issues/175 . Ok(( quote!(), quote! { type Int = #integer_ty; - #![allow(clippy::missing_docs_in_private_items)] + #[allow(clippy::missing_docs_in_private_items)] const MIN_VALUE: #integer_ty = #min_lit; - #![allow(clippy::missing_docs_in_private_items)] + #[allow(clippy::missing_docs_in_private_items)] const MAX_VALUE: #integer_ty = #max_lit; #[inline] @@ -498,7 +530,8 @@ fn get_field_types<'a>( } fn generate_checked_bit_pattern_struct( - input_ident: &Ident, fields: &Fields, attrs: &[Attribute], crate_name: &TokenStream + input_ident: &Ident, fields: &Fields, attrs: &[Attribute], + crate_name: &TokenStream, ) -> Result<(TokenStream, TokenStream)> { let bits_ty = Ident::new(&format!("{}Bits", input_ident), input_ident.span()); @@ -545,7 +578,8 @@ fn generate_checked_bit_pattern_struct( } fn generate_checked_bit_pattern_enum( - input: &DeriveInput, variants: &Punctuated, crate_name: &TokenStream + input: &DeriveInput, variants: &Punctuated, + crate_name: &TokenStream, ) -> Result<(TokenStream, TokenStream)> { if enum_has_fields(variants.iter()) { generate_checked_bit_pattern_enum_with_fields(input, variants, crate_name) @@ -614,7 +648,8 @@ fn generate_checked_bit_pattern_enum_without_fields( } fn generate_checked_bit_pattern_enum_with_fields( - input: &DeriveInput, variants: &Punctuated, crate_name: &TokenStream + input: &DeriveInput, variants: &Punctuated, + crate_name: &TokenStream, ) -> Result<(TokenStream, TokenStream)> { let representation = get_repr(&input.attrs)?; let vis = &input.vis; @@ -634,23 +669,28 @@ fn generate_checked_bit_pattern_enum_with_fields( let bits_repr = Representation { repr: Repr::C, ..representation }; - // the enum manually re-configured as the actual tagged union it represents, - // thus circumventing the requirements rust imposes on the tag even when using - // #[repr(C)] enum layout + // the enum manually re-configured as the actual tagged union it + // represents, thus circumventing the requirements rust imposes on + // the tag even when using #[repr(C)] enum layout // see: https://doc.rust-lang.org/reference/type-layout.html#reprc-enums-with-fields - let bits_ty_ident = Ident::new(&format!("{input_ident}Bits"), input.span()); - - // the variants union part of the tagged union. These get put into a union which gets the - // AnyBitPattern derive applied to it, thus checking that the fields of the union obey the requriements of AnyBitPattern. - // The types that actually go in the union are one more level of indirection deep: we generate new structs for each variant - // (`variant_struct_definitions`) which themselves have the `CheckedBitPattern` derive applied, thus generating `{variant_struct_ident}Bits` - // structs, which are the ones that go into this union. + let bits_ty_ident = + Ident::new(&format!("{input_ident}Bits"), input.span()); + + // the variants union part of the tagged union. These get put into a union + // which gets the AnyBitPattern derive applied to it, thus checking + // that the fields of the union obey the requriements of AnyBitPattern. + // The types that actually go in the union are one more level of + // indirection deep: we generate new structs for each variant + // (`variant_struct_definitions`) which themselves have the + // `CheckedBitPattern` derive applied, thus generating + // `{variant_struct_ident}Bits` structs, which are the ones that go + // into this union. let variants_union_ident = Ident::new(&format!("{}Variants", input.ident), input.span()); - let variant_struct_idents = variants - .iter() - .map(|v| Ident::new(&format!("{input_ident}Variant{}", v.ident), v.span())); + let variant_struct_idents = variants.iter().map(|v| { + Ident::new(&format!("{input_ident}Variant{}", v.ident), v.span()) + }); let variant_struct_definitions = variant_struct_idents.clone().zip(variants.iter()).map(|(variant_struct_ident, v)| { @@ -663,8 +703,10 @@ fn generate_checked_bit_pattern_enum_with_fields( } }); - let union_fields = - variant_struct_idents.clone().zip(variants.iter()).map(|(variant_struct_ident, v)| { + let union_fields = variant_struct_idents + .clone() + .zip(variants.iter()) + .map(|(variant_struct_ident, v)| { let variant_struct_bits_ident = Ident::new(&format!("{variant_struct_ident}Bits"), input.span()); let field_ident = &v.ident; @@ -764,17 +806,20 @@ fn generate_checked_bit_pattern_enum_with_fields( let bits_repr = Representation { repr: Repr::C, ..representation }; let input_ident = &input.ident; - // the enum manually re-configured as the union it represents. such a union is the union of variants - // as a repr(c) struct with the discriminator type inserted at the beginning. - // in our case we union the `Bits` representation of each variant rather than the variant itself, which we generate - // via a nested `CheckedBitPattern` derive on the `variant_struct_definitions` generated below. + // the enum manually re-configured as the union it represents. such a + // union is the union of variants as a repr(c) struct with the + // discriminator type inserted at the beginning. in our case we + // union the `Bits` representation of each variant rather than the variant + // itself, which we generate via a nested `CheckedBitPattern` derive + // on the `variant_struct_definitions` generated below. // // see: https://doc.rust-lang.org/reference/type-layout.html#primitive-representation-of-enums-with-fields - let bits_ty_ident = Ident::new(&format!("{input_ident}Bits"), input.span()); + let bits_ty_ident = + Ident::new(&format!("{input_ident}Bits"), input.span()); - let variant_struct_idents = variants - .iter() - .map(|v| Ident::new(&format!("{input_ident}Variant{}", v.ident), v.span())); + let variant_struct_idents = variants.iter().map(|v| { + Ident::new(&format!("{input_ident}Variant{}", v.ident), v.span()) + }); let variant_struct_definitions = variant_struct_idents.clone().zip(variants.iter()).map(|(variant_struct_ident, v)| { @@ -788,8 +833,10 @@ fn generate_checked_bit_pattern_enum_with_fields( } }); - let union_fields = - variant_struct_idents.clone().zip(variants.iter()).map(|(variant_struct_ident, v)| { + let union_fields = variant_struct_idents + .clone() + .zip(variants.iter()) + .map(|(variant_struct_ident, v)| { let variant_struct_bits_ident = Ident::new(&format!("{variant_struct_ident}Bits"), input.span()); let field_ident = &v.ident;