Skip to main content

mutatis_derive/
lib.rs

1extern crate proc_macro;
2
3use proc_macro2::{Span, TokenStream};
4use quote::quote;
5use syn::{spanned::Spanned, *};
6
7mod container_attributes;
8mod field_attributes;
9use container_attributes::ContainerAttributes;
10use field_attributes::FieldBehavior;
11
12static MUTATIS_ATTRIBUTE_NAME: &str = "mutatis";
13
14#[proc_macro_derive(Mutate, attributes(mutatis))]
15pub fn derive_mutator(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
16    let input = syn::parse_macro_input!(tokens as DeriveInput);
17    expand_derive_mutator(input)
18        .unwrap_or_else(syn::Error::into_compile_error)
19        .into()
20}
21
22fn expand_derive_mutator(input: DeriveInput) -> Result<TokenStream> {
23    let container_attrs = ContainerAttributes::from_derive_input(&input)?;
24    let mutator_ty = MutatorType::new(&input, &container_attrs)?;
25
26    let mutator_type_def = gen_mutator_type_def(&input, &mutator_ty, &container_attrs)?;
27    let mutator_type_default_impl = gen_mutator_type_default_impl(&mutator_ty)?;
28    let mutator_ctor = gen_mutator_ctor(&mutator_ty)?;
29    let mutator_impl = gen_mutator_impl(&input, &mutator_ty)?;
30    let default_mutator_impl = gen_default_mutator_impl(&input, &mutator_ty, &container_attrs)?;
31    let generate_impl = gen_generate_impl(&input, &mutator_ty, &container_attrs)?;
32
33    Ok(quote! {
34        #mutator_type_def
35        #mutator_type_default_impl
36        #mutator_ctor
37        #mutator_impl
38        #default_mutator_impl
39        #generate_impl
40    })
41}
42
43struct MutatorType {
44    ty_name: Ident,
45
46    mutator_name: Ident,
47
48    mutator_fields: Vec<MutatorField>,
49
50    /// A vec of quoted generic parameters, without any bounds but with `const`
51    /// defs, e.g. `'a`, `const N: usize`, or `T`.
52    ty_impl_generics: Vec<TokenStream>,
53
54    /// A vec of quoted generic parameters, without any bounds and without any
55    /// `const` defs, e.t. `'a`, `N`, or `T.
56    ty_name_generics: Vec<TokenStream>,
57
58    /// A vec of quoted bounds for the generics above, e.g. `A: Iterator<Item =
59    /// B>,`.
60    ty_generics_bounds: Vec<TokenStream>,
61}
62
63impl MutatorType {
64    fn new(input: &DeriveInput, container_attrs: &ContainerAttributes) -> Result<Self> {
65        let ty_name = input.ident.clone();
66
67        let mutator_name = container_attrs
68            .mutator_name
69            .clone()
70            .unwrap_or_else(|| Ident::new(&format!("{}Mutator", input.ident), input.ident.span()));
71
72        let mutator_fields = get_mutator_fields(&input)?;
73
74        let mut ty_impl_generics = vec![];
75        let mut ty_name_generics = vec![];
76        let mut ty_generics_bounds = vec![];
77
78        for gen in &input.generics.params {
79            match gen {
80                GenericParam::Lifetime(l) => {
81                    if !l.bounds.is_empty() {
82                        ty_generics_bounds.push(quote! { #l });
83                    }
84
85                    let l = &l.lifetime;
86                    ty_impl_generics.push(quote! { #l });
87                    ty_name_generics.push(quote! { #l });
88                }
89                GenericParam::Const(c) => {
90                    ty_impl_generics.push(quote! { #c });
91                    let c = &c.ident;
92                    ty_name_generics.push(quote! { #c });
93                }
94                GenericParam::Type(t) => {
95                    if !t.bounds.is_empty() {
96                        ty_generics_bounds.push(quote! { #t });
97                    }
98                    let t = &t.ident;
99                    ty_impl_generics.push(quote! { #t });
100                    ty_name_generics.push(quote! { #t });
101                }
102            }
103        }
104
105        if let Some(wc) = &input.generics.where_clause {
106            for bound in wc.predicates.iter() {
107                ty_generics_bounds.push(quote! { #bound });
108            }
109        }
110
111        Ok(Self {
112            ty_name,
113            mutator_name,
114            mutator_fields,
115            ty_impl_generics,
116            ty_name_generics,
117            ty_generics_bounds,
118        })
119    }
120
121    fn mutator_impl_generics_iter(&self) -> impl Iterator<Item = TokenStream> + '_ {
122        self.ty_impl_generics.iter().cloned().chain(
123            self.mutator_fields
124                .iter()
125                .filter_map(|f| f.generic.as_ref().map(|g| quote! { #g })),
126        )
127    }
128
129    /// All the `impl` generic parameters for this mutator, including those
130    /// inherited from the type that it is a mutator for.
131    fn mutator_impl_generics(&self) -> TokenStream {
132        let impl_generics = self
133            .ty_impl_generics
134            .iter()
135            .cloned()
136            .chain(
137                self.mutator_fields
138                    .iter()
139                    .filter_map(|f| f.generic.as_ref().map(|g| quote! { #g })),
140            )
141            .collect::<Vec<_>>();
142        if impl_generics.is_empty() {
143            quote! {}
144        } else {
145            quote! { < #( #impl_generics ),* > }
146        }
147    }
148
149    /// All the named (i.e. just the "N" and excluding "const", ":", and "usize"
150    /// in `const N: usize` generics) generic parameters for this mutator,
151    /// including those inherited from the type that it is a mutator for.
152    fn mutator_name_generics_iter(&self) -> impl Iterator<Item = TokenStream> + '_ {
153        self.ty_name_generics.iter().cloned().chain(
154            self.mutator_fields
155                .iter()
156                .filter_map(|f| f.generic.as_ref().map(|g| quote! { #g })),
157        )
158    }
159
160    fn mutator_impl_generics_with_defaults_iter(&self) -> impl Iterator<Item = TokenStream> + '_ {
161        self.ty_impl_generics
162            .iter()
163            .cloned()
164            .chain(self.mutator_fields.iter().filter_map(move |f| {
165                f.generic.as_ref().map(|g| {
166                    let for_ty = &f.for_ty;
167                    quote! { #g = <#for_ty as mutatis::DefaultMutate>::DefaultMutate }
168                })
169            }))
170    }
171
172    fn ty_name_with_generics(&self) -> TokenStream {
173        let ty_name = &self.ty_name;
174        if self.ty_name_generics.is_empty() {
175            quote! { #ty_name }
176        } else {
177            let ty_generics = self.ty_name_generics.iter();
178            quote! { #ty_name < #( #ty_generics ),* > }
179        }
180    }
181
182    fn mutator_name_with_generics(&self, kind: MutatorNameGenericsKind) -> TokenStream {
183        let mutator_name = &self.mutator_name;
184
185        let generics = match kind {
186            MutatorNameGenericsKind::Generics => {
187                self.mutator_name_generics_iter().collect::<Vec<_>>()
188            }
189            MutatorNameGenericsKind::Impl {
190                impl_default: false,
191            } => self.mutator_impl_generics_iter().collect::<Vec<_>>(),
192            MutatorNameGenericsKind::Impl { impl_default: true } => self
193                .mutator_impl_generics_with_defaults_iter()
194                .collect::<Vec<_>>(),
195            MutatorNameGenericsKind::JustTyGenerics => self.ty_name_generics.clone(),
196        };
197
198        if generics.is_empty() {
199            quote! { #mutator_name }
200        } else {
201            quote! { #mutator_name < #( #generics ),* > }
202        }
203    }
204
205    fn where_clause(&self, kind: WhereClauseKind) -> TokenStream {
206        let mut bounds = self.ty_generics_bounds.clone();
207
208        match kind {
209            WhereClauseKind::NoMutateBounds => {}
210            WhereClauseKind::MutateBounds => {
211                for f in &self.mutator_fields {
212                    let for_ty = &f.for_ty;
213                    if let Some(g) = f.generic.as_ref() {
214                        bounds.push(quote! { #g: mutatis::Mutate<#for_ty> });
215                    } else {
216                        debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
217                        bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
218                    }
219                }
220            }
221            WhereClauseKind::MutateAndGenerateBounds => {
222                for f in &self.mutator_fields {
223                    let for_ty = &f.for_ty;
224                    if let Some(g) = f.generic.as_ref() {
225                        bounds.push(
226                            quote! { #g: mutatis::Mutate<#for_ty> + mutatis::Generate<#for_ty> },
227                        );
228                    } else {
229                        debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
230                        bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
231                        bounds.push(quote! { <#for_ty as mutatis::DefaultMutate>::DefaultMutate: mutatis::Generate<#for_ty> });
232                    }
233                }
234            }
235            WhereClauseKind::DefaultBounds => {
236                for f in &self.mutator_fields {
237                    if let Some(g) = f.generic.as_ref() {
238                        bounds.push(quote! { #g: Default });
239                    } else {
240                        let for_ty = &f.for_ty;
241                        debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
242                        bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
243                    }
244                }
245            }
246            WhereClauseKind::DefaultMutateBounds => {
247                for f in &self.mutator_fields {
248                    let for_ty = &f.for_ty;
249                    bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
250                }
251            }
252            // Like `DefaultMutateBounds`, but additionally requires that each
253            // field's default mutator implements `Generate`. A multi-variant
254            // enum's `Mutate` impl performs variant switching via `generate`, so
255            // its `DefaultMutate` impl can only hold when the default mutators
256            // are themselves `Generate`. For concrete field types this is proven
257            // directly, but for generic parameters it must be stated explicitly.
258            WhereClauseKind::DefaultMutateAndGenerateBounds => {
259                for f in &self.mutator_fields {
260                    let for_ty = &f.for_ty;
261                    bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
262                    bounds.push(quote! {
263                        <#for_ty as mutatis::DefaultMutate>::DefaultMutate: mutatis::Generate<#for_ty>
264                    });
265                }
266            }
267        }
268
269        if bounds.is_empty() {
270            quote! {}
271        } else {
272            quote! { where #( #bounds ),* }
273        }
274    }
275
276    fn phantom_fields_defs<'a>(
277        &self,
278        input: &'a DeriveInput,
279    ) -> impl Iterator<Item = TokenStream> + 'a {
280        let make_phantom_field = |i, ty| {
281            let ident = Ident::new(&format!("_phantom{i}"), Span::call_site());
282            quote! { #ident : core::marker::PhantomData<#ty> , }
283        };
284
285        input
286            .generics
287            .params
288            .iter()
289            .enumerate()
290            .map(move |(i, g)| match g {
291                GenericParam::Lifetime(l) => {
292                    let l = &l.lifetime;
293                    make_phantom_field(i, quote! { & #l () })
294                }
295                GenericParam::Const(c) => {
296                    let c = &c.ident;
297                    make_phantom_field(i, quote! { [(); #c] })
298                }
299                GenericParam::Type(t) => {
300                    let t = &t.ident;
301                    make_phantom_field(i, quote! { #t })
302                }
303            })
304    }
305
306    fn phantom_fields_literals(&self) -> impl Iterator<Item = TokenStream> + '_ {
307        (0..self.ty_name_generics.len()).map(|i| {
308            let ident = Ident::new(&format!("_phantom{i}"), Span::call_site());
309            quote! { #ident : core::marker::PhantomData, }
310        })
311    }
312}
313
314#[derive(Clone, Copy)]
315enum WhereClauseKind {
316    NoMutateBounds,
317    MutateBounds,
318    MutateAndGenerateBounds,
319    DefaultBounds,
320    DefaultMutateBounds,
321    DefaultMutateAndGenerateBounds,
322}
323
324#[derive(Clone, Copy)]
325enum MutatorNameGenericsKind {
326    Generics,
327    Impl { impl_default: bool },
328    JustTyGenerics,
329}
330
331struct MutatorField {
332    /// The identifier for this field inside the mutator struct.
333    ident: Ident,
334    /// The generic type parameter for this field, if any.
335    generic: Option<Ident>,
336    /// The behavior for this field.
337    behavior: FieldBehavior,
338    /// The type that this field is a mutator for.
339    for_ty: Type,
340}
341
342fn get_mutator_fields(input: &DeriveInput) -> Result<Vec<MutatorField>> {
343    let mut i = 0;
344    let mut generic = |b: &FieldBehavior| -> Option<Ident> {
345        if b.needs_generic() {
346            let g = Ident::new(&format!("MutatorT{}", i), Span::call_site());
347            i += 1;
348            Some(g)
349        } else {
350            None
351        }
352    };
353
354    match &input.data {
355        Data::Struct(data) => match &data.fields {
356            Fields::Named(fields) => fields
357                .named
358                .iter()
359                .filter_map(|f| {
360                    FieldBehavior::for_field(f)
361                        .map(|b| {
362                            b.map(|b| MutatorField {
363                                ident: f.ident.clone().unwrap(),
364                                generic: generic(&b),
365                                behavior: b,
366                                for_ty: f.ty.clone(),
367                            })
368                        })
369                        .transpose()
370                })
371                .collect(),
372            Fields::Unnamed(fields) => fields
373                .unnamed
374                .iter()
375                .enumerate()
376                .filter_map(|(i, f)| {
377                    FieldBehavior::for_field(f)
378                        .map(|b| {
379                            b.map(|b| MutatorField {
380                                ident: Ident::new(&format!("field{}", i), f.span()),
381                                generic: generic(&b),
382                                behavior: b,
383                                for_ty: f.ty.clone(),
384                            })
385                        })
386                        .transpose()
387                })
388                .collect(),
389            Fields::Unit => Ok(vec![]),
390        },
391        Data::Enum(data) => Ok(data
392            .variants
393            .iter()
394            .map(|v| {
395                let prefix = v.ident.to_string().to_lowercase();
396                match v.fields {
397                    Fields::Named(ref fields) => fields
398                        .named
399                        .iter()
400                        .filter_map(|f| {
401                            FieldBehavior::for_field(f)
402                                .map(|b| {
403                                    b.map(|b| MutatorField {
404                                        ident: Ident::new(
405                                            &format!("{prefix}_{}", f.ident.clone().unwrap()),
406                                            f.span(),
407                                        ),
408                                        generic: generic(&b),
409                                        behavior: b,
410                                        for_ty: f.ty.clone(),
411                                    })
412                                })
413                                .transpose()
414                        })
415                        .collect::<Result<Vec<_>>>(),
416                    Fields::Unnamed(ref fields) => fields
417                        .unnamed
418                        .iter()
419                        .enumerate()
420                        .filter_map(|(i, f)| {
421                            FieldBehavior::for_field(f)
422                                .map(|b| {
423                                    b.map(|b| MutatorField {
424                                        ident: Ident::new(&format!("{prefix}{i}"), f.span()),
425                                        generic: generic(&b),
426                                        behavior: b,
427                                        for_ty: f.ty.clone(),
428                                    })
429                                })
430                                .transpose()
431                        })
432                        .collect::<Result<Vec<_>>>(),
433                    Fields::Unit => Ok(vec![]),
434                }
435            })
436            .collect::<Result<Vec<_>>>()?
437            .into_iter()
438            .flat_map(|fs| fs)
439            .collect()),
440        Data::Union(_) => Err(Error::new_spanned(
441            input,
442            "cannot `derive(Mutate)` on a union",
443        )),
444    }
445}
446
447fn gen_mutator_type_def(
448    input: &DeriveInput,
449    mutator_ty: &MutatorType,
450    container_attrs: &ContainerAttributes,
451) -> Result<TokenStream> {
452    let vis = &input.vis;
453    let name = &input.ident;
454
455    let impl_default = container_attrs.default_mutate.unwrap_or(true);
456    let mutator_name =
457        mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Impl { impl_default });
458
459    let mut temp: Option<LitStr> = None;
460    let doc = container_attrs.mutator_doc.as_deref().unwrap_or_else(|| {
461        temp = Some(LitStr::new(
462            &format!(" A mutator for the `{name}` type."),
463            input.ident.span(),
464        ));
465        std::slice::from_ref(temp.as_ref().unwrap())
466    });
467
468    let where_clause = mutator_ty.where_clause(WhereClauseKind::NoMutateBounds);
469
470    let fields = mutator_ty
471        .mutator_fields
472        .iter()
473        .map(|f| {
474            let ident = &f.ident;
475            if let Some(g) = f.generic.as_ref() {
476                quote! { #ident: #g , }
477            } else {
478                let for_ty = &f.for_ty;
479                debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
480                quote! { #ident: <#for_ty as mutatis::DefaultMutate>::DefaultMutate, }
481            }
482        })
483        .collect::<Vec<_>>();
484
485    let phantoms = mutator_ty.phantom_fields_defs(input);
486
487    Ok(quote! {
488        #( #[doc = #doc] )*
489        // #[derive(Clone, Debug)]
490        #vis struct #mutator_name #where_clause {
491            #( #fields )*
492            #( #phantoms )*
493            _private: (),
494        }
495    })
496}
497
498fn gen_mutator_type_default_impl(mutator_ty: &MutatorType) -> Result<TokenStream> {
499    let impl_generics = mutator_ty.mutator_impl_generics();
500    let mutator_name = mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Generics);
501    let where_clause = mutator_ty.where_clause(WhereClauseKind::DefaultBounds);
502
503    let fields = mutator_ty
504        .mutator_fields
505        .iter()
506        .map(|f| {
507            let ident = &f.ident;
508            quote! { #ident: Default::default(), }
509        })
510        .collect::<Vec<_>>();
511
512    let phantoms = mutator_ty.phantom_fields_literals();
513
514    Ok(quote! {
515        #[automatically_derived]
516        impl #impl_generics Default for #mutator_name #where_clause {
517            fn default() -> Self {
518                Self {
519                    #( #fields )*
520                    #( #phantoms )*
521                    _private: (),
522                }
523            }
524        }
525    })
526}
527
528fn gen_mutator_ctor(mutator_ty: &MutatorType) -> Result<TokenStream> {
529    let impl_generics = mutator_ty.mutator_impl_generics();
530
531    let params = mutator_ty
532        .mutator_fields
533        .iter()
534        .filter_map(|f| {
535            f.generic.as_ref().map(|g| {
536                let ident = &f.ident;
537                quote! { #ident: #g , }
538            })
539        })
540        .collect::<Vec<_>>();
541
542    let fields = mutator_ty
543        .mutator_fields
544        .iter()
545        .map(|f| {
546            let ident = &f.ident;
547            if f.generic.is_some() {
548                quote! { #ident , }
549            } else {
550                let for_ty = &f.for_ty;
551                debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
552                quote! { #ident: mutatis::mutators::default::<#for_ty>() , }
553            }
554        })
555        .collect::<Vec<_>>();
556
557    let name = &mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Generics);
558    let doc = format!("Construct a new `{name}` instance.");
559    let where_clause = mutator_ty.where_clause(WhereClauseKind::NoMutateBounds);
560    let phantoms = mutator_ty.phantom_fields_literals();
561
562    Ok(quote! {
563        impl #impl_generics #name #where_clause {
564            #[doc = #doc]
565            #[inline]
566            pub fn new( #( #params )* ) -> Self {
567                Self {
568                    #( #fields )*
569                    #( #phantoms )*
570                    _private: (),
571                }
572            }
573        }
574    })
575}
576
577fn gen_mutator_impl(input: &DeriveInput, mutator_ty: &MutatorType) -> Result<TokenStream> {
578    let impl_generics = mutator_ty.mutator_impl_generics();
579
580    // The type name *with* generic arguments (e.g. `Foo<T>`). Valid only in type
581    // positions (the `impl`, method signatures).
582    let ty_name = mutator_ty.ty_name_with_generics();
583
584    // The bare type name *without* generic arguments (e.g. `Foo`). Required in
585    // pattern and expression positions, where generic args would need turbofish
586    // syntax; Rust infers the type params from context instead.
587    let bare_ty_name = &mutator_ty.ty_name;
588
589    let is_multi_variant_enum = matches!(&input.data, Data::Enum(data) if data.variants.len() > 1);
590    let where_clause = if is_multi_variant_enum {
591        mutator_ty.where_clause(WhereClauseKind::MutateAndGenerateBounds)
592    } else {
593        mutator_ty.where_clause(WhereClauseKind::MutateBounds)
594    };
595
596    let mut fields_iter = mutator_ty.mutator_fields.iter();
597    let mut make_mutation = |value| {
598        let ident = &fields_iter.next().unwrap().ident;
599        quote! { self.#ident.mutate(mutations, #value)?; }
600    };
601
602    let mutation_body = match &input.data {
603        Data::Struct(data) => match &data.fields {
604            Fields::Named(fields) => {
605                let mutations = fields
606                    .named
607                    .iter()
608                    .filter(|f| FieldBehavior::for_field(f).unwrap().is_some())
609                    .map(|f| {
610                        let ident = &f.ident;
611                        make_mutation(quote! { &mut value.#ident })
612                    });
613                quote! {
614                    #( #mutations )*
615                }
616            }
617            Fields::Unnamed(fields) => {
618                let mutations = fields
619                    .unnamed
620                    .iter()
621                    .enumerate()
622                    .filter(|(_i, f)| FieldBehavior::for_field(f).unwrap().is_some())
623                    .map(|(i, f)| {
624                        let index = Index {
625                            index: u32::try_from(i).unwrap(),
626                            span: f.span(),
627                        };
628                        make_mutation(quote! { &mut value.#index })
629                    });
630                quote! {
631                    #( #mutations )*
632                }
633            }
634            Fields::Unit => quote! {},
635        },
636
637        Data::Enum(data) => {
638            // Build the existing field-mutation match arms.
639            let mut field_mutation_arms = vec![];
640            for v in data.variants.iter() {
641                let variant_ident = &v.ident;
642                match &v.fields {
643                    Fields::Named(fields) => {
644                        let mut patterns = vec![];
645                        let mutates = fields
646                            .named
647                            .iter()
648                            .filter_map(|f| {
649                                let ident = &f.ident;
650                                if FieldBehavior::for_field(f).unwrap().is_some() {
651                                    patterns.push(quote! { ref mut #ident , });
652                                    Some(make_mutation(quote! { #ident }))
653                                } else {
654                                    patterns.push(quote! { #ident: _ , });
655                                    None
656                                }
657                            })
658                            .collect::<Vec<_>>();
659                        field_mutation_arms.push(quote! {
660                            #bare_ty_name::#variant_ident { #( #patterns )* } => {
661                                #( #mutates )*
662                            }
663                        });
664                    }
665
666                    Fields::Unnamed(fields) => {
667                        let mut patterns = vec![];
668                        let mutates = fields
669                            .unnamed
670                            .iter()
671                            .enumerate()
672                            .filter_map(|(i, f)| {
673                                if FieldBehavior::for_field(f).unwrap().is_some() {
674                                    let binding = Ident::new(&format!("field{}", i), f.span());
675                                    patterns.push(quote! { ref mut #binding , });
676                                    Some(make_mutation(quote! { #binding }))
677                                } else {
678                                    patterns.push(quote! { _ , });
679                                    None
680                                }
681                            })
682                            .collect::<Vec<_>>();
683                        field_mutation_arms.push(quote! {
684                            #bare_ty_name::#variant_ident( #( #patterns )* ) => {
685                                #( #mutates )*
686                            }
687                        });
688                    }
689
690                    Fields::Unit => {
691                        field_mutation_arms.push(quote! {
692                            #bare_ty_name::#variant_ident => {}
693                        });
694                    }
695                }
696            }
697
698            // Build variant-switching mutations for enums with multiple
699            // variants.
700            let variant_switching = if data.variants.len() > 1 {
701                // Build a match to determine the current variant index.
702                let index_arms: Vec<_> = data
703                    .variants
704                    .iter()
705                    .enumerate()
706                    .map(|(v_idx, v)| {
707                        let variant_ident = &v.ident;
708                        match &v.fields {
709                            Fields::Named(_) => {
710                                quote! { #bare_ty_name::#variant_ident { .. } => #v_idx, }
711                            }
712                            Fields::Unnamed(_) => {
713                                quote! { #bare_ty_name::#variant_ident(..) => #v_idx, }
714                            }
715                            Fields::Unit => quote! { #bare_ty_name::#variant_ident => #v_idx, },
716                        }
717                    })
718                    .collect();
719
720                // For each variant, build an expression that constructs a new
721                // instance of that variant. For non-ignored fields, use the
722                // mutator's `generate` method. For ignored fields, use
723                // `Default::default()`.
724                let mut variant_mutations = vec![];
725                let mut mutator_field_offset = 0usize;
726                for (v_idx, v) in data.variants.iter().enumerate() {
727                    let variant_ident = &v.ident;
728
729                    let construction = match &v.fields {
730                        Fields::Named(fields) => {
731                            let field_exprs: Vec<_> = fields
732                                .named
733                                .iter()
734                                .map(|f| {
735                                    let ident = &f.ident;
736                                    if let Some(_behavior) = FieldBehavior::for_field(f).unwrap() {
737                                        let mutator_ident =
738                                            &mutator_ty.mutator_fields[mutator_field_offset].ident;
739                                        mutator_field_offset += 1;
740                                        quote! { #ident: self.#mutator_ident.generate(ctx)? }
741                                    } else {
742                                        quote! { #ident: Default::default() }
743                                    }
744                                })
745                                .collect();
746                            quote! {
747                                *value = #bare_ty_name::#variant_ident { #( #field_exprs ),* };
748                            }
749                        }
750                        Fields::Unnamed(fields) => {
751                            let field_exprs: Vec<_> = fields
752                                .unnamed
753                                .iter()
754                                .map(|f| {
755                                    if let Some(_behavior) = FieldBehavior::for_field(f).unwrap() {
756                                        let mutator_ident =
757                                            &mutator_ty.mutator_fields[mutator_field_offset].ident;
758                                        mutator_field_offset += 1;
759                                        quote! { self.#mutator_ident.generate(ctx)? }
760                                    } else {
761                                        quote! { Default::default() }
762                                    }
763                                })
764                                .collect();
765                            quote! {
766                                *value = #bare_ty_name::#variant_ident( #( #field_exprs ),* );
767                            }
768                        }
769                        Fields::Unit => {
770                            quote! {
771                                *value = #bare_ty_name::#variant_ident;
772                            }
773                        }
774                    };
775
776                    variant_mutations.push((v_idx, construction));
777                }
778
779                let num_variants = data.variants.len();
780                let group_count = num_variants - 1;
781                let group_arms: Vec<_> = variant_mutations
782                    .iter()
783                    .map(|(v_idx, construction)| {
784                        quote! {
785                            #v_idx => {
786                                #construction
787                                Ok(())
788                            }
789                        }
790                    })
791                    .collect();
792
793                quote! {
794                    let _variant_index: usize = match value {
795                        #( #index_arms )*
796                    };
797                    mutations.mutation_group(#group_count as u32, |ctx, _which| {
798                        let _target = if (_which as usize) >= _variant_index {
799                            _which as usize + 1
800                        } else {
801                            _which as usize
802                        };
803                        match _target {
804                            #( #group_arms )*
805                            _ => unreachable!(),
806                        }
807                    })?;
808                }
809            } else {
810                quote! {}
811            };
812
813            quote! {
814                #variant_switching
815                match *value {
816                    #( #field_mutation_arms )*
817                }
818            }
819        }
820
821        Data::Union(_) => {
822            return Err(Error::new_spanned(
823                input,
824                "cannot `derive(Mutate)` on a union",
825            ))
826        }
827    };
828
829    let mutate_method = quote! {
830        fn mutate(
831            &mut self,
832            mutations: &mut mutatis::Candidates,
833            value: &mut #ty_name,
834        ) -> mutatis::Result<()> {
835            #mutation_body
836
837            // Silence unused-variable warnings if every field was marked
838            // `ignore`. Allow unreachable for empty enums.
839            #[allow(unreachable_code)]
840            let _ = (mutations, value);
841
842            Ok(())
843        }
844    };
845
846    let mutation_count_body = match &input.data {
847        Data::Struct(data) => {
848            let mut field_counts = vec![];
849            let mut mutator_field_idx = 0usize;
850            match &data.fields {
851                Fields::Named(fields) => {
852                    for f in fields.named.iter() {
853                        if FieldBehavior::for_field(f).unwrap().is_some() {
854                            let field_ident = &f.ident;
855                            let mutator_ident = &mutator_ty.mutator_fields[mutator_field_idx].ident;
856                            mutator_field_idx += 1;
857                            field_counts.push(quote! {
858                                _count += self.#mutator_ident.mutation_count(
859                                    &value.#field_ident,
860                                    shrink,
861                                )?;
862                            });
863                        }
864                    }
865                }
866                Fields::Unnamed(fields) => {
867                    for (i, f) in fields.unnamed.iter().enumerate() {
868                        if FieldBehavior::for_field(f).unwrap().is_some() {
869                            let index = Index {
870                                index: u32::try_from(i).unwrap(),
871                                span: f.span(),
872                            };
873                            let mutator_ident = &mutator_ty.mutator_fields[mutator_field_idx].ident;
874                            mutator_field_idx += 1;
875                            field_counts.push(quote! {
876                                _count += self.#mutator_ident.mutation_count(
877                                    &value.#index,
878                                    shrink,
879                                )?;
880                            });
881                        }
882                    }
883                }
884                Fields::Unit => {}
885            }
886            quote! {
887                let mut _count = 0u32;
888                #(#field_counts)*
889                Some(_count)
890            }
891        }
892
893        Data::Enum(data) => {
894            let variant_switch_count = if data.variants.len() > 1 {
895                data.variants.len() - 1
896            } else {
897                0
898            };
899
900            let mut count_arms = vec![];
901            let mut mutator_field_idx = 0usize;
902            for v in data.variants.iter() {
903                let variant_ident = &v.ident;
904                match &v.fields {
905                    Fields::Named(fields) => {
906                        let mut patterns = vec![];
907                        let mut fld_counts = vec![];
908                        for f in fields.named.iter() {
909                            let ident = &f.ident;
910                            if FieldBehavior::for_field(f).unwrap().is_some() {
911                                patterns.push(quote! { ref #ident, });
912                                let mutator_ident =
913                                    &mutator_ty.mutator_fields[mutator_field_idx].ident;
914                                mutator_field_idx += 1;
915                                fld_counts.push(quote! {
916                                    _count += self.#mutator_ident.mutation_count(
917                                        #ident,
918                                        shrink,
919                                    )?;
920                                });
921                            } else {
922                                patterns.push(quote! { #ident: _, });
923                            }
924                        }
925                        count_arms.push(quote! {
926                            #bare_ty_name::#variant_ident { #(#patterns)* } => {
927                                #(#fld_counts)*
928                            }
929                        });
930                    }
931                    Fields::Unnamed(fields) => {
932                        let mut patterns = vec![];
933                        let mut fld_counts = vec![];
934                        for (i, f) in fields.unnamed.iter().enumerate() {
935                            if FieldBehavior::for_field(f).unwrap().is_some() {
936                                let binding = Ident::new(&format!("field{}", i), f.span());
937                                patterns.push(quote! { ref #binding, });
938                                let mutator_ident =
939                                    &mutator_ty.mutator_fields[mutator_field_idx].ident;
940                                mutator_field_idx += 1;
941                                fld_counts.push(quote! {
942                                    _count += self.#mutator_ident.mutation_count(
943                                        #binding,
944                                        shrink,
945                                    )?;
946                                });
947                            } else {
948                                patterns.push(quote! { _, });
949                            }
950                        }
951                        count_arms.push(quote! {
952                            #bare_ty_name::#variant_ident(#(#patterns)*) => {
953                                #(#fld_counts)*
954                            }
955                        });
956                    }
957                    Fields::Unit => {
958                        count_arms.push(quote! {
959                            #bare_ty_name::#variant_ident => {}
960                        });
961                    }
962                }
963            }
964
965            if count_arms.is_empty() {
966                quote! { Some(0u32) }
967            } else {
968                quote! {
969                    let mut _count = #variant_switch_count as u32;
970                    match *value {
971                        #(#count_arms)*
972                    }
973                    Some(_count)
974                }
975            }
976        }
977
978        Data::Union(_) => quote! { None },
979    };
980
981    let mutation_count_method = quote! {
982        #[inline]
983        fn mutation_count(&self, value: &#ty_name, shrink: bool) -> core::option::Option<u32> {
984            #mutation_count_body
985        }
986    };
987
988    let mutator_name = &mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Generics);
989
990    Ok(quote! {
991        #[automatically_derived]
992        impl #impl_generics mutatis::Mutate<#ty_name> for #mutator_name
993            #where_clause
994        {
995            #mutate_method
996            #mutation_count_method
997        }
998    })
999}
1000
1001fn gen_default_mutator_impl(
1002    input: &DeriveInput,
1003    mutator_ty: &MutatorType,
1004    container_attrs: &ContainerAttributes,
1005) -> Result<TokenStream> {
1006    let impl_default = container_attrs.default_mutate.unwrap_or(true);
1007    if !impl_default {
1008        return Ok(quote! {});
1009    }
1010
1011    let ty_generics = if mutator_ty.ty_impl_generics.is_empty() {
1012        quote! {}
1013    } else {
1014        let gens = &mutator_ty.ty_impl_generics;
1015        quote! { < #( #gens ),* > }
1016    };
1017
1018    let ty_name = mutator_ty.ty_name_with_generics();
1019
1020    // A multi-variant enum's `Mutate` impl switches variants via `generate`, so
1021    // its `DefaultMutate` impl needs the field mutators to be `Generate` too.
1022    let is_multi_variant_enum = matches!(&input.data, Data::Enum(data) if data.variants.len() > 1);
1023    let where_clause = if is_multi_variant_enum {
1024        mutator_ty.where_clause(WhereClauseKind::DefaultMutateAndGenerateBounds)
1025    } else {
1026        mutator_ty.where_clause(WhereClauseKind::DefaultMutateBounds)
1027    };
1028    let mutator_name =
1029        &mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::JustTyGenerics);
1030
1031    Ok(quote! {
1032        #[automatically_derived]
1033        impl #ty_generics mutatis::DefaultMutate for #ty_name
1034            #where_clause
1035        {
1036            type DefaultMutate = #mutator_name;
1037        }
1038    })
1039}
1040
1041fn gen_generate_impl(
1042    input: &DeriveInput,
1043    mutator_ty: &MutatorType,
1044    container_attrs: &ContainerAttributes,
1045) -> Result<TokenStream> {
1046    let impl_generate = container_attrs.generate.unwrap_or(true);
1047    if !impl_generate {
1048        return Ok(quote! {});
1049    }
1050
1051    let impl_generics = mutator_ty.mutator_impl_generics();
1052    let ty_name = mutator_ty.ty_name_with_generics();
1053    let mutator_name = &mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Generics);
1054    let where_clause = mutator_ty.where_clause(WhereClauseKind::MutateAndGenerateBounds);
1055
1056    let mut fields_iter = mutator_ty.mutator_fields.iter();
1057    let mut next_field_generate = || -> TokenStream {
1058        let mf = fields_iter.next().unwrap();
1059        let ident = &mf.ident;
1060        quote! { self.#ident.generate(cx)? }
1061    };
1062
1063    // For struct literals, we can't include generic args (e.g. `Foo<T> { .. }`
1064    // is invalid). Use the bare name and let Rust infer the type params.
1065    let bare_ty_name = &mutator_ty.ty_name;
1066
1067    let generate_body = match &input.data {
1068        Data::Struct(data) => match &data.fields {
1069            Fields::Named(fields) => {
1070                let field_exprs: Vec<_> = fields
1071                    .named
1072                    .iter()
1073                    .map(|f| {
1074                        let ident = &f.ident;
1075                        if FieldBehavior::for_field(f).unwrap().is_some() {
1076                            let expr = next_field_generate();
1077                            quote! { #ident: #expr }
1078                        } else {
1079                            quote! { #ident: Default::default() }
1080                        }
1081                    })
1082                    .collect();
1083                quote! { Ok(#bare_ty_name { #( #field_exprs ),* }) }
1084            }
1085            Fields::Unnamed(fields) => {
1086                let field_exprs: Vec<_> = fields
1087                    .unnamed
1088                    .iter()
1089                    .map(|f| {
1090                        if FieldBehavior::for_field(f).unwrap().is_some() {
1091                            next_field_generate()
1092                        } else {
1093                            quote! { Default::default() }
1094                        }
1095                    })
1096                    .collect();
1097                quote! { Ok(#bare_ty_name( #( #field_exprs ),* )) }
1098            }
1099            Fields::Unit => {
1100                quote! { Ok(#bare_ty_name) }
1101            }
1102        },
1103
1104        Data::Enum(data) => {
1105            if data.variants.is_empty() {
1106                quote! { unreachable!() }
1107            } else {
1108                let num_variants = data.variants.len();
1109                let mut mutator_field_offset = 0usize;
1110                let match_arms: Vec<_> = data
1111                    .variants
1112                    .iter()
1113                    .enumerate()
1114                    .map(|(v_idx, v)| {
1115                        let variant_ident = &v.ident;
1116                        let construction = match &v.fields {
1117                            Fields::Named(fields) => {
1118                                let field_exprs: Vec<_> = fields
1119                                    .named
1120                                    .iter()
1121                                    .map(|f| {
1122                                        let ident = &f.ident;
1123                                        if FieldBehavior::for_field(f).unwrap().is_some() {
1124                                            let mf =
1125                                                &mutator_ty.mutator_fields[mutator_field_offset];
1126                                            let mutator_ident = &mf.ident;
1127                                            mutator_field_offset += 1;
1128                                            quote! { #ident: self.#mutator_ident.generate(cx)? }
1129                                        } else {
1130                                            quote! { #ident: Default::default() }
1131                                        }
1132                                    })
1133                                    .collect();
1134                                quote! { #bare_ty_name::#variant_ident { #( #field_exprs ),* } }
1135                            }
1136                            Fields::Unnamed(fields) => {
1137                                let field_exprs: Vec<_> = fields
1138                                    .unnamed
1139                                    .iter()
1140                                    .map(|f| {
1141                                        if FieldBehavior::for_field(f).unwrap().is_some() {
1142                                            let mf =
1143                                                &mutator_ty.mutator_fields[mutator_field_offset];
1144                                            let mutator_ident = &mf.ident;
1145                                            mutator_field_offset += 1;
1146                                            quote! { self.#mutator_ident.generate(cx)? }
1147                                        } else {
1148                                            quote! { Default::default() }
1149                                        }
1150                                    })
1151                                    .collect();
1152                                quote! { #bare_ty_name::#variant_ident( #( #field_exprs ),* ) }
1153                            }
1154                            Fields::Unit => {
1155                                quote! { #bare_ty_name::#variant_ident }
1156                            }
1157                        };
1158                        quote! { Some(#v_idx) => Ok(#construction), }
1159                    })
1160                    .collect();
1161
1162                quote! {
1163                    match cx.rng().gen_index(#num_variants) {
1164                        #( #match_arms )*
1165                        _ => unreachable!(),
1166                    }
1167                }
1168            }
1169        }
1170
1171        Data::Union(_) => {
1172            return Err(Error::new_spanned(
1173                input,
1174                "cannot `derive(Mutate)` on a union",
1175            ))
1176        }
1177    };
1178
1179    Ok(quote! {
1180        #[automatically_derived]
1181        impl #impl_generics mutatis::Generate<#ty_name> for #mutator_name
1182            #where_clause
1183        {
1184            fn generate(&mut self, cx: &mut mutatis::Context) -> mutatis::Result<#ty_name> {
1185                #generate_body
1186            }
1187        }
1188    })
1189}