From ef24de24a82fe681581cc130f342363c47c0969a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:48 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/zerovec-derive/src/lib.rs | 7 ++- vendor/zerovec-derive/src/make_ule.rs | 25 ++-------- vendor/zerovec-derive/src/make_varule.rs | 78 +++++++++++++++++++++----------- vendor/zerovec-derive/src/utils.rs | 55 ++++++++++++++-------- 4 files changed, 96 insertions(+), 69 deletions(-) (limited to 'vendor/zerovec-derive/src') diff --git a/vendor/zerovec-derive/src/lib.rs b/vendor/zerovec-derive/src/lib.rs index 5a0de6429..9c3007147 100644 --- a/vendor/zerovec-derive/src/lib.rs +++ b/vendor/zerovec-derive/src/lib.rs @@ -5,8 +5,7 @@ //! Proc macros for generating `ULE`, `VarULE` impls and types for the `zerovec` crate use proc_macro::TokenStream; -use syn::{parse_macro_input, AttributeArgs, DeriveInput}; - +use syn::{parse_macro_input, DeriveInput, Ident}; mod make_ule; mod make_varule; pub(crate) mod ule; @@ -31,7 +30,7 @@ pub fn varule_derive(input: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn make_ule(attr: TokenStream, item: TokenStream) -> TokenStream { let input = parse_macro_input!(item as DeriveInput); - let attr = parse_macro_input!(attr as AttributeArgs); + let attr = parse_macro_input!(attr as Ident); TokenStream::from(make_ule::make_ule_impl(attr, input)) } @@ -39,6 +38,6 @@ pub fn make_ule(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn make_varule(attr: TokenStream, item: TokenStream) -> TokenStream { let input = parse_macro_input!(item as DeriveInput); - let attr = parse_macro_input!(attr as AttributeArgs); + let attr = parse_macro_input!(attr as Ident); TokenStream::from(make_varule::make_varule_impl(attr, input)) } diff --git a/vendor/zerovec-derive/src/make_ule.rs b/vendor/zerovec-derive/src/make_ule.rs index fb94cbc2c..92a200e0b 100644 --- a/vendor/zerovec-derive/src/make_ule.rs +++ b/vendor/zerovec-derive/src/make_ule.rs @@ -6,15 +6,11 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; use crate::utils::{self, FieldInfo, ZeroVecAttrs}; -use syn::spanned::Spanned; -use syn::{ - parse_quote, AttributeArgs, Data, DataEnum, DataStruct, DeriveInput, Error, Expr, Fields, - Ident, Lit, -}; - use std::collections::HashSet; +use syn::spanned::Spanned; +use syn::{parse_quote, Data, DataEnum, DataStruct, DeriveInput, Error, Expr, Fields, Ident, Lit}; -pub fn make_ule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStream2 { +pub fn make_ule_impl(ule_name: Ident, mut input: DeriveInput) -> TokenStream2 { if input.generics.type_params().next().is_some() || input.generics.lifetimes().next().is_some() || input.generics.const_params().next().is_some() @@ -25,17 +21,6 @@ pub fn make_ule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStream ) .to_compile_error(); } - - if attr.len() != 1 { - return Error::new( - input.span(), - "#[make_ule] takes one argument for the name of the ULE type it produces", - ) - .to_compile_error(); - } - let arg = &attr[0]; - let ule_name: Ident = parse_quote!(#arg); - let sp = input.span(); let attrs = match utils::extract_attributes_common(&mut input.attrs, sp, false) { Ok(val) => val, @@ -112,7 +97,7 @@ fn make_ule_enum_impl( let mut not_found = HashSet::new(); for (i, variant) in enu.variants.iter().enumerate() { - if variant.fields != Fields::Unit { + if !matches!(variant.fields, Fields::Unit) { // This can be supported in the future, see zerovec/design_doc.md return Error::new( variant.span(), @@ -225,7 +210,7 @@ fn make_ule_enum_impl( impl #name { /// Attempt to construct the value from its corresponding integer, - /// returning None if not possible + /// returning `None` if not possible pub(crate) fn new_from_u8(value: u8) -> Option { if value <= #max { unsafe { diff --git a/vendor/zerovec-derive/src/make_varule.rs b/vendor/zerovec-derive/src/make_varule.rs index 62cf0d9db..56aa0b4f3 100644 --- a/vendor/zerovec-derive/src/make_varule.rs +++ b/vendor/zerovec-derive/src/make_varule.rs @@ -8,11 +8,11 @@ use proc_macro2::TokenStream as TokenStream2; use quote::{quote, ToTokens}; use syn::spanned::Spanned; use syn::{ - parse_quote, AttributeArgs, Data, DeriveInput, Error, Field, Fields, GenericArgument, Ident, - Lifetime, PathArguments, Type, + parse_quote, Data, DeriveInput, Error, Field, Fields, GenericArgument, Ident, Lifetime, + PathArguments, Type, TypePath, }; -pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStream2 { +pub fn make_varule_impl(ule_name: Ident, mut input: DeriveInput) -> TokenStream2 { if input.generics.type_params().next().is_some() || input.generics.const_params().next().is_some() || input.generics.lifetimes().count() > 1 @@ -44,20 +44,11 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr let lt = lt.map(|l| &l.lifetime); - if attr.len() != 1 { - return Error::new( - input.span(), - "#[make_ule] takes one argument for the name of the ULE type it produces", - ) - .to_compile_error(); - } - let arg = &attr[0]; - let ule_name: Ident = parse_quote!(#arg); - let name = &input.ident; + let input_span = input.span(); let fields = match input.data { - Data::Struct(ref s) => &s.fields, + Data::Struct(ref mut s) => &mut s.fields, _ => { return Error::new(input.span(), "#[make_varule] must be applied to a struct") .to_compile_error(); @@ -75,16 +66,32 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr let mut sized_fields = vec![]; let mut unsized_fields = vec![]; + let mut custom_varule_idents = vec![]; + + for field in fields.iter_mut() { + match utils::extract_field_attributes(&mut field.attrs) { + Ok(i) => custom_varule_idents.push(i), + Err(e) => return e.to_compile_error(), + } + } + for (i, field) in fields.iter().enumerate() { - match UnsizedField::new(field, i) { + match UnsizedField::new(field, i, custom_varule_idents[i].clone()) { Ok(o) => unsized_fields.push(o), Err(_) => sized_fields.push(FieldInfo::new_for_field(field, i)), } } if unsized_fields.is_empty() { + let last_field_index = fields.len() - 1; let last_field = fields.iter().next_back().unwrap(); - let e = UnsizedField::new(last_field, fields.len() - 1).unwrap_err(); + + let e = UnsizedField::new( + last_field, + last_field_index, + custom_varule_idents[last_field_index].clone(), + ) + .unwrap_err(); return Error::new(last_field.span(), e).to_compile_error(); } @@ -112,10 +119,13 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr let field_inits = utils::wrap_field_inits(&field_inits, fields); let vis = &input.vis; - let doc = format!("[`VarULE`](zerovec::ule::VarULE) type for {name}"); + let doc = format!( + "[`VarULE`](zerovec::ule::VarULE) type for [`{name}`]. See [`{name}`] for documentation." + ); let varule_struct: DeriveInput = parse_quote!( #[repr(#repr_attr)] #[doc = #doc] + #[allow(missing_docs)] #vis struct #ule_name #field_inits #semi ); @@ -138,7 +148,7 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr name, &ule_name, lt, - input.span(), + input_span, ); let eq_impl = quote!( @@ -409,11 +419,13 @@ enum OwnULETy<'a> { } /// Represents the type of the last field of the struct -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] enum UnsizedFieldKind<'a> { Cow(OwnULETy<'a>), ZeroVec(&'a Type), VarZeroVec(&'a Type), + /// Custom VarULE type, and the identifier corresponding to the VarULE type + Custom(&'a TypePath, Ident), // Generally you should be using the above ones for maximum zero-copy, but these will still work Growable(OwnULETy<'a>), @@ -568,9 +580,13 @@ impl<'a> UnsizedFields<'a> { } impl<'a> UnsizedField<'a> { - fn new(field: &'a Field, index: usize) -> Result { + fn new( + field: &'a Field, + index: usize, + custom_varule_ident: Option, + ) -> Result { Ok(UnsizedField { - kind: UnsizedFieldKind::new(&field.ty)?, + kind: UnsizedFieldKind::new(&field.ty, custom_varule_ident)?, field: FieldInfo::new_for_field(field, index), }) } @@ -596,7 +612,10 @@ impl<'a> UnsizedField<'a> { impl<'a> UnsizedFieldKind<'a> { /// Construct a UnsizedFieldKind for the type of a UnsizedFieldKind if possible - fn new(ty: &'a Type) -> Result, String> { + fn new( + ty: &'a Type, + custom_varule_ident: Option, + ) -> Result, String> { static PATH_TYPE_IDENTITY_ERROR: &str = "Can only automatically detect corresponding VarULE types for path types \ that are Cow, ZeroVec, VarZeroVec, Box, String, or Vec"; @@ -607,6 +626,9 @@ impl<'a> UnsizedFieldKind<'a> { match *ty { Type::Reference(ref tyref) => OwnULETy::new(&tyref.elem, "reference").map(UnsizedFieldKind::Ref), Type::Path(ref typath) => { + if let Some(custom_varule_ident) = custom_varule_ident { + return Ok(UnsizedFieldKind::Custom(typath, custom_varule_ident)); + } if typath.path.segments.len() != 1 { return Err("Can only automatically detect corresponding VarULE types for \ path types with a single path segment".into()); @@ -678,6 +700,7 @@ impl<'a> UnsizedFieldKind<'a> { let inner_ule = inner.varule_ty(); quote!(#inner_ule) } + Self::Custom(_, ref name) => quote!(#name), Self::ZeroVec(ref inner) => quote!(zerovec::ZeroSlice<#inner>), Self::VarZeroVec(ref inner) => quote!(zerovec::VarZeroSlice<#inner>), } @@ -688,8 +711,8 @@ impl<'a> UnsizedFieldKind<'a> { match *self { Self::Ref(_) | Self::Cow(_) | Self::Growable(_) | Self::Boxed(_) => quote!(&*#value), - Self::ZeroVec(_) => quote!(&*#value), - Self::VarZeroVec(_) => quote!(&*#value), + Self::Custom(..) => quote!(&#value), + Self::ZeroVec(_) | Self::VarZeroVec(_) => quote!(&*#value), } } @@ -701,15 +724,16 @@ impl<'a> UnsizedFieldKind<'a> { | Self::Growable(ref inner) | Self::Boxed(ref inner) => inner.varule_ty(), - Self::ZeroVec(ty) => quote!(zerovec::ZeroSlice<#ty>), - Self::VarZeroVec(ty) => quote!(zerovec::VarZeroSlice<#ty>), + Self::Custom(ref path, _) => quote!(#path), + Self::ZeroVec(ref ty) => quote!(zerovec::ZeroSlice<#ty>), + Self::VarZeroVec(ref ty) => quote!(zerovec::VarZeroSlice<#ty>), } } fn has_zf(&self) -> bool { matches!( *self, - Self::Ref(_) | Self::Cow(_) | Self::ZeroVec(_) | Self::VarZeroVec(_) + Self::Ref(_) | Self::Cow(_) | Self::ZeroVec(_) | Self::VarZeroVec(_) | Self::Custom(..) ) } } diff --git a/vendor/zerovec-derive/src/utils.rs b/vendor/zerovec-derive/src/utils.rs index 3ebf33bf0..6d37444ca 100644 --- a/vendor/zerovec-derive/src/utils.rs +++ b/vendor/zerovec-derive/src/utils.rs @@ -9,19 +9,16 @@ use proc_macro2::TokenStream as TokenStream2; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::spanned::Spanned; -use syn::{parenthesized, parse2, Attribute, Error, Field, Fields, Ident, Index, Result, Token}; +use syn::{Attribute, Error, Field, Fields, Ident, Index, Result, Token}; // Check that there are repr attributes satisfying the given predicate pub fn has_valid_repr(attrs: &[Attribute], predicate: impl Fn(&Ident) -> bool + Copy) -> bool { - attrs - .iter() - .filter(|a| a.path.get_ident().map(|a| a == "repr").unwrap_or(false)) - .any(|a| { - parse2::(a.tokens.clone()) - .ok() - .and_then(|s| s.idents.iter().find(|s| predicate(s)).map(|_| ())) - .is_some() - }) + attrs.iter().filter(|a| a.path().is_ident("repr")).any(|a| { + a.parse_args::() + .ok() + .and_then(|s| s.idents.iter().find(|s| predicate(s)).map(|_| ())) + .is_some() + }) } // An attribute that is a list of idents @@ -31,10 +28,8 @@ struct IdentListAttribute { impl Parse for IdentListAttribute { fn parse(input: ParseStream) -> Result { - let content; - let _paren = parenthesized!(content in input); Ok(IdentListAttribute { - idents: content.parse_terminated(Ident::parse)?, + idents: input.parse_terminated(Ident::parse, Token![,])?, }) } } @@ -164,16 +159,16 @@ pub fn extract_parenthetical_zerovec_attrs( let mut error = None; attrs.retain(|a| { // skip the "zerovec" part - let second_segment = a.path.segments.iter().nth(1); + let second_segment = a.path().segments.iter().nth(1); if let Some(second) = second_segment { if second.ident == name { - let list = match parse2::(a.tokens.clone()) { + let list = match a.parse_args::() { Ok(l) => l, Err(_) => { error = Some(Error::new( a.span(), - "#[zerovec::name(..)] takes in a comma separated list of identifiers", + format!("#[zerovec::{name}(..)] takes in a comma separated list of identifiers"), )); return false; } @@ -196,7 +191,7 @@ pub fn extract_parenthetical_zerovec_attrs( pub fn extract_zerovec_attributes(attrs: &mut Vec) -> Vec { let mut ret = vec![]; attrs.retain(|a| { - if a.path.segments.len() == 2 && a.path.segments[0].ident == "zerovec" { + if a.path().segments.len() == 2 && a.path().segments[0].ident == "zerovec" { ret.push(a.clone()); return false; } @@ -205,6 +200,30 @@ pub fn extract_zerovec_attributes(attrs: &mut Vec) -> Vec ret } +/// Extract attributes from field, and return them +/// +/// Only current field attribute is `zerovec::varule(VarUleType)` +pub fn extract_field_attributes(attrs: &mut Vec) -> Result> { + let mut zerovec_attrs = extract_zerovec_attributes(attrs); + let varule = extract_parenthetical_zerovec_attrs(&mut zerovec_attrs, "varule")?; + + if varule.len() > 1 { + return Err(Error::new( + varule[1].span(), + "Found multiple #[zerovec::varule()] on one field", + )); + } + + if !zerovec_attrs.is_empty() { + return Err(Error::new( + zerovec_attrs[1].span(), + "Found unusable #[zerovec::] attrs on field, only #[zerovec::varule()] supported", + )); + } + + Ok(varule.get(0).cloned()) +} + #[derive(Default, Copy, Clone)] pub struct ZeroVecAttrs { pub skip_kv: bool, @@ -215,7 +234,7 @@ pub struct ZeroVecAttrs { pub hash: bool, } -/// Removes all known zerovec:: attributes from attrs and validates them +/// Removes all known zerovec:: attributes from struct attrs and validates them pub fn extract_attributes_common( attrs: &mut Vec, span: Span, -- cgit v1.2.3