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(&mutator_ty, &container_attrs)?;
31
32 Ok(quote! {
33 #mutator_type_def
34 #mutator_type_default_impl
35 #mutator_ctor
36 #mutator_impl
37 #default_mutator_impl
38 })
39}
40
41struct MutatorType {
42 ty_name: Ident,
43
44 mutator_name: Ident,
45
46 mutator_fields: Vec<MutatorField>,
47
48 ty_impl_generics: Vec<TokenStream>,
51
52 ty_name_generics: Vec<TokenStream>,
55
56 ty_generics_bounds: Vec<TokenStream>,
59}
60
61impl MutatorType {
62 fn new(input: &DeriveInput, container_attrs: &ContainerAttributes) -> Result<Self> {
63 let ty_name = input.ident.clone();
64
65 let mutator_name = container_attrs
66 .mutator_name
67 .clone()
68 .unwrap_or_else(|| Ident::new(&format!("{}Mutator", input.ident), input.ident.span()));
69
70 let mutator_fields = get_mutator_fields(&input)?;
71
72 let mut ty_impl_generics = vec![];
73 let mut ty_name_generics = vec![];
74 let mut ty_generics_bounds = vec![];
75
76 for gen in &input.generics.params {
77 match gen {
78 GenericParam::Lifetime(l) => {
79 if !l.bounds.is_empty() {
80 ty_generics_bounds.push(quote! { #l });
81 }
82
83 let l = &l.lifetime;
84 ty_impl_generics.push(quote! { #l });
85 ty_name_generics.push(quote! { #l });
86 }
87 GenericParam::Const(c) => {
88 ty_impl_generics.push(quote! { #c });
89 let c = &c.ident;
90 ty_name_generics.push(quote! { #c });
91 }
92 GenericParam::Type(t) => {
93 if !t.bounds.is_empty() {
94 ty_generics_bounds.push(quote! { #t });
95 }
96 let t = &t.ident;
97 ty_impl_generics.push(quote! { #t });
98 ty_name_generics.push(quote! { #t });
99 }
100 }
101 }
102
103 if let Some(wc) = &input.generics.where_clause {
104 for bound in wc.predicates.iter() {
105 ty_generics_bounds.push(quote! { #bound });
106 }
107 }
108
109 Ok(Self {
110 ty_name,
111 mutator_name,
112 mutator_fields,
113 ty_impl_generics,
114 ty_name_generics,
115 ty_generics_bounds,
116 })
117 }
118
119 fn mutator_impl_generics_iter(&self) -> impl Iterator<Item = TokenStream> + '_ {
120 self.ty_impl_generics.iter().cloned().chain(
121 self.mutator_fields
122 .iter()
123 .filter_map(|f| f.generic.as_ref().map(|g| quote! { #g })),
124 )
125 }
126
127 fn mutator_impl_generics(&self) -> TokenStream {
130 let impl_generics = self
131 .ty_impl_generics
132 .iter()
133 .cloned()
134 .chain(
135 self.mutator_fields
136 .iter()
137 .filter_map(|f| f.generic.as_ref().map(|g| quote! { #g })),
138 )
139 .collect::<Vec<_>>();
140 if impl_generics.is_empty() {
141 quote! {}
142 } else {
143 quote! { < #( #impl_generics ),* > }
144 }
145 }
146
147 fn mutator_name_generics_iter(&self) -> impl Iterator<Item = TokenStream> + '_ {
151 self.ty_name_generics.iter().cloned().chain(
152 self.mutator_fields
153 .iter()
154 .filter_map(|f| f.generic.as_ref().map(|g| quote! { #g })),
155 )
156 }
157
158 fn mutator_impl_generics_with_defaults_iter(&self) -> impl Iterator<Item = TokenStream> + '_ {
159 self.ty_impl_generics
160 .iter()
161 .cloned()
162 .chain(self.mutator_fields.iter().filter_map(move |f| {
163 f.generic.as_ref().map(|g| {
164 let for_ty = &f.for_ty;
165 quote! { #g = <#for_ty as mutatis::DefaultMutate>::DefaultMutate }
166 })
167 }))
168 }
169
170 fn ty_name_with_generics(&self) -> TokenStream {
171 let ty_name = &self.ty_name;
172 if self.ty_name_generics.is_empty() {
173 quote! { #ty_name }
174 } else {
175 let ty_generics = self.ty_name_generics.iter();
176 quote! { #ty_name < #( #ty_generics ),* > }
177 }
178 }
179
180 fn mutator_name_with_generics(&self, kind: MutatorNameGenericsKind) -> TokenStream {
181 let mutator_name = &self.mutator_name;
182
183 let generics = match kind {
184 MutatorNameGenericsKind::Generics => {
185 self.mutator_name_generics_iter().collect::<Vec<_>>()
186 }
187 MutatorNameGenericsKind::Impl {
188 impl_default: false,
189 } => self.mutator_impl_generics_iter().collect::<Vec<_>>(),
190 MutatorNameGenericsKind::Impl { impl_default: true } => self
191 .mutator_impl_generics_with_defaults_iter()
192 .collect::<Vec<_>>(),
193 MutatorNameGenericsKind::JustTyGenerics => self.ty_name_generics.clone(),
194 };
195
196 if generics.is_empty() {
197 quote! { #mutator_name }
198 } else {
199 quote! { #mutator_name < #( #generics ),* > }
200 }
201 }
202
203 fn where_clause(&self, kind: WhereClauseKind) -> TokenStream {
204 let mut bounds = self.ty_generics_bounds.clone();
205
206 match kind {
207 WhereClauseKind::NoMutateBounds => {}
208 WhereClauseKind::MutateBounds => {
209 for f in &self.mutator_fields {
210 let for_ty = &f.for_ty;
211 if let Some(g) = f.generic.as_ref() {
212 bounds.push(quote! { #g: mutatis::Mutate<#for_ty> });
213 } else {
214 debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
215 bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
216 }
217 }
218 }
219 WhereClauseKind::MutateAndGenerateBounds => {
220 for f in &self.mutator_fields {
221 let for_ty = &f.for_ty;
222 if let Some(g) = f.generic.as_ref() {
223 bounds.push(
224 quote! { #g: mutatis::Mutate<#for_ty> + mutatis::Generate<#for_ty> },
225 );
226 } else {
227 debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
228 bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
229 bounds.push(quote! { <#for_ty as mutatis::DefaultMutate>::DefaultMutate: mutatis::Generate<#for_ty> });
230 }
231 }
232 }
233 WhereClauseKind::DefaultBounds => {
234 for f in &self.mutator_fields {
235 if let Some(g) = f.generic.as_ref() {
236 bounds.push(quote! { #g: Default });
237 } else {
238 let for_ty = &f.for_ty;
239 debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
240 bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
241 }
242 }
243 }
244 WhereClauseKind::DefaultMutateBounds => {
245 for f in &self.mutator_fields {
246 let for_ty = &f.for_ty;
247 bounds.push(quote! { #for_ty: mutatis::DefaultMutate });
248 }
249 }
250 }
251
252 if bounds.is_empty() {
253 quote! {}
254 } else {
255 quote! { where #( #bounds ),* }
256 }
257 }
258
259 fn phantom_fields_defs<'a>(
260 &self,
261 input: &'a DeriveInput,
262 ) -> impl Iterator<Item = TokenStream> + 'a {
263 let make_phantom_field = |i, ty| {
264 let ident = Ident::new(&format!("_phantom{i}"), Span::call_site());
265 quote! { #ident : core::marker::PhantomData<#ty> , }
266 };
267
268 input
269 .generics
270 .params
271 .iter()
272 .enumerate()
273 .map(move |(i, g)| match g {
274 GenericParam::Lifetime(l) => {
275 let l = &l.lifetime;
276 make_phantom_field(i, quote! { & #l () })
277 }
278 GenericParam::Const(c) => {
279 let c = &c.ident;
280 make_phantom_field(i, quote! { [(); #c] })
281 }
282 GenericParam::Type(t) => {
283 let t = &t.ident;
284 make_phantom_field(i, quote! { #t })
285 }
286 })
287 }
288
289 fn phantom_fields_literals(&self) -> impl Iterator<Item = TokenStream> + '_ {
290 (0..self.ty_name_generics.len()).map(|i| {
291 let ident = Ident::new(&format!("_phantom{i}"), Span::call_site());
292 quote! { #ident : core::marker::PhantomData, }
293 })
294 }
295}
296
297#[derive(Clone, Copy)]
298enum WhereClauseKind {
299 NoMutateBounds,
300 MutateBounds,
301 MutateAndGenerateBounds,
302 DefaultBounds,
303 DefaultMutateBounds,
304}
305
306#[derive(Clone, Copy)]
307enum MutatorNameGenericsKind {
308 Generics,
309 Impl { impl_default: bool },
310 JustTyGenerics,
311}
312
313struct MutatorField {
314 ident: Ident,
316 generic: Option<Ident>,
318 behavior: FieldBehavior,
320 for_ty: Type,
322}
323
324fn get_mutator_fields(input: &DeriveInput) -> Result<Vec<MutatorField>> {
325 let mut i = 0;
326 let mut generic = |b: &FieldBehavior| -> Option<Ident> {
327 if b.needs_generic() {
328 let g = Ident::new(&format!("MutatorT{}", i), Span::call_site());
329 i += 1;
330 Some(g)
331 } else {
332 None
333 }
334 };
335
336 match &input.data {
337 Data::Struct(data) => match &data.fields {
338 Fields::Named(fields) => fields
339 .named
340 .iter()
341 .filter_map(|f| {
342 FieldBehavior::for_field(f)
343 .map(|b| {
344 b.map(|b| MutatorField {
345 ident: f.ident.clone().unwrap(),
346 generic: generic(&b),
347 behavior: b,
348 for_ty: f.ty.clone(),
349 })
350 })
351 .transpose()
352 })
353 .collect(),
354 Fields::Unnamed(fields) => fields
355 .unnamed
356 .iter()
357 .enumerate()
358 .filter_map(|(i, f)| {
359 FieldBehavior::for_field(f)
360 .map(|b| {
361 b.map(|b| MutatorField {
362 ident: Ident::new(&format!("field{}", i), f.span()),
363 generic: generic(&b),
364 behavior: b,
365 for_ty: f.ty.clone(),
366 })
367 })
368 .transpose()
369 })
370 .collect(),
371 Fields::Unit => Ok(vec![]),
372 },
373 Data::Enum(data) => Ok(data
374 .variants
375 .iter()
376 .map(|v| {
377 let prefix = v.ident.to_string().to_lowercase();
378 match v.fields {
379 Fields::Named(ref fields) => fields
380 .named
381 .iter()
382 .filter_map(|f| {
383 FieldBehavior::for_field(f)
384 .map(|b| {
385 b.map(|b| MutatorField {
386 ident: Ident::new(
387 &format!("{prefix}_{}", f.ident.clone().unwrap()),
388 f.span(),
389 ),
390 generic: generic(&b),
391 behavior: b,
392 for_ty: f.ty.clone(),
393 })
394 })
395 .transpose()
396 })
397 .collect::<Result<Vec<_>>>(),
398 Fields::Unnamed(ref fields) => fields
399 .unnamed
400 .iter()
401 .enumerate()
402 .filter_map(|(i, f)| {
403 FieldBehavior::for_field(f)
404 .map(|b| {
405 b.map(|b| MutatorField {
406 ident: Ident::new(&format!("{prefix}{i}"), f.span()),
407 generic: generic(&b),
408 behavior: b,
409 for_ty: f.ty.clone(),
410 })
411 })
412 .transpose()
413 })
414 .collect::<Result<Vec<_>>>(),
415 Fields::Unit => Ok(vec![]),
416 }
417 })
418 .collect::<Result<Vec<_>>>()?
419 .into_iter()
420 .flat_map(|fs| fs)
421 .collect()),
422 Data::Union(_) => Err(Error::new_spanned(
423 input,
424 "cannot `derive(Mutate)` on a union",
425 )),
426 }
427}
428
429fn gen_mutator_type_def(
430 input: &DeriveInput,
431 mutator_ty: &MutatorType,
432 container_attrs: &ContainerAttributes,
433) -> Result<TokenStream> {
434 let vis = &input.vis;
435 let name = &input.ident;
436
437 let impl_default = container_attrs.default_mutate.unwrap_or(true);
438 let mutator_name =
439 mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Impl { impl_default });
440
441 let mut temp: Option<LitStr> = None;
442 let doc = container_attrs.mutator_doc.as_deref().unwrap_or_else(|| {
443 temp = Some(LitStr::new(
444 &format!(" A mutator for the `{name}` type."),
445 input.ident.span(),
446 ));
447 std::slice::from_ref(temp.as_ref().unwrap())
448 });
449
450 let where_clause = mutator_ty.where_clause(WhereClauseKind::NoMutateBounds);
451
452 let fields = mutator_ty
453 .mutator_fields
454 .iter()
455 .map(|f| {
456 let ident = &f.ident;
457 if let Some(g) = f.generic.as_ref() {
458 quote! { #ident: #g , }
459 } else {
460 let for_ty = &f.for_ty;
461 debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
462 quote! { #ident: <#for_ty as mutatis::DefaultMutate>::DefaultMutate, }
463 }
464 })
465 .collect::<Vec<_>>();
466
467 let phantoms = mutator_ty.phantom_fields_defs(input);
468
469 Ok(quote! {
470 #( #[doc = #doc] )*
471 #vis struct #mutator_name #where_clause {
473 #( #fields )*
474 #( #phantoms )*
475 _private: (),
476 }
477 })
478}
479
480fn gen_mutator_type_default_impl(mutator_ty: &MutatorType) -> Result<TokenStream> {
481 let impl_generics = mutator_ty.mutator_impl_generics();
482 let mutator_name = mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Generics);
483 let where_clause = mutator_ty.where_clause(WhereClauseKind::DefaultBounds);
484
485 let fields = mutator_ty
486 .mutator_fields
487 .iter()
488 .map(|f| {
489 let ident = &f.ident;
490 quote! { #ident: Default::default(), }
491 })
492 .collect::<Vec<_>>();
493
494 let phantoms = mutator_ty.phantom_fields_literals();
495
496 Ok(quote! {
497 #[automatically_derived]
498 impl #impl_generics Default for #mutator_name #where_clause {
499 fn default() -> Self {
500 Self {
501 #( #fields )*
502 #( #phantoms )*
503 _private: (),
504 }
505 }
506 }
507 })
508}
509
510fn gen_mutator_ctor(mutator_ty: &MutatorType) -> Result<TokenStream> {
511 let impl_generics = mutator_ty.mutator_impl_generics();
512
513 let params = mutator_ty
514 .mutator_fields
515 .iter()
516 .filter_map(|f| {
517 f.generic.as_ref().map(|g| {
518 let ident = &f.ident;
519 quote! { #ident: #g , }
520 })
521 })
522 .collect::<Vec<_>>();
523
524 let fields = mutator_ty
525 .mutator_fields
526 .iter()
527 .map(|f| {
528 let ident = &f.ident;
529 if f.generic.is_some() {
530 quote! { #ident , }
531 } else {
532 let for_ty = &f.for_ty;
533 debug_assert_eq!(f.behavior, FieldBehavior::DefaultMutate);
534 quote! { #ident: mutatis::mutators::default::<#for_ty>() , }
535 }
536 })
537 .collect::<Vec<_>>();
538
539 let name = &mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Generics);
540 let doc = format!("Construct a new `{name}` instance.");
541 let where_clause = mutator_ty.where_clause(WhereClauseKind::NoMutateBounds);
542 let phantoms = mutator_ty.phantom_fields_literals();
543
544 Ok(quote! {
545 impl #impl_generics #name #where_clause {
546 #[doc = #doc]
547 #[inline]
548 pub fn new( #( #params )* ) -> Self {
549 Self {
550 #( #fields )*
551 #( #phantoms )*
552 _private: (),
553 }
554 }
555 }
556 })
557}
558
559fn gen_mutator_impl(input: &DeriveInput, mutator_ty: &MutatorType) -> Result<TokenStream> {
560 let impl_generics = mutator_ty.mutator_impl_generics();
561
562 let ty_name = mutator_ty.ty_name_with_generics();
563
564 let is_multi_variant_enum = matches!(&input.data, Data::Enum(data) if data.variants.len() > 1);
565 let where_clause = if is_multi_variant_enum {
566 mutator_ty.where_clause(WhereClauseKind::MutateAndGenerateBounds)
567 } else {
568 mutator_ty.where_clause(WhereClauseKind::MutateBounds)
569 };
570
571 let mut fields_iter = mutator_ty.mutator_fields.iter();
572 let mut make_mutation = |value| {
573 let ident = &fields_iter.next().unwrap().ident;
574 quote! { self.#ident.mutate(mutations, #value)?; }
575 };
576
577 let mutation_body = match &input.data {
578 Data::Struct(data) => match &data.fields {
579 Fields::Named(fields) => {
580 let mutations = fields
581 .named
582 .iter()
583 .filter(|f| FieldBehavior::for_field(f).unwrap().is_some())
584 .map(|f| {
585 let ident = &f.ident;
586 make_mutation(quote! { &mut value.#ident })
587 });
588 quote! {
589 #( #mutations )*
590 }
591 }
592 Fields::Unnamed(fields) => {
593 let mutations = fields
594 .unnamed
595 .iter()
596 .enumerate()
597 .filter(|(_i, f)| FieldBehavior::for_field(f).unwrap().is_some())
598 .map(|(i, f)| {
599 let index = Index {
600 index: u32::try_from(i).unwrap(),
601 span: f.span(),
602 };
603 make_mutation(quote! { &mut value.#index })
604 });
605 quote! {
606 #( #mutations )*
607 }
608 }
609 Fields::Unit => quote! {},
610 },
611
612 Data::Enum(data) => {
613 let mut field_mutation_arms = vec![];
615 for v in data.variants.iter() {
616 let variant_ident = &v.ident;
617 match &v.fields {
618 Fields::Named(fields) => {
619 let mut patterns = vec![];
620 let mutates = fields
621 .named
622 .iter()
623 .filter_map(|f| {
624 let ident = &f.ident;
625 if FieldBehavior::for_field(f).unwrap().is_some() {
626 patterns.push(quote! { #ident , });
627 Some(make_mutation(quote! { #ident }))
628 } else {
629 patterns.push(quote! { #ident: _ , });
630 None
631 }
632 })
633 .collect::<Vec<_>>();
634 field_mutation_arms.push(quote! {
635 #ty_name::#variant_ident { #( #patterns )* } => {
636 #( #mutates )*
637 }
638 });
639 }
640
641 Fields::Unnamed(fields) => {
642 let mut patterns = vec![];
643 let mutates = fields
644 .unnamed
645 .iter()
646 .enumerate()
647 .filter_map(|(i, f)| {
648 if FieldBehavior::for_field(f).unwrap().is_some() {
649 let binding = Ident::new(&format!("field{}", i), f.span());
650 patterns.push(quote! { #binding , });
651 Some(make_mutation(quote! { #binding }))
652 } else {
653 patterns.push(quote! { _ , });
654 None
655 }
656 })
657 .collect::<Vec<_>>();
658 field_mutation_arms.push(quote! {
659 #ty_name::#variant_ident( #( #patterns )* ) => {
660 #( #mutates )*
661 }
662 });
663 }
664
665 Fields::Unit => {
666 field_mutation_arms.push(quote! {
667 #ty_name::#variant_ident => {}
668 });
669 }
670 }
671 }
672
673 let variant_switching = if data.variants.len() > 1 {
676 let index_arms: Vec<_> = data
678 .variants
679 .iter()
680 .enumerate()
681 .map(|(v_idx, v)| {
682 let variant_ident = &v.ident;
683 match &v.fields {
684 Fields::Named(_) => {
685 quote! { #ty_name::#variant_ident { .. } => #v_idx, }
686 }
687 Fields::Unnamed(_) => {
688 quote! { #ty_name::#variant_ident(..) => #v_idx, }
689 }
690 Fields::Unit => quote! { #ty_name::#variant_ident => #v_idx, },
691 }
692 })
693 .collect();
694
695 let mut variant_mutations = vec![];
700 let mut mutator_field_offset = 0usize;
701 for (v_idx, v) in data.variants.iter().enumerate() {
702 let variant_ident = &v.ident;
703
704 let construction = match &v.fields {
705 Fields::Named(fields) => {
706 let field_exprs: Vec<_> = fields
707 .named
708 .iter()
709 .map(|f| {
710 let ident = &f.ident;
711 if let Some(_behavior) = FieldBehavior::for_field(f).unwrap() {
712 let mutator_ident =
713 &mutator_ty.mutator_fields[mutator_field_offset].ident;
714 mutator_field_offset += 1;
715 quote! { #ident: self.#mutator_ident.generate(ctx)? }
716 } else {
717 quote! { #ident: Default::default() }
718 }
719 })
720 .collect();
721 quote! {
722 *value = #ty_name::#variant_ident { #( #field_exprs ),* };
723 }
724 }
725 Fields::Unnamed(fields) => {
726 let field_exprs: Vec<_> = fields
727 .unnamed
728 .iter()
729 .map(|f| {
730 if let Some(_behavior) = FieldBehavior::for_field(f).unwrap() {
731 let mutator_ident =
732 &mutator_ty.mutator_fields[mutator_field_offset].ident;
733 mutator_field_offset += 1;
734 quote! { self.#mutator_ident.generate(ctx)? }
735 } else {
736 quote! { Default::default() }
737 }
738 })
739 .collect();
740 quote! {
741 *value = #ty_name::#variant_ident( #( #field_exprs ),* );
742 }
743 }
744 Fields::Unit => {
745 quote! {
746 *value = #ty_name::#variant_ident;
747 }
748 }
749 };
750
751 variant_mutations.push((v_idx, construction));
752 }
753
754 let num_variants = data.variants.len();
755 let switch_stmts: Vec<_> = variant_mutations
756 .iter()
757 .map(|(v_idx, construction)| {
758 quote! {
759 if _variant_index != #v_idx {
760 mutations.mutation(|ctx| {
761 #construction
762 Ok(())
763 })?;
764 }
765 }
766 })
767 .collect();
768
769 quote! {
770 let _variant_index: usize = match value {
771 #( #index_arms )*
772 };
773 let _ = #num_variants;
774 #( #switch_stmts )*
775 }
776 } else {
777 quote! {}
778 };
779
780 quote! {
781 #variant_switching
782 match value {
783 #( #field_mutation_arms )*
784 }
785 }
786 }
787
788 Data::Union(_) => {
789 return Err(Error::new_spanned(
790 input,
791 "cannot `derive(Mutate)` on a union",
792 ))
793 }
794 };
795
796 let mutate_method = quote! {
797 fn mutate(
798 &mut self,
799 mutations: &mut mutatis::Candidates,
800 value: &mut #ty_name,
801 ) -> mutatis::Result<()> {
802 #mutation_body
803
804 let _ = (mutations, value);
806
807 Ok(())
808 }
809 };
810
811 let mutator_name = &mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::Generics);
812
813 Ok(quote! {
814 #[automatically_derived]
815 impl #impl_generics mutatis::Mutate<#ty_name> for #mutator_name
816 #where_clause
817 {
818 #mutate_method
819 }
820 })
821}
822
823fn gen_default_mutator_impl(
824 mutator_ty: &MutatorType,
825 container_attrs: &ContainerAttributes,
826) -> Result<TokenStream> {
827 let impl_default = container_attrs.default_mutate.unwrap_or(true);
828 if !impl_default {
829 return Ok(quote! {});
830 }
831
832 let ty_generics = if mutator_ty.ty_impl_generics.is_empty() {
833 quote! {}
834 } else {
835 let gens = &mutator_ty.ty_impl_generics;
836 quote! { < #( #gens ),* > }
837 };
838
839 let ty_name = mutator_ty.ty_name_with_generics();
840 let where_clause = mutator_ty.where_clause(WhereClauseKind::DefaultMutateBounds);
841 let mutator_name =
842 &mutator_ty.mutator_name_with_generics(MutatorNameGenericsKind::JustTyGenerics);
843
844 Ok(quote! {
845 #[automatically_derived]
846 impl #ty_generics mutatis::DefaultMutate for #ty_name
847 #where_clause
848 {
849 type DefaultMutate = #mutator_name;
850 }
851 })
852}