derive_more_impl/
utils.rs

1#![cfg_attr(
2    not(all(feature = "add", feature = "mul")),
3    allow(dead_code, unused_mut)
4)]
5
6use proc_macro2::TokenStream;
7use quote::{format_ident, quote, ToTokens};
8use syn::{
9    parse_quote, punctuated::Punctuated, spanned::Spanned, Attribute, Data,
10    DeriveInput, Error, Field, Fields, FieldsNamed, FieldsUnnamed, GenericParam,
11    Generics, Ident, Index, Result, Token, Type, TypeGenerics, TypeParamBound, Variant,
12    WhereClause,
13};
14
15#[cfg(any(
16    feature = "add",
17    feature = "add_assign",
18    feature = "as_ref",
19    feature = "debug",
20    feature = "display",
21    feature = "eq",
22    feature = "from",
23    feature = "from_str",
24    feature = "into",
25    feature = "mul",
26    feature = "mul_assign",
27    feature = "try_from",
28    feature = "try_into",
29))]
30pub(crate) use self::either::Either;
31#[cfg(any(feature = "from", feature = "into"))]
32pub(crate) use self::fields_ext::FieldsExt;
33#[cfg(any(
34    feature = "add",
35    feature = "add_assign",
36    feature = "as_ref",
37    feature = "eq",
38    feature = "from_str",
39    feature = "mul",
40    feature = "mul_assign",
41))]
42pub(crate) use self::generics_search::GenericsSearch;
43#[cfg(any(
44    feature = "add",
45    feature = "add_assign",
46    feature = "as_ref",
47    feature = "debug",
48    feature = "display",
49    feature = "eq",
50    feature = "from",
51    feature = "from_str",
52    feature = "into",
53    feature = "mul",
54    feature = "mul_assign",
55    feature = "try_from",
56    feature = "try_into",
57))]
58pub(crate) use self::spanning::Spanning;
59
60#[derive(Clone, Copy, Default)]
61pub struct DeterministicState;
62
63impl std::hash::BuildHasher for DeterministicState {
64    type Hasher = std::collections::hash_map::DefaultHasher;
65
66    fn build_hasher(&self) -> Self::Hasher {
67        Self::Hasher::default()
68    }
69}
70
71pub type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
72pub type HashSet<K> = std::collections::HashSet<K, DeterministicState>;
73
74#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
75pub enum RefType {
76    No,
77    Ref,
78    Mut,
79}
80
81impl RefType {
82    pub fn lifetime(self) -> TokenStream {
83        match self {
84            RefType::No => quote! {},
85            _ => quote! { '__deriveMoreLifetime },
86        }
87    }
88
89    pub fn reference(self) -> TokenStream {
90        match self {
91            RefType::No => quote! {},
92            RefType::Ref => quote! { & },
93            RefType::Mut => quote! { &mut },
94        }
95    }
96
97    pub fn mutability(self) -> TokenStream {
98        match self {
99            RefType::Mut => quote! { mut },
100            _ => quote! {},
101        }
102    }
103
104    pub fn pattern_ref(self) -> TokenStream {
105        match self {
106            RefType::Ref => quote! { ref },
107            RefType::Mut => quote! { ref mut },
108            RefType::No => quote! {},
109        }
110    }
111
112    pub fn reference_with_lifetime(self) -> TokenStream {
113        if !self.is_ref() {
114            return quote! {};
115        }
116        let lifetime = self.lifetime();
117        let mutability = self.mutability();
118        quote! { &#lifetime #mutability }
119    }
120
121    pub fn is_ref(self) -> bool {
122        !matches!(self, RefType::No)
123    }
124
125    pub fn from_attr_name(name: &str) -> Self {
126        match name {
127            "owned" => RefType::No,
128            "ref" => RefType::Ref,
129            "ref_mut" => RefType::Mut,
130            _ => panic!("`{name}` is not a `RefType`"),
131        }
132    }
133}
134
135pub fn numbered_vars(count: usize, prefix: &str) -> Vec<Ident> {
136    (0..count).map(|i| format_ident!("__{prefix}{i}")).collect()
137}
138
139pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> {
140    fields
141        .iter()
142        .map(|f| {
143            f.ident
144                .as_ref()
145                .expect("Tried to get field names of a tuple struct")
146        })
147        .collect()
148}
149
150pub fn get_field_types_iter<'a>(
151    fields: &'a [&'a Field],
152) -> Box<dyn Iterator<Item = &'a Type> + 'a> {
153    Box::new(fields.iter().map(|f| &f.ty))
154}
155
156pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> {
157    get_field_types_iter(fields).collect()
158}
159
160pub fn add_extra_type_param_bound_op_output<'a>(
161    generics: &'a Generics,
162    trait_ident: &'a Ident,
163) -> Generics {
164    let mut generics = generics.clone();
165    for type_param in &mut generics.type_params_mut() {
166        let type_ident = &type_param.ident;
167        let bound: TypeParamBound = parse_quote! {
168            derive_more::core::ops::#trait_ident<Output = #type_ident>
169        };
170        type_param.bounds.push(bound)
171    }
172
173    generics
174}
175
176pub fn add_extra_ty_param_bound<'a>(
177    generics: &'a Generics,
178    bound: &'a TokenStream,
179) -> Generics {
180    let mut generics = generics.clone();
181    let bound: TypeParamBound = parse_quote! { #bound };
182    for type_param in &mut generics.type_params_mut() {
183        type_param.bounds.push(bound.clone())
184    }
185
186    generics
187}
188
189pub fn add_extra_generic_param(
190    generics: &Generics,
191    generic_param: TokenStream,
192) -> Generics {
193    let generic_param: GenericParam = parse_quote! { #generic_param };
194    let mut generics = generics.clone();
195    generics.params.push(generic_param);
196
197    generics
198}
199
200pub fn add_extra_generic_type_param(
201    generics: &Generics,
202    generic_param: TokenStream,
203) -> Generics {
204    let generic_param: GenericParam = parse_quote! { #generic_param };
205    let lifetimes: Vec<GenericParam> =
206        generics.lifetimes().map(|x| x.clone().into()).collect();
207    let type_params: Vec<GenericParam> =
208        generics.type_params().map(|x| x.clone().into()).collect();
209    let const_params: Vec<GenericParam> =
210        generics.const_params().map(|x| x.clone().into()).collect();
211    let mut generics = generics.clone();
212    generics.params = Default::default();
213    generics.params.extend(lifetimes);
214    generics.params.extend(type_params);
215    generics.params.push(generic_param);
216    generics.params.extend(const_params);
217
218    generics
219}
220
221pub fn add_extra_where_clauses(
222    generics: &Generics,
223    type_where_clauses: TokenStream,
224) -> Generics {
225    let mut type_where_clauses: WhereClause = parse_quote! { #type_where_clauses };
226    let mut new_generics = generics.clone();
227    if let Some(old_where) = new_generics.where_clause {
228        type_where_clauses.predicates.extend(old_where.predicates)
229    }
230    new_generics.where_clause = Some(type_where_clauses);
231
232    new_generics
233}
234
235pub fn add_where_clauses_for_new_ident<'a>(
236    generics: &'a Generics,
237    fields: &[&'a Field],
238    type_ident: &Ident,
239    type_where_clauses: TokenStream,
240    sized: bool,
241) -> Generics {
242    let generic_param = if fields.len() > 1 {
243        quote! { #type_ident: derive_more::core::marker::Copy }
244    } else if sized {
245        quote! { #type_ident }
246    } else {
247        quote! { #type_ident: ?derive_more::core::marker::Sized }
248    };
249
250    let generics = add_extra_where_clauses(generics, type_where_clauses);
251    add_extra_generic_type_param(&generics, generic_param)
252}
253
254pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> {
255    fields.unnamed.iter().collect()
256}
257
258pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> {
259    fields.named.iter().collect()
260}
261
262pub(crate) fn panic_one_field(trait_name: &str, trait_attr: &str) -> ! {
263    panic!(
264        "derive({trait_name}) only works when forwarding to a single field. \
265         Try putting #[{trait_attr}] or #[{trait_attr}(ignore)] on the fields in the struct",
266    )
267}
268
269#[derive(Copy, Clone, Debug, PartialEq, Eq)]
270pub enum DeriveType {
271    Unnamed,
272    Named,
273    Enum,
274}
275
276pub struct State<'input> {
277    pub input: &'input DeriveInput,
278    pub trait_name: &'static str,
279    pub method_ident: Ident,
280    pub trait_path: TokenStream,
281    pub trait_path_params: Vec<TokenStream>,
282    pub trait_attr: String,
283    pub derive_type: DeriveType,
284    pub fields: Vec<&'input Field>,
285    pub variants: Vec<&'input Variant>,
286    pub variant_states: Vec<State<'input>>,
287    pub variant: Option<&'input Variant>,
288    pub generics: Generics,
289    pub default_info: FullMetaInfo,
290    full_meta_infos: Vec<FullMetaInfo>,
291}
292
293#[derive(Default, Clone)]
294pub struct AttrParams {
295    pub enum_: Vec<&'static str>,
296    pub variant: Vec<&'static str>,
297    pub struct_: Vec<&'static str>,
298    pub field: Vec<&'static str>,
299}
300
301impl AttrParams {
302    pub fn new(params: Vec<&'static str>) -> AttrParams {
303        AttrParams {
304            enum_: params.clone(),
305            struct_: params.clone(),
306            variant: params.clone(),
307            field: params,
308        }
309    }
310}
311
312impl<'input> State<'input> {
313    pub fn new<'arg_input>(
314        input: &'arg_input DeriveInput,
315        trait_name: &'static str,
316        trait_attr: String,
317    ) -> Result<State<'arg_input>> {
318        State::new_impl(input, trait_name, trait_attr, AttrParams::default(), true)
319    }
320
321    pub fn with_field_ignore<'arg_input>(
322        input: &'arg_input DeriveInput,
323        trait_name: &'static str,
324        trait_attr: String,
325    ) -> Result<State<'arg_input>> {
326        State::new_impl(
327            input,
328            trait_name,
329            trait_attr,
330            AttrParams::new(vec!["ignore"]),
331            true,
332        )
333    }
334
335    pub fn with_field_ignore_and_forward<'arg_input>(
336        input: &'arg_input DeriveInput,
337        trait_name: &'static str,
338        trait_attr: String,
339    ) -> Result<State<'arg_input>> {
340        State::new_impl(
341            input,
342            trait_name,
343            trait_attr,
344            AttrParams::new(vec!["ignore", "forward"]),
345            true,
346        )
347    }
348
349    pub fn with_field_ignore_and_refs<'arg_input>(
350        input: &'arg_input DeriveInput,
351        trait_name: &'static str,
352        trait_attr: String,
353    ) -> Result<State<'arg_input>> {
354        State::new_impl(
355            input,
356            trait_name,
357            trait_attr,
358            AttrParams::new(vec!["ignore", "owned", "ref", "ref_mut"]),
359            true,
360        )
361    }
362
363    pub fn with_attr_params<'arg_input>(
364        input: &'arg_input DeriveInput,
365        trait_name: &'static str,
366        trait_attr: String,
367        allowed_attr_params: AttrParams,
368    ) -> Result<State<'arg_input>> {
369        State::new_impl(input, trait_name, trait_attr, allowed_attr_params, true)
370    }
371
372    fn new_impl<'arg_input>(
373        input: &'arg_input DeriveInput,
374        trait_name: &'static str,
375        trait_attr: String,
376        allowed_attr_params: AttrParams,
377        add_type_bound: bool,
378    ) -> Result<State<'arg_input>> {
379        let trait_name = trait_name.trim_end_matches("ToInner");
380        let trait_ident = format_ident!("{trait_name}");
381        let method_ident = format_ident!("{trait_attr}");
382        let trait_path = quote! { derive_more::with_trait::#trait_ident };
383        let (derive_type, fields, variants): (_, Vec<_>, Vec<_>) = match input.data {
384            Data::Struct(ref data_struct) => match data_struct.fields {
385                Fields::Unnamed(ref fields) => {
386                    (DeriveType::Unnamed, unnamed_to_vec(fields), vec![])
387                }
388
389                Fields::Named(ref fields) => {
390                    (DeriveType::Named, named_to_vec(fields), vec![])
391                }
392                Fields::Unit => (DeriveType::Named, vec![], vec![]),
393            },
394            Data::Enum(ref data_enum) => (
395                DeriveType::Enum,
396                vec![],
397                data_enum.variants.iter().collect(),
398            ),
399            Data::Union(_) => {
400                panic!("cannot derive({trait_name}) for union")
401            }
402        };
403        let attrs: Vec<_> = if derive_type == DeriveType::Enum {
404            variants.iter().map(|v| &v.attrs).collect()
405        } else {
406            fields.iter().map(|f| &f.attrs).collect()
407        };
408
409        let (allowed_attr_params_outer, allowed_attr_params_inner) =
410            if derive_type == DeriveType::Enum {
411                (&allowed_attr_params.enum_, &allowed_attr_params.variant)
412            } else {
413                (&allowed_attr_params.struct_, &allowed_attr_params.field)
414            };
415
416        let struct_meta_info =
417            get_meta_info(&trait_attr, &input.attrs, allowed_attr_params_outer)?;
418        let meta_infos: Result<Vec<_>> = attrs
419            .iter()
420            .map(|attrs| get_meta_info(&trait_attr, attrs, allowed_attr_params_inner))
421            .collect();
422        let meta_infos = meta_infos?;
423        let first_match = meta_infos
424            .iter()
425            .find_map(|info| info.enabled.map(|_| info));
426
427        // Default to enabled true, except when first attribute has explicit
428        // enabling.
429        //
430        // Except for derive Error.
431        //
432        // The way `else` case works is that if any field have any valid
433        // attribute specified, then all fields without any attributes
434        // specified are filtered out from `State::enabled_fields`.
435        //
436        // However, derive Error *infers* fields and there are cases when
437        // one of the fields may have an attribute specified, but another field
438        // would be inferred. So, for derive Error macro we default enabled
439        // to true unconditionally (i.e., even if some fields have attributes
440        // specified).
441        let default_enabled = if trait_name == "Error" {
442            true
443        } else {
444            first_match.map_or(true, |info| !info.enabled.unwrap())
445        };
446
447        let defaults = struct_meta_info.into_full(FullMetaInfo {
448            enabled: default_enabled,
449            forward: false,
450            // Default to owned true, except when first attribute has one of owned,
451            // ref or ref_mut
452            // - not a single attribute means default true
453            // - an attribute, but non of owned, ref or ref_mut means default true
454            // - an attribute, and owned, ref or ref_mut means default false
455            owned: first_match.map_or(true, |info| {
456                info.owned.is_none() && info.ref_.is_none() || info.ref_mut.is_none()
457            }),
458            ref_: false,
459            ref_mut: false,
460            info: MetaInfo::default(),
461        });
462
463        let full_meta_infos: Vec<_> = meta_infos
464            .into_iter()
465            .map(|info| info.into_full(defaults.clone()))
466            .collect();
467
468        let variant_states: Result<Vec<_>> = if derive_type == DeriveType::Enum {
469            variants
470                .iter()
471                .zip(full_meta_infos.iter().cloned())
472                .map(|(variant, info)| {
473                    State::from_variant(
474                        input,
475                        trait_name,
476                        trait_attr.clone(),
477                        allowed_attr_params.clone(),
478                        variant,
479                        info,
480                    )
481                })
482                .collect()
483        } else {
484            Ok(vec![])
485        };
486
487        let generics = if add_type_bound {
488            add_extra_ty_param_bound(&input.generics, &trait_path)
489        } else {
490            input.generics.clone()
491        };
492
493        Ok(State {
494            input,
495            trait_name,
496            method_ident,
497            trait_path,
498            trait_path_params: vec![],
499            trait_attr,
500            // input,
501            fields,
502            variants,
503            variant_states: variant_states?,
504            variant: None,
505            derive_type,
506            generics,
507            full_meta_infos,
508            default_info: defaults,
509        })
510    }
511
512    pub fn from_variant<'arg_input>(
513        input: &'arg_input DeriveInput,
514        trait_name: &'static str,
515        trait_attr: String,
516        allowed_attr_params: AttrParams,
517        variant: &'arg_input Variant,
518        default_info: FullMetaInfo,
519    ) -> Result<State<'arg_input>> {
520        let trait_name = trait_name.trim_end_matches("ToInner");
521        let trait_ident = format_ident!("{trait_name}");
522        let method_ident = format_ident!("{trait_attr}");
523        let trait_path = quote! { derive_more::with_trait::#trait_ident };
524        let (derive_type, fields): (_, Vec<_>) = match variant.fields {
525            Fields::Unnamed(ref fields) => {
526                (DeriveType::Unnamed, unnamed_to_vec(fields))
527            }
528
529            Fields::Named(ref fields) => (DeriveType::Named, named_to_vec(fields)),
530            Fields::Unit => (DeriveType::Named, vec![]),
531        };
532
533        let meta_infos: Result<Vec<_>> = fields
534            .iter()
535            .map(|f| &f.attrs)
536            .map(|attrs| get_meta_info(&trait_attr, attrs, &allowed_attr_params.field))
537            .collect();
538        let meta_infos = meta_infos?;
539
540        let first_match = meta_infos
541            .iter()
542            .find_map(|info| info.enabled.map(|_| info));
543
544        let default_enabled = if trait_name == "Error" {
545            true
546        } else {
547            first_match.map_or(true, |info| !info.enabled.unwrap())
548        };
549
550        let default_info = FullMetaInfo {
551            enabled: default_enabled,
552            ..default_info.clone()
553        };
554
555        let full_meta_infos: Vec<_> = meta_infos
556            .into_iter()
557            .map(|info| info.into_full(default_info.clone()))
558            .collect();
559
560        let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
561
562        Ok(State {
563            input,
564            trait_name,
565            trait_path,
566            trait_path_params: vec![],
567            trait_attr,
568            method_ident,
569            // input,
570            fields,
571            variants: vec![],
572            variant_states: vec![],
573            variant: Some(variant),
574            derive_type,
575            generics,
576            full_meta_infos,
577            default_info,
578        })
579    }
580    pub fn add_trait_path_type_param(&mut self, param: TokenStream) {
581        self.trait_path_params.push(param);
582    }
583
584    pub fn assert_single_enabled_field<'state>(
585        &'state self,
586    ) -> SingleFieldData<'input, 'state> {
587        if self.derive_type == DeriveType::Enum {
588            panic_one_field(self.trait_name, &self.trait_attr);
589        }
590        let data = self.enabled_fields_data();
591        if data.fields.len() != 1 {
592            panic_one_field(self.trait_name, &self.trait_attr);
593        };
594        SingleFieldData {
595            input_type: data.input_type,
596            field: data.fields[0],
597            field_type: data.field_types[0],
598            member: data.members[0].clone(),
599            info: data.infos[0].clone(),
600            trait_path: data.trait_path,
601            trait_path_with_params: data.trait_path_with_params.clone(),
602            casted_trait: data.casted_traits[0].clone(),
603            ty_generics: data.ty_generics.clone(),
604        }
605    }
606
607    pub fn enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state> {
608        if self.derive_type == DeriveType::Enum {
609            panic!("cannot derive({}) for enum", self.trait_name)
610        }
611        let fields = self.enabled_fields();
612        let field_idents = self.enabled_fields_idents();
613        let field_indexes = self.enabled_fields_indexes();
614        let field_types: Vec<_> = fields.iter().map(|f| &f.ty).collect();
615        let members: Vec<_> = field_idents
616            .iter()
617            .map(|ident| quote! { self.#ident })
618            .collect();
619        let trait_path = &self.trait_path;
620        let trait_path_with_params = if !self.trait_path_params.is_empty() {
621            let params = self.trait_path_params.iter();
622            quote! { #trait_path<#(#params),*> }
623        } else {
624            self.trait_path.clone()
625        };
626
627        let casted_traits: Vec<_> = field_types
628            .iter()
629            .map(|field_type| quote! { <#field_type as #trait_path_with_params> })
630            .collect();
631        let (_, ty_generics, _) = self.generics.split_for_impl();
632        let input_type = &self.input.ident;
633        let (variant_name, variant_type) = self.variant.map_or_else(
634            || (None, quote! { #input_type }),
635            |v| {
636                let variant_name = &v.ident;
637                (Some(variant_name), quote! { #input_type::#variant_name })
638            },
639        );
640        MultiFieldData {
641            input_type,
642            variant_type,
643            variant_name,
644            variant_info: self.default_info.clone(),
645            fields,
646            field_types,
647            field_indexes,
648            members,
649            infos: self.enabled_infos(),
650            field_idents,
651            method_ident: &self.method_ident,
652            trait_path,
653            trait_path_with_params,
654            casted_traits,
655            ty_generics,
656            state: self,
657        }
658    }
659
660    pub fn enabled_variant_data<'state>(
661        &'state self,
662    ) -> MultiVariantData<'input, 'state> {
663        if self.derive_type != DeriveType::Enum {
664            panic!("can only derive({}) for enum", self.trait_name)
665        }
666        let variants = self.enabled_variants();
667        MultiVariantData {
668            variants,
669            variant_states: self.enabled_variant_states(),
670            infos: self.enabled_infos(),
671        }
672    }
673
674    fn enabled_variants(&self) -> Vec<&'input Variant> {
675        self.variants
676            .iter()
677            .zip(self.full_meta_infos.iter().map(|info| info.enabled))
678            .filter(|(_, ig)| *ig)
679            .map(|(v, _)| *v)
680            .collect()
681    }
682
683    fn enabled_variant_states(&self) -> Vec<&State<'input>> {
684        self.variant_states
685            .iter()
686            .zip(self.full_meta_infos.iter().map(|info| info.enabled))
687            .filter(|(_, ig)| *ig)
688            .map(|(v, _)| v)
689            .collect()
690    }
691
692    pub fn enabled_fields(&self) -> Vec<&'input Field> {
693        self.fields
694            .iter()
695            .zip(self.full_meta_infos.iter().map(|info| info.enabled))
696            .filter(|(_, ig)| *ig)
697            .map(|(f, _)| *f)
698            .collect()
699    }
700
701    fn field_idents(&self) -> Vec<TokenStream> {
702        if self.derive_type == DeriveType::Named {
703            self.fields
704                .iter()
705                .map(|f| {
706                    f.ident
707                        .as_ref()
708                        .expect("Tried to get field names of a tuple struct")
709                        .to_token_stream()
710                })
711                .collect()
712        } else {
713            let count = self.fields.len();
714            (0..count)
715                .map(|i| Index::from(i).to_token_stream())
716                .collect()
717        }
718    }
719
720    fn enabled_fields_idents(&self) -> Vec<TokenStream> {
721        self.field_idents()
722            .into_iter()
723            .zip(self.full_meta_infos.iter().map(|info| info.enabled))
724            .filter(|(_, ig)| *ig)
725            .map(|(f, _)| f)
726            .collect()
727    }
728
729    fn enabled_fields_indexes(&self) -> Vec<usize> {
730        self.full_meta_infos
731            .iter()
732            .map(|info| info.enabled)
733            .enumerate()
734            .filter(|(_, ig)| *ig)
735            .map(|(i, _)| i)
736            .collect()
737    }
738    fn enabled_infos(&self) -> Vec<FullMetaInfo> {
739        self.full_meta_infos
740            .iter()
741            .filter(|info| info.enabled)
742            .cloned()
743            .collect()
744    }
745}
746
747#[derive(Clone)]
748pub struct SingleFieldData<'input, 'state> {
749    pub input_type: &'input Ident,
750    pub field: &'input Field,
751    pub field_type: &'input Type,
752    pub member: TokenStream,
753    pub info: FullMetaInfo,
754    pub trait_path: &'state TokenStream,
755    pub trait_path_with_params: TokenStream,
756    pub casted_trait: TokenStream,
757    pub ty_generics: TypeGenerics<'state>,
758}
759
760#[derive(Clone)]
761pub struct MultiFieldData<'input, 'state> {
762    pub input_type: &'input Ident,
763    pub variant_type: TokenStream,
764    pub variant_name: Option<&'input Ident>,
765    pub variant_info: FullMetaInfo,
766    pub fields: Vec<&'input Field>,
767    pub field_types: Vec<&'input Type>,
768    pub field_idents: Vec<TokenStream>,
769    pub field_indexes: Vec<usize>,
770    pub members: Vec<TokenStream>,
771    pub infos: Vec<FullMetaInfo>,
772    pub method_ident: &'state Ident,
773    pub trait_path: &'state TokenStream,
774    pub trait_path_with_params: TokenStream,
775    pub casted_traits: Vec<TokenStream>,
776    pub ty_generics: TypeGenerics<'state>,
777    pub state: &'state State<'input>,
778}
779
780pub struct MultiVariantData<'input, 'state> {
781    pub variants: Vec<&'input Variant>,
782    pub variant_states: Vec<&'state State<'input>>,
783    pub infos: Vec<FullMetaInfo>,
784}
785
786impl MultiFieldData<'_, '_> {
787    pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
788        let MultiFieldData {
789            variant_type,
790            field_idents,
791            ..
792        } = self;
793        if self.state.derive_type == DeriveType::Named {
794            quote! { #variant_type{#(#field_idents: #initializers),*} }
795        } else {
796            quote! { #variant_type(#(#initializers),*) }
797        }
798    }
799    pub fn matcher<T: ToTokens>(
800        &self,
801        indexes: &[usize],
802        bindings: &[T],
803    ) -> TokenStream {
804        let MultiFieldData { variant_type, .. } = self;
805        let full_bindings = (0..self.state.fields.len()).map(|i| {
806            indexes.iter().position(|index| i == *index).map_or_else(
807                || quote! { _ },
808                |found_index| bindings[found_index].to_token_stream(),
809            )
810        });
811        if self.state.derive_type == DeriveType::Named {
812            let field_idents = self.state.field_idents();
813            quote! { #variant_type{#(#field_idents: #full_bindings),*} }
814        } else {
815            quote! { #variant_type(#(#full_bindings),*) }
816        }
817    }
818}
819
820fn get_meta_info(
821    trait_attr: &str,
822    attrs: &[Attribute],
823    allowed_attr_params: &[&str],
824) -> Result<MetaInfo> {
825    let mut it = attrs.iter().filter(|a| {
826        a.meta
827            .path()
828            .segments
829            .first()
830            .map(|p| p.ident == trait_attr)
831            .unwrap_or_default()
832    });
833
834    let mut info = MetaInfo::default();
835
836    let Some(attr) = it.next() else {
837        return Ok(info);
838    };
839
840    if allowed_attr_params.is_empty() {
841        return Err(Error::new(attr.span(), "Attribute is not allowed here"));
842    }
843
844    info.enabled = Some(true);
845
846    if let Some(another_attr) = it.next() {
847        return Err(Error::new(
848            another_attr.span(),
849            "Only a single attribute is allowed",
850        ));
851    }
852
853    let list = match &attr.meta {
854        syn::Meta::Path(_) => {
855            if allowed_attr_params.contains(&"ignore") {
856                return Ok(info);
857            } else {
858                return Err(Error::new(
859                    attr.span(),
860                    format!(
861                        "Empty attribute is not allowed, add one of the following parameters: {}",
862                        allowed_attr_params.join(", "),
863                    ),
864                ));
865            }
866        }
867        syn::Meta::List(list) => list,
868        syn::Meta::NameValue(val) => {
869            return Err(Error::new(
870                val.span(),
871                "Attribute doesn't support name-value format here",
872            ));
873        }
874    };
875
876    parse_punctuated_nested_meta(
877        &mut info,
878        &list.parse_args_with(Punctuated::parse_terminated)?,
879        allowed_attr_params,
880        None,
881    )?;
882
883    Ok(info)
884}
885
886fn parse_punctuated_nested_meta(
887    info: &mut MetaInfo,
888    meta: &Punctuated<polyfill::Meta, Token![,]>,
889    allowed_attr_params: &[&str],
890    wrapper_name: Option<&str>,
891) -> Result<()> {
892    for meta in meta.iter() {
893        match meta {
894            polyfill::Meta::List(list) if list.path.is_ident("not") => {
895                if wrapper_name.is_some() {
896                    // Only single top-level `not` attribute is allowed.
897                    return Err(Error::new(
898                        list.span(),
899                        "Attribute doesn't support multiple multiple or nested `not` parameters",
900                    ));
901                }
902                parse_punctuated_nested_meta(
903                    info,
904                    &list.parse_args_with(Punctuated::parse_terminated)?,
905                    allowed_attr_params,
906                    Some("not"),
907                )?;
908            }
909
910            polyfill::Meta::List(list) => {
911                let path = &list.path;
912                if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
913                    return Err(Error::new(
914                        meta.span(),
915                        format!(
916                            "Attribute nested parameter not supported. \
917                             Supported attribute parameters are: {}",
918                            allowed_attr_params.join(", "),
919                        ),
920                    ));
921                }
922
923                let mut parse_nested = true;
924
925                let attr_name = path.get_ident().unwrap().to_string();
926                match (wrapper_name, attr_name.as_str()) {
927                    (None, "owned") => info.owned = Some(true),
928                    (None, "ref") => info.ref_ = Some(true),
929                    (None, "ref_mut") => info.ref_mut = Some(true),
930
931                    (None, "source") => info.source = Some(true),
932
933                    #[cfg(any(feature = "from", feature = "into"))]
934                    (None, "types")
935                    | (Some("owned"), "types")
936                    | (Some("ref"), "types")
937                    | (Some("ref_mut"), "types") => {
938                        parse_nested = false;
939                        for meta in &list.parse_args_with(
940                            Punctuated::<polyfill::NestedMeta, syn::token::Comma>::parse_terminated,
941                        )? {
942                            let typ: syn::Type = match meta {
943                                polyfill::NestedMeta::Meta(meta) => {
944                                    let polyfill::Meta::Path(path) = meta else {
945                                        return Err(Error::new(
946                                            meta.span(),
947                                            format!(
948                                                "Attribute doesn't support type {}",
949                                                quote! { #meta },
950                                            ),
951                                        ));
952                                    };
953                                    syn::TypePath {
954                                        qself: None,
955                                        path: path.clone().into(),
956                                    }
957                                    .into()
958                                }
959                                polyfill::NestedMeta::Lit(syn::Lit::Str(s)) => s.parse()?,
960                                polyfill::NestedMeta::Lit(lit) => return Err(Error::new(
961                                    lit.span(),
962                                    "Attribute doesn't support nested literals here",
963                                )),
964                            };
965
966                            for ref_type in wrapper_name
967                                .map(|n| vec![RefType::from_attr_name(n)])
968                                .unwrap_or_else(|| {
969                                    vec![RefType::No, RefType::Ref, RefType::Mut]
970                                })
971                            {
972                                if info
973                                    .types
974                                    .entry(ref_type)
975                                    .or_default()
976                                    .replace(typ.clone())
977                                    .is_some()
978                                {
979                                    return Err(Error::new(
980                                        typ.span(),
981                                        format!(
982                                            "Duplicate type `{}` specified",
983                                            quote! { #path },
984                                        ),
985                                    ));
986                                }
987                            }
988                        }
989                    }
990
991                    _ => {
992                        return Err(Error::new(
993                            list.span(),
994                            format!(
995                                "Attribute doesn't support nested parameter `{}` here",
996                                quote! { #path },
997                            ),
998                        ))
999                    }
1000                };
1001
1002                if parse_nested {
1003                    parse_punctuated_nested_meta(
1004                        info,
1005                        &list.parse_args_with(Punctuated::parse_terminated)?,
1006                        allowed_attr_params,
1007                        Some(&attr_name),
1008                    )?;
1009                }
1010            }
1011
1012            polyfill::Meta::Path(path) => {
1013                if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
1014                    return Err(Error::new(
1015                        meta.span(),
1016                        format!(
1017                            "Attribute parameter not supported. \
1018                             Supported attribute parameters are: {}",
1019                            allowed_attr_params.join(", "),
1020                        ),
1021                    ));
1022                }
1023
1024                let attr_name = path.get_ident().unwrap().to_string();
1025                match (wrapper_name, attr_name.as_str()) {
1026                    (None, "ignore") => info.enabled = Some(false),
1027                    (None, "forward") => info.forward = Some(true),
1028                    (Some("not"), "forward") => info.forward = Some(false),
1029                    (None, "owned") => info.owned = Some(true),
1030                    (None, "ref") => info.ref_ = Some(true),
1031                    (None, "ref_mut") => info.ref_mut = Some(true),
1032                    (None, "source") => info.source = Some(true),
1033                    (Some("not"), "source") => info.source = Some(false),
1034                    (Some("source"), "optional") => info.source_optional = Some(true),
1035                    (None, "backtrace") => info.backtrace = Some(true),
1036                    (Some("not"), "backtrace") => info.backtrace = Some(false),
1037                    _ => {
1038                        return Err(Error::new(
1039                            path.span(),
1040                            format!(
1041                                "Attribute doesn't support parameter `{}` here",
1042                                quote! { #path }
1043                            ),
1044                        ))
1045                    }
1046                }
1047            }
1048        }
1049    }
1050
1051    Ok(())
1052}
1053
1054// TODO: Remove this eventually, once all macros migrate to
1055//       custom typed attributes parsing.
1056/// Polyfill for [`syn`] 1.x AST.
1057pub(crate) mod polyfill {
1058    use proc_macro2::TokenStream;
1059    use quote::ToTokens;
1060    use syn::{
1061        ext::IdentExt as _,
1062        parse::{Parse, ParseStream, Parser},
1063        token, Token,
1064    };
1065
1066    #[derive(Clone)]
1067    pub(crate) enum PathOrKeyword {
1068        Path(syn::Path),
1069        Keyword(syn::Ident),
1070    }
1071
1072    impl Parse for PathOrKeyword {
1073        fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1074            if input.fork().parse::<syn::Path>().is_ok() {
1075                return input.parse().map(Self::Path);
1076            }
1077            syn::Ident::parse_any(input).map(Self::Keyword)
1078        }
1079    }
1080
1081    impl ToTokens for PathOrKeyword {
1082        fn to_tokens(&self, tokens: &mut TokenStream) {
1083            match self {
1084                Self::Path(p) => p.to_tokens(tokens),
1085                Self::Keyword(i) => i.to_tokens(tokens),
1086            }
1087        }
1088    }
1089
1090    impl PathOrKeyword {
1091        pub(crate) fn is_ident<I: ?Sized>(&self, ident: &I) -> bool
1092        where
1093            syn::Ident: PartialEq<I>,
1094        {
1095            match self {
1096                Self::Path(p) => p.is_ident(ident),
1097                Self::Keyword(i) => i == ident,
1098            }
1099        }
1100
1101        pub fn get_ident(&self) -> Option<&syn::Ident> {
1102            match self {
1103                Self::Path(p) => p.get_ident(),
1104                Self::Keyword(i) => Some(i),
1105            }
1106        }
1107    }
1108
1109    impl From<PathOrKeyword> for syn::Path {
1110        fn from(p: PathOrKeyword) -> Self {
1111            match p {
1112                PathOrKeyword::Path(p) => p,
1113                PathOrKeyword::Keyword(i) => i.into(),
1114            }
1115        }
1116    }
1117
1118    #[derive(Clone)]
1119    pub(crate) struct MetaList {
1120        pub(crate) path: PathOrKeyword,
1121        pub(crate) tokens: TokenStream,
1122    }
1123
1124    impl Parse for MetaList {
1125        fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1126            let path = input.parse::<PathOrKeyword>()?;
1127            let tokens;
1128            _ = syn::parenthesized!(tokens in input);
1129            Ok(Self {
1130                path,
1131                tokens: tokens.parse()?,
1132            })
1133        }
1134    }
1135
1136    impl ToTokens for MetaList {
1137        fn to_tokens(&self, tokens: &mut TokenStream) {
1138            self.path.to_tokens(tokens);
1139            token::Paren::default()
1140                .surround(tokens, |tokens| self.tokens.to_tokens(tokens))
1141        }
1142    }
1143
1144    impl MetaList {
1145        pub fn parse_args_with<F: Parser>(&self, parser: F) -> syn::Result<F::Output> {
1146            parser.parse2(self.tokens.clone())
1147        }
1148    }
1149
1150    #[derive(Clone)]
1151    pub(crate) enum Meta {
1152        Path(PathOrKeyword),
1153        List(MetaList),
1154    }
1155
1156    impl Parse for Meta {
1157        fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1158            let path = input.parse::<PathOrKeyword>()?;
1159            Ok(if input.peek(token::Paren) {
1160                let tokens;
1161                _ = syn::parenthesized!(tokens in input);
1162                Self::List(MetaList {
1163                    path,
1164                    tokens: tokens.parse()?,
1165                })
1166            } else {
1167                Self::Path(path)
1168            })
1169        }
1170    }
1171
1172    impl ToTokens for Meta {
1173        fn to_tokens(&self, tokens: &mut TokenStream) {
1174            match self {
1175                Self::Path(p) => p.to_tokens(tokens),
1176                Self::List(l) => l.to_tokens(tokens),
1177            }
1178        }
1179    }
1180
1181    #[derive(Clone)]
1182    pub(crate) enum NestedMeta {
1183        Meta(Meta),
1184        Lit(syn::Lit),
1185    }
1186
1187    impl Parse for NestedMeta {
1188        fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1189            if input.peek(syn::Lit)
1190                && !(input.peek(syn::LitBool) && input.peek2(Token![=]))
1191            {
1192                input.parse().map(Self::Lit)
1193            } else if input.peek(syn::Ident::peek_any)
1194                || input.peek(Token![::]) && input.peek3(syn::Ident::peek_any)
1195            {
1196                input.parse().map(Self::Meta)
1197            } else {
1198                Err(input.error("expected identifier or literal"))
1199            }
1200        }
1201    }
1202
1203    impl ToTokens for NestedMeta {
1204        fn to_tokens(&self, tokens: &mut TokenStream) {
1205            match self {
1206                Self::Meta(m) => m.to_tokens(tokens),
1207                Self::Lit(l) => l.to_tokens(tokens),
1208            }
1209        }
1210    }
1211}
1212
1213#[derive(Clone, Debug, Default)]
1214pub struct FullMetaInfo {
1215    pub enabled: bool,
1216    pub forward: bool,
1217    pub owned: bool,
1218    pub ref_: bool,
1219    pub ref_mut: bool,
1220    pub info: MetaInfo,
1221}
1222
1223#[derive(Clone, Debug, Default)]
1224pub struct MetaInfo {
1225    pub enabled: Option<bool>,
1226    pub forward: Option<bool>,
1227    pub owned: Option<bool>,
1228    pub ref_: Option<bool>,
1229    pub ref_mut: Option<bool>,
1230    pub source: Option<bool>,
1231    pub source_optional: Option<bool>,
1232    pub backtrace: Option<bool>,
1233    #[cfg(any(feature = "from", feature = "into"))]
1234    pub types: HashMap<RefType, HashSet<syn::Type>>,
1235}
1236
1237impl MetaInfo {
1238    fn into_full(self, defaults: FullMetaInfo) -> FullMetaInfo {
1239        FullMetaInfo {
1240            enabled: self.enabled.unwrap_or(defaults.enabled),
1241            forward: self.forward.unwrap_or(defaults.forward),
1242            owned: self.owned.unwrap_or(defaults.owned),
1243            ref_: self.ref_.unwrap_or(defaults.ref_),
1244            ref_mut: self.ref_mut.unwrap_or(defaults.ref_mut),
1245            info: self,
1246        }
1247    }
1248}
1249
1250impl FullMetaInfo {
1251    pub fn ref_types(&self) -> Vec<RefType> {
1252        let mut ref_types = vec![];
1253        if self.owned {
1254            ref_types.push(RefType::No);
1255        }
1256        if self.ref_ {
1257            ref_types.push(RefType::Ref);
1258        }
1259        if self.ref_mut {
1260            ref_types.push(RefType::Mut);
1261        }
1262        ref_types
1263    }
1264}
1265
1266pub fn get_if_type_parameter_used_in_type(
1267    type_parameters: &HashSet<syn::Ident>,
1268    ty: &syn::Type,
1269) -> Option<syn::Type> {
1270    is_type_parameter_used_in_type(type_parameters, ty).then(|| match ty {
1271        syn::Type::Reference(syn::TypeReference { elem: ty, .. }) => (**ty).clone(),
1272        ty => ty.clone(),
1273    })
1274}
1275
1276pub fn is_type_parameter_used_in_type(
1277    type_parameters: &HashSet<syn::Ident>,
1278    ty: &syn::Type,
1279) -> bool {
1280    match ty {
1281        syn::Type::Path(ty) => {
1282            if let Some(qself) = &ty.qself {
1283                if is_type_parameter_used_in_type(type_parameters, &qself.ty) {
1284                    return true;
1285                }
1286            }
1287
1288            if let Some(segment) = ty.path.segments.first() {
1289                if type_parameters.contains(&segment.ident) {
1290                    return true;
1291                }
1292            }
1293
1294            ty.path.segments.iter().any(|segment| {
1295                if let syn::PathArguments::AngleBracketed(arguments) =
1296                    &segment.arguments
1297                {
1298                    arguments.args.iter().any(|argument| match argument {
1299                        syn::GenericArgument::Type(ty) => {
1300                            is_type_parameter_used_in_type(type_parameters, ty)
1301                        }
1302                        syn::GenericArgument::Constraint(constraint) => {
1303                            type_parameters.contains(&constraint.ident)
1304                        }
1305                        _ => false,
1306                    })
1307                } else {
1308                    false
1309                }
1310            })
1311        }
1312
1313        syn::Type::Reference(ty) => {
1314            is_type_parameter_used_in_type(type_parameters, &ty.elem)
1315        }
1316
1317        _ => false,
1318    }
1319}
1320
1321#[cfg(any(
1322    feature = "add",
1323    feature = "add_assign",
1324    feature = "as_ref",
1325    feature = "debug",
1326    feature = "display",
1327    feature = "eq",
1328    feature = "from",
1329    feature = "from_str",
1330    feature = "into",
1331    feature = "mul",
1332    feature = "mul_assign",
1333    feature = "try_from",
1334    feature = "try_into",
1335))]
1336mod either {
1337    use proc_macro2::TokenStream;
1338    use quote::ToTokens;
1339    use syn::parse::{discouraged::Speculative as _, Parse, ParseStream};
1340
1341    /// Either [`Left`] or [`Right`].
1342    ///
1343    /// [`Left`]: Either::Left
1344    /// [`Right`]: Either::Right
1345    #[derive(Clone, Copy, Debug)]
1346    pub(crate) enum Either<L, R> {
1347        /// Left variant.
1348        Left(L),
1349
1350        /// Right variant.
1351        Right(R),
1352    }
1353
1354    impl<L, R> Parse for Either<L, R>
1355    where
1356        L: Parse,
1357        R: Parse,
1358    {
1359        fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1360            let ahead = input.fork();
1361            if let Ok(left) = ahead.parse::<L>() {
1362                input.advance_to(&ahead);
1363                Ok(Self::Left(left))
1364            } else {
1365                input.parse::<R>().map(Self::Right)
1366            }
1367        }
1368    }
1369
1370    impl<L, R, T> Iterator for Either<L, R>
1371    where
1372        L: Iterator<Item = T>,
1373        R: Iterator<Item = T>,
1374    {
1375        type Item = T;
1376
1377        fn next(&mut self) -> Option<Self::Item> {
1378            match self {
1379                Self::Left(left) => left.next(),
1380                Self::Right(right) => right.next(),
1381            }
1382        }
1383    }
1384
1385    impl<L, R> ToTokens for Either<L, R>
1386    where
1387        L: ToTokens,
1388        R: ToTokens,
1389    {
1390        fn to_tokens(&self, tokens: &mut TokenStream) {
1391            match self {
1392                Self::Left(l) => l.to_tokens(tokens),
1393                Self::Right(r) => r.to_tokens(tokens),
1394            }
1395        }
1396    }
1397}
1398
1399#[cfg(any(
1400    feature = "add",
1401    feature = "add_assign",
1402    feature = "as_ref",
1403    feature = "debug",
1404    feature = "display",
1405    feature = "eq",
1406    feature = "from",
1407    feature = "from_str",
1408    feature = "into",
1409    feature = "mul",
1410    feature = "mul_assign",
1411    feature = "try_from",
1412    feature = "try_into",
1413))]
1414mod spanning {
1415    use std::ops::{Deref, DerefMut};
1416
1417    use proc_macro2::Span;
1418
1419    /// Wrapper for non-[`Spanned`] types to hold their [`Span`].
1420    ///
1421    /// [`Spanned`]: syn::spanned::Spanned
1422    #[derive(Clone, Copy, Debug)]
1423    pub(crate) struct Spanning<T: ?Sized> {
1424        /// [`Span`] of the `item`.
1425        pub(crate) span: Span,
1426
1427        /// Item the [`Span`] is held for.
1428        pub(crate) item: T,
1429    }
1430
1431    impl<T: ?Sized> Spanning<T> {
1432        /// Creates a new [`Spanning`] `item`, attaching the provided [`Span`] to it.
1433        pub(crate) const fn new(item: T, span: Span) -> Self
1434        where
1435            T: Sized,
1436        {
1437            Self { span, item }
1438        }
1439
1440        /// Destructures this [`Spanning`] wrapper returning the underlying `item`.
1441        pub fn into_inner(self) -> T
1442        where
1443            T: Sized,
1444        {
1445            self.item
1446        }
1447
1448        /// Returns the [`Span`] contained in this [`Spanning`] wrapper.
1449        pub(crate) const fn span(&self) -> Span {
1450            self.span
1451        }
1452
1453        /// Converts this `&`[`Spanning`]`<T>` into [`Spanning`]`<&T>` (moves the reference inside).
1454        pub(crate) const fn as_ref(&self) -> Spanning<&T> {
1455            Spanning {
1456                span: self.span,
1457                item: &self.item,
1458            }
1459        }
1460
1461        /// Maps the wrapped `item` with the provided `f`unction, preserving the current [`Span`].
1462        pub(crate) fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanning<U>
1463        where
1464            T: Sized,
1465        {
1466            Spanning {
1467                span: self.span,
1468                item: f(self.item),
1469            }
1470        }
1471    }
1472
1473    #[cfg(feature = "into")]
1474    impl<T> Spanning<Option<T>> {
1475        pub(crate) fn transpose(self) -> Option<Spanning<T>> {
1476            match self.item {
1477                Some(item) => Some(Spanning {
1478                    item,
1479                    span: self.span,
1480                }),
1481                None => None,
1482            }
1483        }
1484    }
1485
1486    impl<T: ?Sized> Deref for Spanning<T> {
1487        type Target = T;
1488
1489        fn deref(&self) -> &Self::Target {
1490            &self.item
1491        }
1492    }
1493
1494    impl<T: ?Sized> DerefMut for Spanning<T> {
1495        fn deref_mut(&mut self) -> &mut Self::Target {
1496            &mut self.item
1497        }
1498    }
1499}
1500
1501#[cfg(any(
1502    feature = "add",
1503    feature = "add_assign",
1504    feature = "as_ref",
1505    feature = "debug",
1506    feature = "display",
1507    feature = "eq",
1508    feature = "from",
1509    feature = "from_str",
1510    feature = "into",
1511    feature = "mul",
1512    feature = "mul_assign",
1513    feature = "try_from",
1514    feature = "try_into",
1515))]
1516pub(crate) mod attr {
1517    use std::any::Any;
1518
1519    use syn::{
1520        parse::{Parse, ParseStream},
1521        spanned::Spanned as _,
1522    };
1523
1524    use super::{Either, Spanning};
1525
1526    #[cfg(any(
1527        feature = "as_ref",
1528        feature = "from",
1529        feature = "into",
1530        feature = "try_from"
1531    ))]
1532    pub(crate) use self::empty::Empty;
1533    #[cfg(any(feature = "from_str", feature = "try_into"))]
1534    pub(crate) use self::error::Error;
1535    #[cfg(any(
1536        feature = "as_ref",
1537        feature = "from",
1538        feature = "mul",
1539        feature = "mul_assign",
1540    ))]
1541    pub(crate) use self::forward::Forward;
1542    #[cfg(any(feature = "display", feature = "from_str"))]
1543    pub(crate) use self::rename_all::RenameAll;
1544    #[cfg(any(
1545        feature = "add",
1546        feature = "add_assign",
1547        feature = "as_ref",
1548        feature = "debug",
1549        feature = "eq",
1550        feature = "from",
1551        feature = "into",
1552        feature = "mul",
1553        feature = "mul_assign",
1554    ))]
1555    pub(crate) use self::skip::Skip;
1556    #[cfg(any(feature = "as_ref", feature = "from", feature = "try_from"))]
1557    pub(crate) use self::types::Types;
1558    #[cfg(any(feature = "as_ref", feature = "from"))]
1559    pub(crate) use self::{conversion::Conversion, field_conversion::FieldConversion};
1560    #[cfg(feature = "try_from")]
1561    pub(crate) use self::{repr_conversion::ReprConversion, repr_int::ReprInt};
1562
1563    /// [`Parse`]ing with additional state or metadata.
1564    pub(crate) trait Parser {
1565        /// [`Parse`]s an item, using additional state or metadata.
1566        ///
1567        /// Default implementation just calls [`Parse::parse()`] directly.
1568        fn parse<T: Parse + Any>(&self, input: ParseStream<'_>) -> syn::Result<T> {
1569            T::parse(input)
1570        }
1571    }
1572
1573    impl Parser for () {}
1574
1575    /// Parsing of a typed attribute from multiple [`syn::Attribute`]s.
1576    pub(crate) trait ParseMultiple: Parse + Sized + 'static {
1577        /// Parses this attribute from the provided single [`syn::Attribute`] with the provided
1578        /// [`Parser`].
1579        ///
1580        /// Required, because with [`Parse`] we only able to parse inner attribute tokens, which
1581        /// doesn't work for attributes with empty arguments, like `#[attr]`.
1582        ///
1583        /// Override this method if the default [`syn::Attribute::parse_args_with()`] is not enough.
1584        fn parse_attr_with<P: Parser>(
1585            attr: &syn::Attribute,
1586            parser: &P,
1587        ) -> syn::Result<Self> {
1588            attr.parse_args_with(|ps: ParseStream<'_>| parser.parse(ps))
1589        }
1590
1591        /// Merges multiple values of this attribute into a single one.
1592        ///
1593        /// Default implementation only errors, disallowing multiple values of the same attribute.
1594        fn merge_attrs(
1595            _prev: Spanning<Self>,
1596            new: Spanning<Self>,
1597            name: &syn::Ident,
1598        ) -> syn::Result<Spanning<Self>> {
1599            Err(syn::Error::new(
1600                new.span,
1601                format!("only single `#[{name}(...)]` attribute is allowed here"),
1602            ))
1603        }
1604
1605        /// Merges multiple [`Option`]al values of this attribute into a single one.
1606        ///
1607        /// Default implementation uses [`ParseMultiple::merge_attrs()`] when both `prev` and `new`
1608        /// are [`Some`].
1609        fn merge_opt_attrs(
1610            prev: Option<Spanning<Self>>,
1611            new: Option<Spanning<Self>>,
1612            name: &syn::Ident,
1613        ) -> syn::Result<Option<Spanning<Self>>> {
1614            Ok(match (prev, new) {
1615                (Some(p), Some(n)) => Some(Self::merge_attrs(p, n, name)?),
1616                (Some(p), None) => Some(p),
1617                (None, Some(n)) => Some(n),
1618                (None, None) => None,
1619            })
1620        }
1621
1622        /// Parses this attribute from the provided multiple [`syn::Attribute`]s with the provided
1623        /// [`Parser`], merging them, and preserving their [`Span`].
1624        ///
1625        /// [`Span`]: proc_macro2::Span
1626        fn parse_attrs_with<P: Parser>(
1627            attrs: impl AsRef<[syn::Attribute]>,
1628            name: &syn::Ident,
1629            parser: &P,
1630        ) -> syn::Result<Option<Spanning<Self>>> {
1631            attrs
1632                .as_ref()
1633                .iter()
1634                .filter(|attr| attr.path().is_ident(name))
1635                .try_fold(None, |merged, attr| {
1636                    let parsed = Spanning::new(
1637                        Self::parse_attr_with(attr, parser)?,
1638                        attr.span(),
1639                    );
1640                    if let Some(prev) = merged {
1641                        Self::merge_attrs(prev, parsed, name).map(Some)
1642                    } else {
1643                        Ok(Some(parsed))
1644                    }
1645                })
1646        }
1647
1648        /// Parses this attribute from the provided multiple [`syn::Attribute`]s with the default
1649        /// [`Parse`], merging them, and preserving their [`Span`].
1650        ///
1651        /// [`Span`]: proc_macro2::Span
1652        fn parse_attrs(
1653            attrs: impl AsRef<[syn::Attribute]>,
1654            name: &syn::Ident,
1655        ) -> syn::Result<Option<Spanning<Self>>> {
1656            Self::parse_attrs_with(attrs, name, &())
1657        }
1658    }
1659
1660    impl<L: ParseMultiple, R: ParseMultiple> ParseMultiple for Either<L, R> {
1661        fn parse_attr_with<P: Parser>(
1662            attr: &syn::Attribute,
1663            parser: &P,
1664        ) -> syn::Result<Self> {
1665            L::parse_attr_with(attr, parser)
1666                .map(Self::Left)
1667                .or_else(|_| R::parse_attr_with(attr, parser).map(Self::Right))
1668        }
1669
1670        fn merge_attrs(
1671            prev: Spanning<Self>,
1672            new: Spanning<Self>,
1673            name: &syn::Ident,
1674        ) -> syn::Result<Spanning<Self>> {
1675            Ok(match (prev.item, new.item) {
1676                (Self::Left(p), Self::Left(n)) => {
1677                    L::merge_attrs(Spanning::new(p, prev.span), Spanning::new(n, new.span), name)?
1678                        .map(Self::Left)
1679                },
1680                (Self::Right(p), Self::Right(n)) => {
1681                    R::merge_attrs(Spanning::new(p, prev.span), Spanning::new(n, new.span), name)?
1682                        .map(Self::Right)
1683                },
1684                _ => return Err(syn::Error::new(
1685                    new.span,
1686                    format!("only single kind of `#[{name}(...)]` attribute is allowed here"),
1687                ))
1688            })
1689        }
1690    }
1691
1692    #[cfg(any(
1693        feature = "as_ref",
1694        feature = "from",
1695        feature = "into",
1696        feature = "try_from"
1697    ))]
1698    mod empty {
1699        use syn::{
1700            parse::{Parse, ParseStream},
1701            spanned::Spanned as _,
1702        };
1703
1704        use super::{ParseMultiple, Parser, Spanning};
1705
1706        /// Representation of an empty attribute, containing no arguments.
1707        ///
1708        /// ```rust,ignore
1709        /// #[<attribute>]
1710        /// ```
1711        #[derive(Clone, Copy, Debug)]
1712        pub(crate) struct Empty;
1713
1714        impl Parse for Empty {
1715            fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1716                if input.is_empty() {
1717                    Ok(Self)
1718                } else {
1719                    Err(syn::Error::new(
1720                        input.span(),
1721                        "no attribute arguments allowed here",
1722                    ))
1723                }
1724            }
1725        }
1726
1727        impl ParseMultiple for Empty {
1728            fn parse_attr_with<P: Parser>(
1729                attr: &syn::Attribute,
1730                _: &P,
1731            ) -> syn::Result<Self> {
1732                if matches!(attr.meta, syn::Meta::Path(_)) {
1733                    Ok(Self)
1734                } else {
1735                    Err(syn::Error::new(
1736                        attr.span(),
1737                        "no attribute arguments allowed here",
1738                    ))
1739                }
1740            }
1741
1742            fn merge_attrs(
1743                _prev: Spanning<Self>,
1744                new: Spanning<Self>,
1745                name: &syn::Ident,
1746            ) -> syn::Result<Spanning<Self>> {
1747                Err(syn::Error::new(
1748                    new.span,
1749                    format!("only single `#[{name}]` attribute is allowed here"),
1750                ))
1751            }
1752        }
1753    }
1754
1755    #[cfg(any(
1756        feature = "as_ref",
1757        feature = "from",
1758        feature = "mul",
1759        feature = "mul_assign",
1760    ))]
1761    mod forward {
1762        use syn::{
1763            parse::{Parse, ParseStream},
1764            spanned::Spanned as _,
1765        };
1766
1767        use super::ParseMultiple;
1768
1769        /// Representation of a `forward` attribute.
1770        ///
1771        /// ```rust,ignore
1772        /// #[<attribute>(forward)]
1773        /// ```
1774        #[derive(Clone, Copy, Debug)]
1775        pub(crate) struct Forward;
1776
1777        impl Parse for Forward {
1778            fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1779                match input.parse::<syn::Path>()? {
1780                    p if p.is_ident("forward") => Ok(Self),
1781                    p => Err(syn::Error::new(p.span(), "only `forward` allowed here")),
1782                }
1783            }
1784        }
1785
1786        impl ParseMultiple for Forward {}
1787    }
1788
1789    #[cfg(feature = "try_from")]
1790    mod repr_int {
1791        use proc_macro2::Span;
1792        use syn::parse::{Parse, ParseStream};
1793
1794        use super::{ParseMultiple, Parser, Spanning};
1795
1796        /// Representation of a [`#[repr(u/i*)]` Rust attribute][0].
1797        ///
1798        /// **NOTE**: Disregards any non-integer representation `#[repr]`s.
1799        ///
1800        /// ```rust,ignore
1801        /// #[repr(<type>)]
1802        /// ```
1803        ///
1804        /// [0]: https://doc.rust-lang.org/reference/type-layout.html#primitive-representations
1805        #[derive(Default)]
1806        pub(crate) struct ReprInt(Option<syn::Ident>);
1807
1808        impl ReprInt {
1809            /// Returns [`syn::Ident`] of the primitive integer type behind this [`ReprInt`]
1810            /// attribute.
1811            ///
1812            /// If there is no explicitly specified  primitive integer type, then returns a
1813            /// [default `isize` discriminant][0].
1814            ///
1815            /// [`syn::Ident`]: struct@syn::Ident
1816            /// [0]: https://doc.rust-lang.org/reference/items/enumerations.html#discriminants
1817            pub(crate) fn ty(&self) -> syn::Ident {
1818                self.0
1819                    .as_ref()
1820                    .cloned()
1821                    .unwrap_or_else(|| syn::Ident::new("isize", Span::call_site()))
1822            }
1823        }
1824
1825        impl Parse for ReprInt {
1826            fn parse(_: ParseStream<'_>) -> syn::Result<Self> {
1827                unreachable!("call `attr::ParseMultiple::parse_attr_with()` instead")
1828            }
1829        }
1830
1831        impl ParseMultiple for ReprInt {
1832            fn parse_attr_with<P: Parser>(
1833                attr: &syn::Attribute,
1834                _: &P,
1835            ) -> syn::Result<Self> {
1836                let mut repr = None;
1837                attr.parse_nested_meta(|meta| {
1838                    if let Some(ident) = meta.path.get_ident() {
1839                        if matches!(
1840                            ident.to_string().as_str(),
1841                            "u8" | "u16"
1842                                | "u32"
1843                                | "u64"
1844                                | "u128"
1845                                | "usize"
1846                                | "i8"
1847                                | "i16"
1848                                | "i32"
1849                                | "i64"
1850                                | "i128"
1851                                | "isize"
1852                        ) {
1853                            repr = Some(ident.clone());
1854                            return Ok(());
1855                        }
1856                    }
1857                    // Ignore all other attributes that could have a body, e.g. `align`.
1858                    _ = meta.input.parse::<proc_macro2::Group>();
1859                    Ok(())
1860                })?;
1861                Ok(Self(repr))
1862            }
1863
1864            fn merge_attrs(
1865                prev: Spanning<Self>,
1866                new: Spanning<Self>,
1867                name: &syn::Ident,
1868            ) -> syn::Result<Spanning<Self>> {
1869                match (&prev.item.0, &new.item.0) {
1870                    (Some(_), None) | (None, None) => Ok(prev),
1871                    (None, Some(_)) => Ok(new),
1872                    (Some(_), Some(_)) => Err(syn::Error::new(
1873                        new.span,
1874                        format!(
1875                            "only single `#[{name}(u/i*)]` attribute is expected here",
1876                        ),
1877                    )),
1878                }
1879            }
1880        }
1881    }
1882
1883    #[cfg(any(
1884        feature = "add",
1885        feature = "add_assign",
1886        feature = "as_ref",
1887        feature = "debug",
1888        feature = "display",
1889        feature = "eq",
1890        feature = "from",
1891        feature = "into",
1892        feature = "mul",
1893        feature = "mul_assign",
1894    ))]
1895    mod skip {
1896        use syn::{
1897            parse::{Parse, ParseStream},
1898            spanned::Spanned as _,
1899        };
1900
1901        use super::{ParseMultiple, Spanning};
1902
1903        /// Representation of a `skip`/`ignore` attribute.
1904        ///
1905        /// ```rust,ignore
1906        /// #[<attribute>(skip)]
1907        /// #[<attribute>(ignore)]
1908        /// ```
1909        #[derive(Clone, Copy, Debug)]
1910        pub(crate) struct Skip(&'static str);
1911
1912        impl Parse for Skip {
1913            fn parse(content: ParseStream<'_>) -> syn::Result<Self> {
1914                match content.parse::<syn::Path>()? {
1915                    p if p.is_ident("skip") => Ok(Self("skip")),
1916                    p if p.is_ident("ignore") => Ok(Self("ignore")),
1917                    p => Err(syn::Error::new(
1918                        p.span(),
1919                        "only `skip`/`ignore` allowed here",
1920                    )),
1921                }
1922            }
1923        }
1924
1925        impl Skip {
1926            /// Returns the concrete name of this attribute (`skip` or `ignore`).
1927            pub(crate) const fn name(&self) -> &'static str {
1928                self.0
1929            }
1930        }
1931
1932        impl ParseMultiple for Skip {
1933            fn merge_attrs(
1934                _: Spanning<Self>,
1935                new: Spanning<Self>,
1936                name: &syn::Ident,
1937            ) -> syn::Result<Spanning<Self>> {
1938                Err(syn::Error::new(
1939                    new.span,
1940                    format!(
1941                        "only single `#[{name}(skip)]`/`#[{name}(ignore)]` attribute is allowed \
1942                         here",
1943                    ),
1944                ))
1945            }
1946        }
1947    }
1948
1949    #[cfg(any(feature = "as_ref", feature = "from", feature = "try_from"))]
1950    mod types {
1951        use syn::{
1952            parse::{Parse, ParseStream},
1953            punctuated::Punctuated,
1954            Token,
1955        };
1956
1957        use super::{ParseMultiple, Spanning};
1958
1959        /// Representation of an attribute, containing a comma-separated list of types.
1960        ///
1961        /// ```rust,ignore
1962        /// #[<attribute>(<types>)]
1963        /// ```
1964        pub(crate) struct Types(pub(crate) Punctuated<syn::Type, Token![,]>);
1965
1966        impl Parse for Types {
1967            fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1968                input
1969                    .parse_terminated(syn::Type::parse, Token![,])
1970                    .map(Self)
1971            }
1972        }
1973
1974        impl ParseMultiple for Types {
1975            fn merge_attrs(
1976                mut prev: Spanning<Self>,
1977                new: Spanning<Self>,
1978                _: &syn::Ident,
1979            ) -> syn::Result<Spanning<Self>> {
1980                prev.item.0.extend(new.item.0);
1981                Ok(Spanning::new(
1982                    prev.item,
1983                    prev.span.join(new.span).unwrap_or(prev.span),
1984                ))
1985            }
1986        }
1987    }
1988
1989    #[cfg(any(feature = "as_ref", feature = "from"))]
1990    mod conversion {
1991        use syn::parse::{Parse, ParseStream};
1992
1993        use crate::utils::attr;
1994
1995        use super::{Either, ParseMultiple, Spanning};
1996
1997        /// Untyped analogue of a [`Conversion`], recreating its type structure via [`Either`].
1998        ///
1999        /// Used to piggyback [`Parse`] and [`ParseMultiple`] impls to [`Either`].
2000        type Untyped = Either<attr::Forward, attr::Types>;
2001
2002        /// Representation of an attribute, specifying which conversions should be generated:
2003        /// either forwarded via a blanket impl, or direct for concrete specified types.
2004        ///
2005        /// ```rust,ignore
2006        /// #[<attribute>(forward)]
2007        /// #[<attribute>(<types>)]
2008        /// ```
2009        pub(crate) enum Conversion {
2010            Forward(attr::Forward),
2011            Types(attr::Types),
2012        }
2013
2014        impl From<Untyped> for Conversion {
2015            fn from(v: Untyped) -> Self {
2016                match v {
2017                    Untyped::Left(f) => Self::Forward(f),
2018                    Untyped::Right(t) => Self::Types(t),
2019                }
2020            }
2021        }
2022        impl From<Conversion> for Untyped {
2023            fn from(v: Conversion) -> Self {
2024                match v {
2025                    Conversion::Forward(f) => Self::Left(f),
2026                    Conversion::Types(t) => Self::Right(t),
2027                }
2028            }
2029        }
2030
2031        impl Parse for Conversion {
2032            fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
2033                Untyped::parse(input).map(Self::from)
2034            }
2035        }
2036
2037        impl ParseMultiple for Conversion {
2038            fn parse_attr_with<P: attr::Parser>(
2039                attr: &syn::Attribute,
2040                parser: &P,
2041            ) -> syn::Result<Self> {
2042                Untyped::parse_attr_with(attr, parser).map(Self::from)
2043            }
2044
2045            fn merge_attrs(
2046                prev: Spanning<Self>,
2047                new: Spanning<Self>,
2048                name: &syn::Ident,
2049            ) -> syn::Result<Spanning<Self>> {
2050                Untyped::merge_attrs(prev.map(Into::into), new.map(Into::into), name)
2051                    .map(|v| v.map(Self::from))
2052            }
2053        }
2054    }
2055
2056    #[cfg(any(feature = "as_ref", feature = "from"))]
2057    mod field_conversion {
2058        use syn::parse::{Parse, ParseStream};
2059
2060        use crate::utils::attr;
2061
2062        use super::{Either, ParseMultiple, Spanning};
2063
2064        /// Untyped analogue of a [`FieldConversion`], recreating its type structure via [`Either`].
2065        ///
2066        /// Used to piggyback [`Parse`] and [`ParseMultiple`] impls to [`Either`].
2067        type Untyped =
2068            Either<attr::Empty, Either<attr::Skip, Either<attr::Forward, attr::Types>>>;
2069
2070        /// Representation of an attribute, specifying which conversions should be generated:
2071        /// either forwarded via a blanket impl, or direct for concrete specified types.
2072        ///
2073        /// ```rust,ignore
2074        /// #[<attribute>]
2075        /// #[<attribute>(skip)] #[<attribute>(ignore)]
2076        /// #[<attribute>(forward)]
2077        /// #[<attribute>(<types>)]
2078        /// ```
2079        pub(crate) enum FieldConversion {
2080            Empty(attr::Empty),
2081            Skip(attr::Skip),
2082            Forward(attr::Forward),
2083            Types(attr::Types),
2084        }
2085
2086        impl From<Untyped> for FieldConversion {
2087            fn from(v: Untyped) -> Self {
2088                match v {
2089                    Untyped::Left(e) => Self::Empty(e),
2090                    Untyped::Right(Either::Left(s)) => Self::Skip(s),
2091                    Untyped::Right(Either::Right(Either::Left(f))) => Self::Forward(f),
2092                    Untyped::Right(Either::Right(Either::Right(t))) => Self::Types(t),
2093                }
2094            }
2095        }
2096
2097        impl From<FieldConversion> for Untyped {
2098            fn from(v: FieldConversion) -> Self {
2099                match v {
2100                    FieldConversion::Empty(e) => Self::Left(e),
2101                    FieldConversion::Skip(s) => Self::Right(Either::Left(s)),
2102                    FieldConversion::Forward(f) => {
2103                        Self::Right(Either::Right(Either::Left(f)))
2104                    }
2105                    FieldConversion::Types(t) => {
2106                        Self::Right(Either::Right(Either::Right(t)))
2107                    }
2108                }
2109            }
2110        }
2111
2112        impl From<attr::Conversion> for FieldConversion {
2113            fn from(v: attr::Conversion) -> Self {
2114                match v {
2115                    attr::Conversion::Forward(f) => Self::Forward(f),
2116                    attr::Conversion::Types(t) => Self::Types(t),
2117                }
2118            }
2119        }
2120
2121        impl From<FieldConversion> for Option<attr::Conversion> {
2122            fn from(v: FieldConversion) -> Self {
2123                match v {
2124                    FieldConversion::Forward(f) => Some(attr::Conversion::Forward(f)),
2125                    FieldConversion::Types(t) => Some(attr::Conversion::Types(t)),
2126                    FieldConversion::Empty(_) | FieldConversion::Skip(_) => None,
2127                }
2128            }
2129        }
2130
2131        impl Parse for FieldConversion {
2132            fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
2133                Untyped::parse(input).map(Self::from)
2134            }
2135        }
2136
2137        impl ParseMultiple for FieldConversion {
2138            fn parse_attr_with<P: attr::Parser>(
2139                attr: &syn::Attribute,
2140                parser: &P,
2141            ) -> syn::Result<Self> {
2142                Untyped::parse_attr_with(attr, parser).map(Self::from)
2143            }
2144
2145            fn merge_attrs(
2146                prev: Spanning<Self>,
2147                new: Spanning<Self>,
2148                name: &syn::Ident,
2149            ) -> syn::Result<Spanning<Self>> {
2150                Untyped::merge_attrs(prev.map(Into::into), new.map(Into::into), name)
2151                    .map(|v| v.map(Self::from))
2152            }
2153        }
2154    }
2155
2156    #[cfg(any(feature = "from_str", feature = "try_into"))]
2157    pub(crate) mod error {
2158        use syn::parse::{Parse, ParseStream};
2159
2160        use super::{Either, ParseMultiple};
2161
2162        /// Representation of an attribute, specifying the error type and, optionally, a
2163        /// [`Conversion`] from a built-in error type.
2164        ///
2165        /// ```rust,ignore
2166        /// #[<attribute>(error(<ty>))]
2167        /// #[<attribute>(error(<ty>, <conv>))]
2168        /// ```
2169        pub(crate) struct Error {
2170            /// Type to convert the error into.
2171            pub(crate) ty: syn::TypePath,
2172
2173            /// Custom conversion.
2174            ///
2175            /// If [`None`], then [`Into`] conversion should be applied.
2176            pub(crate) conv: Option<Conversion>,
2177        }
2178
2179        impl Parse for Error {
2180            fn parse(input: ParseStream) -> syn::Result<Self> {
2181                let prefix = syn::Ident::parse(input)?;
2182                if prefix != "error" {
2183                    return Err(syn::Error::new(
2184                        prefix.span(),
2185                        "expected `error` argument here",
2186                    ));
2187                }
2188
2189                let inner;
2190                syn::parenthesized!(inner in input);
2191
2192                let ty = syn::TypePath::parse(&inner)?;
2193                if inner.is_empty() {
2194                    return Ok(Self { ty, conv: None });
2195                }
2196
2197                _ = syn::token::Comma::parse(&inner)?;
2198
2199                let conv = Conversion::parse(&inner)?;
2200                if inner.is_empty() {
2201                    Ok(Self {
2202                        ty,
2203                        conv: Some(conv),
2204                    })
2205                } else {
2206                    Err(syn::Error::new(
2207                        inner.span(),
2208                        "no more arguments allowed here",
2209                    ))
2210                }
2211            }
2212        }
2213
2214        impl ParseMultiple for Error {}
2215
2216        /// Possible conversions of an [`attr::Error`].
2217        ///
2218        /// [`attr::Error`]: Error
2219        pub(crate) type Conversion =
2220            Either<syn::ExprCall, Either<syn::Path, syn::ExprClosure>>;
2221    }
2222
2223    #[cfg(feature = "try_from")]
2224    mod repr_conversion {
2225        use syn::parse::{Parse, ParseStream};
2226
2227        use crate::utils::attr;
2228
2229        use super::{ParseMultiple, Spanning};
2230
2231        /// Representation of an attribute, specifying which `repr`-conversions should be generated:
2232        /// either direct into a discriminant, or for concrete specified types forwarding from a
2233        /// discriminant.
2234        ///
2235        /// ```rust,ignore
2236        /// #[<attribute>(repr)]
2237        /// #[<attribute>(repr(<types>))]
2238        /// ```
2239        pub(crate) enum ReprConversion {
2240            Discriminant(attr::Empty),
2241            Types(attr::Types),
2242        }
2243
2244        impl Parse for ReprConversion {
2245            fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
2246                let prefix = syn::Ident::parse(input)?;
2247                if prefix != "repr" {
2248                    return Err(syn::Error::new(
2249                        prefix.span(),
2250                        "expected `repr` argument here",
2251                    ));
2252                }
2253                if input.is_empty() {
2254                    Ok(Self::Discriminant(attr::Empty))
2255                } else {
2256                    let inner;
2257                    syn::parenthesized!(inner in input);
2258                    Ok(Self::Types(attr::Types::parse(&inner)?))
2259                }
2260            }
2261        }
2262
2263        impl ParseMultiple for ReprConversion {
2264            fn merge_attrs(
2265                prev: Spanning<Self>,
2266                new: Spanning<Self>,
2267                name: &syn::Ident,
2268            ) -> syn::Result<Spanning<Self>> {
2269                Ok(match (prev.item, new.item) {
2270                    (Self::Discriminant(_), Self::Discriminant(_)) => {
2271                        return Err(syn::Error::new(
2272                            new.span,
2273                            format!("only single `#[{name}(repr)]` attribute is allowed here"),
2274                        ))
2275                    },
2276                    (Self::Types(p), Self::Types(n)) => {
2277                        attr::Types::merge_attrs(
2278                            Spanning::new(p, prev.span),
2279                            Spanning::new(n, new.span),
2280                            name,
2281                        )?.map(Self::Types)
2282                    },
2283                    _ => return Err(syn::Error::new(
2284                        new.span,
2285                        format!(
2286                            "only single kind of `#[{name}(repr(...))]` attribute is allowed here",
2287                        ),
2288                    ))
2289                })
2290            }
2291        }
2292    }
2293
2294    #[cfg(any(feature = "display", feature = "from_str"))]
2295    mod rename_all {
2296        use syn::{
2297            parse::{Parse, ParseStream},
2298            spanned::Spanned as _,
2299            token,
2300        };
2301
2302        use super::ParseMultiple;
2303
2304        /// Representation of a `rename_all` macro attribute.
2305        ///
2306        /// ```rust,ignore
2307        /// #[<attribute>(rename_all = "...")]
2308        /// ```
2309        ///
2310        /// Possible cases:
2311        /// - `lowercase`
2312        /// - `UPPERCASE`
2313        /// - `PascalCase`
2314        /// - `camelCase`
2315        /// - `snake_case`
2316        /// - `SCREAMING_SNAKE_CASE`
2317        /// - `kebab-case`
2318        /// - `SCREAMING-KEBAB-CASE`
2319        #[derive(Clone, Copy, Debug)]
2320        pub(crate) enum RenameAll {
2321            Lower,
2322            Upper,
2323            Pascal,
2324            Camel,
2325            Snake,
2326            ScreamingSnake,
2327            Kebab,
2328            ScreamingKebab,
2329        }
2330
2331        impl RenameAll {
2332            /// Converts the provided `name` into the case of this [`RenameAll`].
2333            pub(crate) fn convert_case(&self, name: &str) -> String {
2334                use convert_case::Casing as _;
2335
2336                let case = match self {
2337                    Self::Lower => convert_case::Case::Flat,
2338                    Self::Upper => convert_case::Case::UpperFlat,
2339                    Self::Pascal => convert_case::Case::Pascal,
2340                    Self::Camel => convert_case::Case::Camel,
2341                    Self::Snake => convert_case::Case::Snake,
2342                    Self::ScreamingSnake => convert_case::Case::UpperSnake,
2343                    Self::Kebab => convert_case::Case::Kebab,
2344                    Self::ScreamingKebab => convert_case::Case::UpperKebab,
2345                };
2346                name.to_case(case)
2347            }
2348        }
2349
2350        impl Parse for RenameAll {
2351            fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
2352                let _ = input.parse::<syn::Path>().and_then(|p| {
2353                    if p.is_ident("rename_all") {
2354                        Ok(p)
2355                    } else {
2356                        Err(syn::Error::new(
2357                            p.span(),
2358                            "unknown attribute argument, expected `rename_all = \"...\"`",
2359                        ))
2360                    }
2361                })?;
2362
2363                input.parse::<token::Eq>()?;
2364
2365                let lit: syn::LitStr = input.parse()?;
2366                Ok(
2367                    match lit.value().replace(['-', '_'], "").to_lowercase().as_str() {
2368                        "lowercase" => Self::Lower,
2369                        "uppercase" => Self::Upper,
2370                        "pascalcase" => Self::Pascal,
2371                        "camelcase" => Self::Camel,
2372                        "snakecase" => Self::Snake,
2373                        "screamingsnakecase" => Self::ScreamingSnake,
2374                        "kebabcase" => Self::Kebab,
2375                        "screamingkebabcase" => Self::ScreamingKebab,
2376                        _ => {
2377                            return Err(syn::Error::new_spanned(
2378                                lit,
2379                                "unexpected casing expected one of: \
2380                         \"lowercase\", \"UPPERCASE\", \"PascalCase\", \"camelCase\", \
2381                         \"snake_case\", \"SCREAMING_SNAKE_CASE\", \"kebab-case\", or \
2382                         \"SCREAMING-KEBAB-CASE\"",
2383                            ))
2384                        }
2385                    },
2386                )
2387            }
2388        }
2389
2390        impl ParseMultiple for RenameAll {}
2391    }
2392}
2393
2394#[cfg(any(feature = "from", feature = "into"))]
2395mod fields_ext {
2396    use std::{cmp, iter};
2397
2398    use quote::ToTokens as _;
2399    use syn::{punctuated, spanned::Spanned as _};
2400
2401    use super::Either;
2402
2403    /// Abstraction over `.len()` method to use it on type parameters.
2404    pub(crate) trait Len {
2405        /// Returns number of fields.
2406        fn len(&self) -> usize;
2407    }
2408
2409    impl Len for syn::Fields {
2410        fn len(&self) -> usize {
2411            self.len()
2412        }
2413    }
2414
2415    impl<T> Len for [T] {
2416        fn len(&self) -> usize {
2417            self.len()
2418        }
2419    }
2420
2421    /// [`syn::Fields`] extension.
2422    pub(crate) trait FieldsExt: Len {
2423        /// Validates the provided [`syn::Type`] against these [`syn::Fields`].
2424        fn validate_type<'t>(
2425            &self,
2426            ty: &'t syn::Type,
2427        ) -> syn::Result<
2428            Either<punctuated::Iter<'t, syn::Type>, iter::Once<&'t syn::Type>>,
2429        > {
2430            match ty {
2431                syn::Type::Tuple(syn::TypeTuple { elems, .. }) if self.len() > 1 => {
2432                    match self.len().cmp(&elems.len()) {
2433                        cmp::Ordering::Greater => {
2434                            return Err(syn::Error::new(
2435                                ty.span(),
2436                                format!(
2437                                    "wrong tuple length: expected {}, found {}. \
2438                                     Consider adding {} more type{}: `({})`",
2439                                    self.len(),
2440                                    elems.len(),
2441                                    self.len() - elems.len(),
2442                                    if self.len() - elems.len() > 1 {
2443                                        "s"
2444                                    } else {
2445                                        ""
2446                                    },
2447                                    elems
2448                                        .iter()
2449                                        .map(|ty| ty.into_token_stream().to_string())
2450                                        .chain(
2451                                            (0..(self.len() - elems.len()))
2452                                                .map(|_| "_".to_string())
2453                                        )
2454                                        .collect::<Vec<_>>()
2455                                        .join(", "),
2456                                ),
2457                            ));
2458                        }
2459                        cmp::Ordering::Less => {
2460                            return Err(syn::Error::new(
2461                                ty.span(),
2462                                format!(
2463                                    "wrong tuple length: expected {}, found {}. \
2464                                     Consider removing last {} type{}: `({})`",
2465                                    self.len(),
2466                                    elems.len(),
2467                                    elems.len() - self.len(),
2468                                    if elems.len() - self.len() > 1 {
2469                                        "s"
2470                                    } else {
2471                                        ""
2472                                    },
2473                                    elems
2474                                        .iter()
2475                                        .take(self.len())
2476                                        .map(|ty| ty.into_token_stream().to_string())
2477                                        .collect::<Vec<_>>()
2478                                        .join(", "),
2479                                ),
2480                            ));
2481                        }
2482                        cmp::Ordering::Equal => {}
2483                    }
2484                }
2485                other if self.len() > 1 => {
2486                    return Err(syn::Error::new(
2487                        other.span(),
2488                        format!(
2489                            "expected tuple: `({}, {})`",
2490                            other.into_token_stream(),
2491                            (0..(self.len() - 1))
2492                                .map(|_| "_")
2493                                .collect::<Vec<_>>()
2494                                .join(", "),
2495                        ),
2496                    ));
2497                }
2498                _ => {}
2499            }
2500            Ok(match ty {
2501                syn::Type::Tuple(syn::TypeTuple { elems, .. }) => {
2502                    Either::Left(elems.iter())
2503                }
2504                other => Either::Right(iter::once(other)),
2505            })
2506        }
2507    }
2508
2509    impl<T: Len + ?Sized> FieldsExt for T {}
2510}
2511
2512#[cfg(any(
2513    feature = "add",
2514    feature = "add_assign",
2515    feature = "as_ref",
2516    feature = "eq",
2517    feature = "from_str",
2518    feature = "mul",
2519    feature = "mul_assign",
2520))]
2521mod generics_search {
2522    use syn::visit::Visit;
2523
2524    /// Search of whether some generics (type parameters, lifetime parameters or const parameters)
2525    /// are present in some [`syn::Type`].
2526    pub(crate) struct GenericsSearch<'s> {
2527        /// Type parameters to look for.
2528        pub(crate) types: Vec<&'s syn::Ident>,
2529
2530        /// Lifetime parameters to look for.
2531        pub(crate) lifetimes: Vec<&'s syn::Ident>,
2532
2533        /// Const parameters to look for.
2534        pub(crate) consts: Vec<&'s syn::Ident>,
2535    }
2536
2537    impl<'s> From<&'s syn::Generics> for GenericsSearch<'s> {
2538        fn from(value: &'s syn::Generics) -> Self {
2539            Self {
2540                types: value.type_params().map(|p| &p.ident).collect(),
2541                lifetimes: value.lifetimes().map(|p| &p.lifetime.ident).collect(),
2542                consts: value.const_params().map(|p| &p.ident).collect(),
2543            }
2544        }
2545    }
2546
2547    impl GenericsSearch<'_> {
2548        /// Checks the provided [`syn::Type`] to contain anything from this [`GenericsSearch`].
2549        pub(crate) fn any_in(&self, ty: &syn::Type) -> bool {
2550            let mut visitor = Visitor {
2551                search: self,
2552                found: false,
2553            };
2554            visitor.visit_type(ty);
2555            visitor.found
2556        }
2557    }
2558
2559    /// [`Visit`]or performing a [`GenericsSearch`].
2560    struct Visitor<'s> {
2561        /// [`GenericsSearch`] parameters.
2562        search: &'s GenericsSearch<'s>,
2563
2564        /// Indication whether anything was found for the [`GenericsSearch`] parameters.
2565        found: bool,
2566    }
2567
2568    impl<'ast> Visit<'ast> for Visitor<'_> {
2569        fn visit_expr_path(&mut self, ep: &'ast syn::ExprPath) {
2570            self.found |= ep
2571                .path
2572                .get_ident()
2573                .is_some_and(|ident| self.search.consts.contains(&ident));
2574
2575            if !self.found {
2576                syn::visit::visit_expr_path(self, ep);
2577            }
2578        }
2579
2580        fn visit_lifetime(&mut self, lf: &'ast syn::Lifetime) {
2581            self.found |= self.search.lifetimes.contains(&&lf.ident);
2582
2583            if !self.found {
2584                syn::visit::visit_lifetime(self, lf);
2585            }
2586        }
2587
2588        fn visit_type_path(&mut self, tp: &'ast syn::TypePath) {
2589            self.found |= tp.path.get_ident().is_some_and(|ident| {
2590                self.search.types.contains(&ident)
2591                    || self.search.consts.contains(&ident)
2592            });
2593
2594            if !self.found {
2595                // `TypeParam::AssocType` case.
2596                self.found |= tp.path.segments.first().is_some_and(|segment| {
2597                    matches!(segment.arguments, syn::PathArguments::None)
2598                        && self.search.types.contains(&&segment.ident)
2599                });
2600            }
2601
2602            if !self.found {
2603                syn::visit::visit_type_path(self, tp)
2604            }
2605        }
2606    }
2607
2608    #[cfg(test)]
2609    mod spec {
2610        use quote::ToTokens as _;
2611        use syn::parse_quote;
2612
2613        use super::GenericsSearch;
2614
2615        #[test]
2616        fn types() {
2617            let generics: syn::Generics = parse_quote! { <T> };
2618            let search = GenericsSearch::from(&generics);
2619
2620            for input in [
2621                parse_quote! { T },
2622                parse_quote! { &T },
2623                parse_quote! { &'a T },
2624                parse_quote! { &&'a T },
2625                parse_quote! { Type<'a, T> },
2626                parse_quote! { path::Type<T, 'a> },
2627                parse_quote! { path::<'a, T>::Type },
2628                parse_quote! { <Self as Trait<'a, T>>::Type },
2629                parse_quote! { <Self as Trait>::Type<T, 'a> },
2630                parse_quote! { T::Type },
2631                parse_quote! { <T as Trait>::Type },
2632                parse_quote! { [T] },
2633                parse_quote! { [T; 3] },
2634                parse_quote! { [T; _] },
2635                parse_quote! { (T) },
2636                parse_quote! { (T,) },
2637                parse_quote! { (T, u8) },
2638                parse_quote! { (u8, T) },
2639                parse_quote! { fn(T) },
2640                parse_quote! { fn(u8, T) },
2641                parse_quote! { fn(_) -> T },
2642                parse_quote! { fn(_) -> (u8, T) },
2643            ] {
2644                assert!(
2645                    search.any_in(&input),
2646                    "cannot find type parameter `T` in type `{}`",
2647                    input.into_token_stream(),
2648                );
2649            }
2650        }
2651
2652        #[test]
2653        fn lifetimes() {
2654            let generics: syn::Generics = parse_quote! { <'a> };
2655            let search = GenericsSearch::from(&generics);
2656
2657            for input in [
2658                parse_quote! { &'a T },
2659                parse_quote! { &&'a T },
2660                parse_quote! { Type<'a> },
2661                parse_quote! { path::Type<'a> },
2662                parse_quote! { path::<'a>::Type },
2663                parse_quote! { <Self as Trait<'a>>::Type },
2664                parse_quote! { <Self as Trait>::Type<'a> },
2665            ] {
2666                assert!(
2667                    search.any_in(&input),
2668                    "cannot find lifetime parameter `'a` in type `{}`",
2669                    input.into_token_stream(),
2670                );
2671            }
2672        }
2673
2674        #[test]
2675        fn consts() {
2676            let generics: syn::Generics = parse_quote! { <const N: usize> };
2677            let search = GenericsSearch::from(&generics);
2678
2679            for input in [
2680                parse_quote! { [_; N] },
2681                parse_quote! { Type<N> },
2682                #[cfg(feature = "testing-helpers")] // requires `syn/full`
2683                parse_quote! { Type<{ N }> },
2684                parse_quote! { path::Type<N> },
2685                #[cfg(feature = "testing-helpers")] // requires `syn/full`
2686                parse_quote! { path::Type<{ N }> },
2687                parse_quote! { path::<N>::Type },
2688                #[cfg(feature = "testing-helpers")] // requires `syn/full`
2689                parse_quote! { path::<{ N }>::Type },
2690                parse_quote! { <Self as Trait<N>>::Type },
2691                #[cfg(feature = "testing-helpers")] // requires `syn/full`
2692                parse_quote! { <Self as Trait<{ N }>>::Type },
2693                parse_quote! { <Self as Trait>::Type<N> },
2694                #[cfg(feature = "testing-helpers")] // requires `syn/full`
2695                parse_quote! { <Self as Trait>::Type<{ N }> },
2696            ] {
2697                assert!(
2698                    search.any_in(&input),
2699                    "cannot find const parameter `N` in type `{}`",
2700                    input.into_token_stream(),
2701                );
2702            }
2703        }
2704    }
2705}
2706
2707#[cfg(any(feature = "into", feature = "try_into"))]
2708pub(crate) mod replace_self {
2709    use syn::{parse_quote, visit_mut::VisitMut};
2710
2711    /// Extension of a [`syn::DeriveInput`] providing capabilities for `Self` type replacement.
2712    pub(crate) trait DeriveInputExt {
2713        /// Replaces `Self` type in fields and trait bounds of this [`syn::DeriveInput`].
2714        fn replace_self_type(&self) -> Self;
2715    }
2716
2717    impl DeriveInputExt for syn::DeriveInput {
2718        fn replace_self_type(&self) -> Self {
2719            let mut input = self.clone();
2720            Visitor::new(&input).visit_derive_input_mut(&mut input);
2721            input
2722        }
2723    }
2724
2725    /// [`VisitMut`] implementation performing the `Self` type replacement.
2726    ///
2727    /// Based on:
2728    /// <https://github.com/mbrobbel/narrow/blob/v0.11.1/narrow-derive/src/util/self_replace.rs>
2729    struct Visitor {
2730        /// [`syn::PathSegment`] representing a type to replace `Self` occurrences with.
2731        self_ty: syn::PathSegment,
2732    }
2733
2734    impl Visitor {
2735        /// Creates a new `Self` type replacement [`Visitor`] for the provided [`syn::DeriveInput`].
2736        fn new(input: &syn::DeriveInput) -> Self {
2737            let ident = &input.ident;
2738            let (_, ty_generics, _) = input.generics.split_for_impl();
2739            Self {
2740                self_ty: parse_quote! { #ident #ty_generics },
2741            }
2742        }
2743    }
2744
2745    impl VisitMut for Visitor {
2746        fn visit_derive_input_mut(&mut self, i: &mut syn::DeriveInput) {
2747            self.visit_generics_mut(&mut i.generics);
2748            self.visit_data_mut(&mut i.data);
2749        }
2750
2751        fn visit_field_mut(&mut self, i: &mut syn::Field) {
2752            self.visit_type_mut(&mut i.ty);
2753        }
2754
2755        fn visit_path_segment_mut(&mut self, i: &mut syn::PathSegment) {
2756            if i.ident == "Self" {
2757                *i = self.self_ty.clone();
2758            } else {
2759                self.visit_path_arguments_mut(&mut i.arguments);
2760            }
2761        }
2762
2763        fn visit_variant_mut(&mut self, i: &mut syn::Variant) {
2764            self.visit_fields_mut(&mut i.fields);
2765        }
2766    }
2767
2768    #[cfg(test)]
2769    mod spec {
2770        use syn::{parse_quote, DeriveInput};
2771
2772        use super::DeriveInputExt as _;
2773
2774        #[test]
2775        fn replaces_generics() {
2776            let input: DeriveInput = parse_quote! {
2777                struct Foo<T, U: Sub<Self>>
2778                where
2779                    U: Add<Self>,
2780                    Self: X,
2781                    <U as Add<Self>>::Output: X,
2782                    T: IntoIterator<Item = Self>,
2783                    [Self; 5]: SomeTrait,
2784                    <Self as OtherTrait>::Type: Copy;
2785            };
2786
2787            let actual = input.replace_self_type();
2788
2789            let expected: DeriveInput = parse_quote! {
2790                struct Foo<T, U: Sub<Foo<T, U>>>
2791                where
2792                    U: Add<Foo<T, U>>,
2793                    Foo<T, U>: X,
2794                    <U as Add<Foo<T, U>>>::Output: X,
2795                    T: IntoIterator<Item = Foo<T, U>>,
2796                    [Foo<T, U>; 5]: SomeTrait,
2797                    <Foo<T, U> as OtherTrait>::Type: Copy;
2798            };
2799
2800            assert_eq!(actual, expected);
2801        }
2802
2803        #[test]
2804        fn replaces_struct_named_fields() {
2805            let input: DeriveInput = parse_quote! {
2806                struct Foo {
2807                    a: AddType<Self>,
2808                    b: <Self as OtherTrait>::Type,
2809                }
2810            };
2811
2812            let actual = input.replace_self_type();
2813
2814            let expected: DeriveInput = parse_quote! {
2815                struct Foo {
2816                    a: AddType<Foo>,
2817                    b: <Foo as OtherTrait>::Type,
2818                }
2819            };
2820
2821            assert_eq!(actual, expected);
2822        }
2823
2824        #[test]
2825        fn replaces_struct_unnamed_fields() {
2826            let input: DeriveInput = parse_quote! {
2827                struct Bar([Self; 5], <Foo as Add<Self>>::Output);
2828            };
2829
2830            let actual = input.replace_self_type();
2831
2832            let expected: DeriveInput = parse_quote! {
2833                struct Bar([Bar; 5], <Foo as Add<Bar>>::Output);
2834            };
2835
2836            assert_eq!(actual, expected);
2837        }
2838
2839        #[test]
2840        fn replaces_enum_fields() {
2841            let input: DeriveInput = parse_quote! {
2842                enum E {
2843                    Foo {
2844                        a: AddType<Self>,
2845                        b: <Self as OtherTrait>::Type,
2846                    },
2847                    Bar([Self; 5], <Foo as Add<Self>>::Output),
2848                }
2849            };
2850
2851            let actual = input.replace_self_type();
2852
2853            let expected: DeriveInput = parse_quote! {
2854                enum E {
2855                    Foo {
2856                        a: AddType<E>,
2857                        b: <E as OtherTrait>::Type,
2858                    },
2859                    Bar([E; 5], <Foo as Add<E>>::Output),
2860                }
2861            };
2862
2863            assert_eq!(actual, expected);
2864        }
2865    }
2866}
2867
2868#[cfg(any(
2869    feature = "add",
2870    feature = "add_assign",
2871    feature = "eq",
2872    feature = "mul",
2873    feature = "mul_assign",
2874))]
2875pub(crate) mod structural_inclusion {
2876    //! Helper extensions of [`syn`] types for checking structural inclusion.
2877
2878    /// Extension of a [`syn::Type`] providing helper methods checking for structural inclusion of
2879    /// other types.
2880    pub(crate) trait TypeExt {
2881        /// Checks whether the provided [`syn::Type`] is contained within this [`syn::Type`]
2882        /// structurally (part of the actual structure).
2883        ///
2884        /// # False positives
2885        ///
2886        /// This check naturally gives a false positive when a type parameter is not used directly
2887        /// in a field, but its associative type does (e.g. `struct Foo<T: Some>(T::Assoc);`). This
2888        /// is because the structure of the type cannot be scanned by its name only.
2889        fn contains_type_structurally(&self, needle: &syn::Type) -> bool;
2890    }
2891
2892    impl TypeExt for syn::Type {
2893        fn contains_type_structurally(&self, needle: &Self) -> bool {
2894            if self == needle {
2895                return true;
2896            }
2897            match self {
2898                syn::Type::Array(syn::TypeArray { elem, .. })
2899                | syn::Type::Group(syn::TypeGroup { elem, .. })
2900                | syn::Type::Paren(syn::TypeParen { elem, .. })
2901                | syn::Type::Ptr(syn::TypePtr { elem, .. })
2902                | syn::Type::Reference(syn::TypeReference { elem, .. })
2903                | syn::Type::Slice(syn::TypeSlice { elem, .. }) => {
2904                    elem.contains_type_structurally(needle)
2905                }
2906                syn::Type::Tuple(syn::TypeTuple { elems, .. }) => {
2907                    elems.iter().any(|elem| elem.contains_type_structurally(needle))
2908                }
2909                syn::Type::Path(syn::TypePath { path, .. }) => path
2910                    .segments
2911                    .iter()
2912                    .filter_map(|seg| {
2913                        if let syn::PathArguments::AngleBracketed(args) = &seg.arguments {
2914                            Some(&args.args)
2915                        } else {
2916                            None
2917                        }
2918                    })
2919                    .flatten()
2920                    .any(|generic_arg| {
2921                        matches!(
2922                            generic_arg,
2923                            syn::GenericArgument::Type(ty) if ty.contains_type_structurally(needle),
2924                        )
2925                    }),
2926                syn::Type::BareFn(_)
2927                | syn::Type::ImplTrait(_)
2928                | syn::Type::Infer(_)
2929                | syn::Type::Macro(_)
2930                | syn::Type::Never(_)
2931                | syn::Type::TraitObject(_)
2932                | syn::Type::Verbatim(_) => false,
2933                _ => unimplemented!(
2934                    "syntax is not supported by `derive_more`, please report a bug",
2935                ),
2936            }
2937        }
2938    }
2939
2940    #[cfg(test)]
2941    mod type_ext_spec {
2942        use quote::ToTokens as _;
2943        use syn::parse_quote;
2944
2945        use super::TypeExt as _;
2946
2947        #[test]
2948        fn contains() {
2949            for (input, container) in [
2950                (parse_quote! { Self }, parse_quote! { Self }),
2951                (parse_quote! { Self }, parse_quote! { (Self) }),
2952                (parse_quote! { Self }, parse_quote! { (Self,) }),
2953                (parse_quote! { Self }, parse_quote! { (Self, Foo) }),
2954                (
2955                    parse_quote! { Self },
2956                    parse_quote! { (Foo, Bar, Baz, Self) },
2957                ),
2958                (parse_quote! { Self }, parse_quote! { [Self] }),
2959                (parse_quote! { Self }, parse_quote! { [Self; N] }),
2960                (parse_quote! { Self }, parse_quote! { *const Self }),
2961                (parse_quote! { Self }, parse_quote! { *mut Self }),
2962                (parse_quote! { Self }, parse_quote! { &'a Self }),
2963                (parse_quote! { Self }, parse_quote! { &'a mut Self }),
2964                (parse_quote! { Self }, parse_quote! { Box<Self> }),
2965                (parse_quote! { Self }, parse_quote! { PhantomData<Self> }),
2966                (parse_quote! { Self }, parse_quote! { Arc<Mutex<Self>> }),
2967                (
2968                    parse_quote! { Self },
2969                    parse_quote! { [*const (&'a [Arc<Mutex<Self>>],); 0] },
2970                ),
2971            ] {
2972                let container: syn::Type = container; // for type inference only
2973                assert!(
2974                    container.contains_type_structurally(&input),
2975                    "cannot find type `{}` in type `{}`",
2976                    input.into_token_stream(),
2977                    container.into_token_stream(),
2978                );
2979            }
2980        }
2981
2982        #[test]
2983        fn not_contains() {
2984            for (input, container) in [
2985                (parse_quote! { Self }, parse_quote! { Foo }),
2986                (parse_quote! { Self }, parse_quote! { (Foo) }),
2987                (parse_quote! { Self }, parse_quote! { (Foo,) }),
2988                (parse_quote! { Self }, parse_quote! { (Foo, Bar, Baz) }),
2989                (parse_quote! { Self }, parse_quote! { [Foo] }),
2990                (parse_quote! { Self }, parse_quote! { [Foo; N] }),
2991                (parse_quote! { Self }, parse_quote! { *const Foo }),
2992                (parse_quote! { Self }, parse_quote! { *mut Foo }),
2993                (parse_quote! { Self }, parse_quote! { &'a Foo }),
2994                (parse_quote! { Self }, parse_quote! { &'a mut Foo }),
2995                (parse_quote! { Self }, parse_quote! { Box<Foo> }),
2996                (parse_quote! { Self }, parse_quote! { PhantomData<Foo> }),
2997                (parse_quote! { Self }, parse_quote! { Arc<Mutex<Foo>> }),
2998                (
2999                    parse_quote! { Self },
3000                    parse_quote! { [*const (&'a [Arc<Mutex<Foo>>],); 0] },
3001                ),
3002                (parse_quote! { Self }, parse_quote! { fn(Self) -> Foo }),
3003                (parse_quote! { Self }, parse_quote! { fn(Foo) -> Self }),
3004                (parse_quote! { Self }, parse_quote! { impl Foo<Self> }),
3005                (
3006                    parse_quote! { Self },
3007                    parse_quote! { impl Foo<Type = Self> },
3008                ),
3009                (parse_quote! { Self }, parse_quote! { dyn Foo<Self> }),
3010                (
3011                    parse_quote! { Self },
3012                    parse_quote! { dyn Sync + Foo<Type = Self> },
3013                ),
3014            ] {
3015                let container: syn::Type = container; // for type inference only
3016                assert!(
3017                    !container.contains_type_structurally(&input),
3018                    "found type `{}` in type `{}`",
3019                    input.into_token_stream(),
3020                    container.into_token_stream(),
3021                );
3022            }
3023        }
3024    }
3025}
3026
3027#[cfg(any(
3028    feature = "add",
3029    feature = "add_assign",
3030    feature = "eq",
3031    feature = "mul",
3032    feature = "mul_assign",
3033))]
3034pub(crate) mod pattern_matching {
3035    //! Helper extensions of [`syn`] types for pattern matching code generation.
3036
3037    use proc_macro2::TokenStream;
3038    use quote::{format_ident, quote};
3039
3040    #[cfg(any(feature = "add_assign", feature = "eq", feature = "mul_assign"))]
3041    use crate::utils::HashSet;
3042
3043    /// Extension of [`syn::Fields`] for pattern matching code generation.
3044    pub(crate) trait FieldsExt {
3045        #[cfg(any(feature = "add_assign", feature = "eq", feature = "mul_assign"))]
3046        /// Generates a pattern for matching these [`syn::Fields`] non-exhaustively (considering the
3047        /// provided `skipped_indices`) in an arm of a `match` expression.
3048        ///
3049        /// All the [`syn::Fields`] will be assigned as `{prefix}{num}` bindings for use.
3050        fn non_exhaustive_arm_pattern(
3051            &self,
3052            prefix: &str,
3053            skipped_indices: &HashSet<usize>,
3054        ) -> TokenStream;
3055
3056        #[cfg(any(feature = "add", feature = "mul"))]
3057        /// Generates a pattern for matching these [`syn::Fields`] exhaustively in an arm of a
3058        /// `match` expression.
3059        ///
3060        /// All the [`syn::Fields`] will be assigned as `{prefix}{num}` bindings for use.
3061        fn exhaustive_arm_pattern(&self, prefix: &str) -> TokenStream;
3062    }
3063
3064    impl FieldsExt for syn::Fields {
3065        #[cfg(any(feature = "add_assign", feature = "eq", feature = "mul_assign"))]
3066        fn non_exhaustive_arm_pattern(
3067            &self,
3068            prefix: &str,
3069            skipped_indices: &HashSet<usize>,
3070        ) -> TokenStream {
3071            match self {
3072                Self::Named(fields) => {
3073                    let fields = fields
3074                        .named
3075                        .iter()
3076                        .enumerate()
3077                        .filter(|(num, _)| !skipped_indices.contains(num))
3078                        .map(|(num, field)| {
3079                            let name = &field.ident;
3080                            let binding = format_ident!("{prefix}{num}");
3081                            quote! { #name: #binding }
3082                        });
3083                    let wildcard =
3084                        (!skipped_indices.is_empty()).then(syn::token::DotDot::default);
3085                    quote! {{ #( #fields , )* #wildcard }}
3086                }
3087                Self::Unnamed(fields) => {
3088                    let fields = (0..fields.unnamed.len()).map(|num| {
3089                        if skipped_indices.contains(&num) {
3090                            quote! { _ }
3091                        } else {
3092                            let binding = format_ident!("{prefix}{num}");
3093                            quote! { #binding }
3094                        }
3095                    });
3096                    quote! {( #( #fields , )* )}
3097                }
3098                Self::Unit => quote! {},
3099            }
3100        }
3101
3102        #[cfg(any(feature = "add", feature = "mul"))]
3103        fn exhaustive_arm_pattern(&self, prefix: &str) -> TokenStream {
3104            match self {
3105                Self::Named(fields) => {
3106                    let fields = fields.named.iter().enumerate().map(|(num, field)| {
3107                        let name = &field.ident;
3108                        let binding = format_ident!("{prefix}{num}");
3109                        quote! { #name: #binding }
3110                    });
3111                    quote! {{ #( #fields , )* }}
3112                }
3113                Self::Unnamed(fields) => {
3114                    let fields = (0..fields.unnamed.len())
3115                        .map(|num| format_ident!("{prefix}{num}"));
3116                    quote! {( #( #fields , )* )}
3117                }
3118                Self::Unit => quote! {},
3119            }
3120        }
3121    }
3122}