From fef1c01992c002a2a1e5118a6f1ceb4d4f0ebb2a Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 12:12:35 -0600 Subject: [PATCH 1/3] Change #![allow(clippy::missing_docs_in_private_items)] to #[allow(clippy::missing_docs_in_private_items)], also rustfmt went wild --- derive/src/traits.rs | 149 ++++++++++++++++++++++++++++--------------- 1 file changed, 98 insertions(+), 51 deletions(-) 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; From 8461fdbe2e4ff958b100a66c6b426e9c5979ba18 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 12:19:37 -0600 Subject: [PATCH 2/3] fix for 1.34 building. --- src/checked.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/checked.rs b/src/checked.rs index cc65869..9f55a6b 100644 --- a/src/checked.rs +++ b/src/checked.rs @@ -114,13 +114,13 @@ use crate::{ /// /// # Safety /// -/// * `Self` *must* have the same layout as the specified `Bits` except for -/// the possible invalid bit patterns being checked during -/// [`is_valid_bit_pattern`]. -/// * This almost certainly means your type must be `#[repr(C)]` or a similar +/// * `Self` *must* have the same layout as the specified `Bits` except for the +/// possible invalid bit patterns being checked during +/// [`is_valid_bit_pattern`]. +/// * This almost certainly means your type must be `#[repr(C)]` or a similar /// specified repr, but if you think you know better, you probably don't. If -/// you still think you know better, be careful and have fun. And don't mess -/// it up (I mean it). +/// you still think you know better, be careful and have fun. And don't mess +/// it up (I mean it). /// * If [`is_valid_bit_pattern`] returns true, then the bit pattern contained /// in `bits` must also be valid for an instance of `Self`. /// * Probably more, don't mess it up (I mean it 2.0) @@ -163,7 +163,10 @@ unsafe impl CheckedBitPattern for bool { #[inline] fn is_valid_bit_pattern(bits: &Self::Bits) -> bool { - matches!(*bits, 0 | 1) + match *bits { + 0 | 1 => true, + _ => false, + } } } From 8251252b47cb7685a24f97d0bacbbc73dd85bdc6 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 12:19:44 -0600 Subject: [PATCH 3/3] clippy be quiet --- src/allocation.rs | 1 + src/anybitpattern.rs | 21 ++++++++++++--------- src/checked.rs | 1 + src/lib.rs | 2 ++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/allocation.rs b/src/allocation.rs index bdcf724..1763ffd 100644 --- a/src/allocation.rs +++ b/src/allocation.rs @@ -1,4 +1,5 @@ #![cfg(feature = "extern_crate_alloc")] +#![allow(clippy::duplicated_attributes)] //! Stuff to boost things in the `alloc` crate. //! diff --git a/src/anybitpattern.rs b/src/anybitpattern.rs index 56c6bc6..3b98b09 100644 --- a/src/anybitpattern.rs +++ b/src/anybitpattern.rs @@ -2,12 +2,12 @@ use crate::{Pod, Zeroable}; /// Marker trait for "plain old data" types that are valid for any bit pattern. /// -/// The requirements for this is very similar to [`Pod`], -/// except that the type can allow uninit (or padding) bytes. -/// This limits what you can do with a type of this kind, but also broadens the -/// included types to `repr(C)` `struct`s that contain padding as well as -/// `union`s. Notably, you can only cast *immutable* references and *owned* -/// values into [`AnyBitPattern`] types, not *mutable* references. +/// The requirements for this is very similar to [`Pod`], except that the type +/// can allow uninit (or padding) bytes. This limits what you can do with a type +/// of this kind, but also broadens the included types to `repr(C)` `struct`s +/// that contain padding as well as `union`s. Notably, you can only cast +/// *immutable* references and *owned* values into [`AnyBitPattern`] types, not +/// *mutable* references. /// /// [`Pod`] is a subset of [`AnyBitPattern`], meaning that any `T: Pod` is also /// [`AnyBitPattern`] but any `T: AnyBitPattern` is not necessarily [`Pod`]. @@ -26,8 +26,8 @@ use crate::{Pod, Zeroable}; /// below safety rules. /// /// * *NOTE: even `C-style`, fieldless enums are intentionally **excluded** from -/// this trait, since it is **unsound** for an enum to have a discriminant value -/// that is not one of its defined variants. +/// this trait, since it is **unsound** for an enum to have a discriminant +/// value that is not one of its defined variants. /// /// # Safety /// @@ -56,6 +56,9 @@ pub unsafe trait AnyBitPattern: unsafe impl AnyBitPattern for T {} #[cfg(feature = "zeroable_maybe_uninit")] -#[cfg_attr(feature = "nightly_docs", doc(cfg(feature = "zeroable_maybe_uninit")))] +#[cfg_attr( + feature = "nightly_docs", + doc(cfg(feature = "zeroable_maybe_uninit")) +)] unsafe impl AnyBitPattern for core::mem::MaybeUninit where T: AnyBitPattern {} diff --git a/src/checked.rs b/src/checked.rs index 9f55a6b..cb8c4c3 100644 --- a/src/checked.rs +++ b/src/checked.rs @@ -163,6 +163,7 @@ unsafe impl CheckedBitPattern for bool { #[inline] fn is_valid_bit_pattern(bits: &Self::Bits) -> bool { + // DO NOT use the `matches!` macro, it isn't 1.34 compatible. match *bits { 0 | 1 => true, _ => false, diff --git a/src/lib.rs b/src/lib.rs index 3966627..daa8177 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,8 @@ #![warn(missing_docs)] #![allow(clippy::match_like_matches_macro)] #![allow(clippy::uninlined_format_args)] +#![allow(clippy::result_unit_err)] +#![allow(clippy::type_complexity)] #![cfg_attr(feature = "nightly_docs", feature(doc_cfg))] #![cfg_attr(feature = "nightly_portable_simd", feature(portable_simd))] #![cfg_attr(