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 ty_impl_generics: Vec<TokenStream>,
53
54 ty_name_generics: Vec<TokenStream>,
57
58 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 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 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 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 ident: Ident,
334 generic: Option<Ident>,
336 behavior: FieldBehavior,
338 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 #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 let ty_name = mutator_ty.ty_name_with_generics();
583
584 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 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 let variant_switching = if data.variants.len() > 1 {
701 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 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 #[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 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 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}