1 // vim: tw=80
2 //! Proc Macros for use with Mockall
3 //!
4 //! You probably don't want to use this crate directly.  Instead, you should use
5 //! its reexports via the [`mockall`](https://docs.rs/mockall/latest/mockall)
6 //! crate.
7 
8 #![cfg_attr(feature = "nightly_derive", feature(proc_macro_diagnostic))]
9 #![cfg_attr(test, deny(warnings))]
10 
11 use cfg_if::cfg_if;
12 use proc_macro2::{Span, TokenStream};
13 use quote::{ToTokens, format_ident, quote};
14 use std::{
15     env,
16     hash::BuildHasherDefault
17 };
18 use syn::{
19     *,
20     punctuated::Punctuated,
21     spanned::Spanned
22 };
23 
24 mod automock;
25 mod mock_function;
26 mod mock_item;
27 mod mock_item_struct;
28 mod mock_trait;
29 mod mockable_item;
30 mod mockable_struct;
31 use crate::automock::Attrs;
32 use crate::mockable_struct::MockableStruct;
33 use crate::mock_item::MockItem;
34 use crate::mock_item_struct::MockItemStruct;
35 use crate::mockable_item::MockableItem;
36 
37 extern crate proc_macro;
38 
39 // Define deterministic aliases for these common types.
40 type HashMap<K, V> = std::collections::HashMap<K, V, BuildHasherDefault<std::collections::hash_map::DefaultHasher>>;
41 type HashSet<K> = std::collections::HashSet<K, BuildHasherDefault<std::collections::hash_map::DefaultHasher>>;
42 
43 cfg_if! {
44     // proc-macro2's Span::unstable method requires the nightly feature, and it
45     // doesn't work in test mode.
46     // https://github.com/alexcrichton/proc-macro2/issues/159
47     if #[cfg(all(feature = "nightly_derive", not(test)))] {
48         fn compile_error(span: Span, msg: &str) {
49             span.unstable()
50                 .error(msg)
51                 .emit();
52         }
53     } else {
54         fn compile_error(_span: Span, msg: &str) {
55             panic!("{msg}.  More information may be available when mockall is built with the \"nightly\" feature.");
56         }
57     }
58 }
59 
60 /// Does this Attribute represent Mockall's "concretize" pseudo-attribute?
is_concretize(attr: &Attribute) -> bool61 fn is_concretize(attr: &Attribute) -> bool {
62     if attr.path().segments.last().unwrap().ident == "concretize" {
63         true
64     } else if attr.path().is_ident("cfg_attr") {
65         match &attr.meta {
66             Meta::List(ml) => {
67                 ml.tokens.to_string().contains("concretize")
68             },
69             // cfg_attr should always contain a list
70             _ => false,
71         }
72     } else {
73         false
74     }
75 }
76 
77 /// replace generic arguments with concrete trait object arguments
concretize_args(gen: &Generics, args: &Punctuated<FnArg, Token![,]>) -> (Generics, Vec<FnArg>, Vec<TokenStream>)78 fn concretize_args(gen: &Generics, args: &Punctuated<FnArg, Token![,]>) ->
79     (Generics, Vec<FnArg>, Vec<TokenStream>)
80 {
81     let mut hm = HashMap::default();
82 
83     let mut save_types = |ident: &Ident, tpb: &Punctuated<TypeParamBound, Token![+]>| {
84         if !tpb.is_empty() {
85             if let Ok(newty) = parse2::<Type>(quote!(&(dyn #tpb))) {
86                 // substitute T arguments
87                 let subst_ty: Type = parse2(quote!(#ident)).unwrap();
88                 hm.insert(subst_ty, (newty.clone(), None));
89 
90                 // substitute &T arguments
91                 let subst_ty: Type = parse2(quote!(&#ident)).unwrap();
92                 hm.insert(subst_ty, (newty, None));
93             } else {
94                 compile_error(tpb.span(),
95                     "Type cannot be made into a trait object");
96             }
97 
98             if let Ok(newty) = parse2::<Type>(quote!(&mut (dyn #tpb))) {
99                 // substitute &mut T arguments
100                 let subst_ty: Type = parse2(quote!(&mut #ident)).unwrap();
101                 hm.insert(subst_ty, (newty, None));
102             } else {
103                 compile_error(tpb.span(),
104                     "Type cannot be made into a trait object");
105             }
106 
107             // I wish we could substitute &[T] arguments.  But there's no way
108             // for the mock method to turn &[T] into &[&dyn T].
109             if let Ok(newty) = parse2::<Type>(quote!(&[&(dyn #tpb)])) {
110                 let subst_ty: Type = parse2(quote!(&[#ident])).unwrap();
111                 hm.insert(subst_ty, (newty, Some(tpb.clone())));
112             } else {
113                 compile_error(tpb.span(),
114                     "Type cannot be made into a trait object");
115             }
116         }
117     };
118 
119     for g in gen.params.iter() {
120         if let GenericParam::Type(tp) = g {
121             save_types(&tp.ident, &tp.bounds);
122             // else there had better be a where clause
123         }
124     }
125     if let Some(wc) = &gen.where_clause {
126         for pred in wc.predicates.iter() {
127             if let WherePredicate::Type(pt) = pred {
128                 let bounded_ty = &pt.bounded_ty;
129                 if let Ok(ident) = parse2::<Ident>(quote!(#bounded_ty)) {
130                     save_types(&ident, &pt.bounds);
131                 } else {
132                     // We can't yet handle where clauses this complicated
133                 }
134             }
135         }
136     }
137 
138     let outg = Generics {
139         lt_token: None,
140         gt_token: None,
141         params: Punctuated::new(),
142         where_clause: None
143     };
144     let outargs: Vec<FnArg> = args.iter().map(|arg| {
145         if let FnArg::Typed(pt) = arg {
146             let mut immutable_pt = pt.clone();
147             demutify_arg(&mut immutable_pt);
148             if let Some((newty, _)) = hm.get(&pt.ty) {
149                 FnArg::Typed(PatType {
150                     attrs: Vec::default(),
151                     pat: immutable_pt.pat,
152                     colon_token: pt.colon_token,
153                     ty: Box::new(newty.clone())
154                 })
155             } else {
156                 FnArg::Typed(PatType {
157                     attrs: Vec::default(),
158                     pat: immutable_pt.pat,
159                     colon_token: pt.colon_token,
160                     ty: pt.ty.clone()
161                 })
162             }
163         } else {
164             arg.clone()
165         }
166     }).collect();
167 
168     // Finally, Reference any concretizing arguments
169     // use filter_map to remove the &self argument
170     let call_exprs = args.iter().filter_map(|arg| {
171         match arg {
172             FnArg::Typed(pt) => {
173                 let mut pt2 = pt.clone();
174                 demutify_arg(&mut pt2);
175                 let pat = &pt2.pat;
176                 if pat_is_self(pat) {
177                     None
178                 } else if let Some((_, newbound)) = hm.get(&pt.ty) {
179                     if let Type::Reference(tr) = &*pt.ty {
180                         if let Type::Slice(_ts) = &*tr.elem {
181                             // Assume _ts is the generic type or we wouldn't be
182                             // here
183                             Some(quote!(
184                                 &(0..#pat.len())
185                                 .map(|__mockall_i| &#pat[__mockall_i] as &(dyn #newbound))
186                                 .collect::<Vec<_>>()
187                             ))
188                         } else {
189                             Some(quote!(#pat))
190                         }
191                     } else {
192                         Some(quote!(&#pat))
193                     }
194                 } else {
195                     Some(quote!(#pat))
196                 }
197             },
198             FnArg::Receiver(_) => None,
199         }
200     }).collect();
201     (outg, outargs, call_exprs)
202 }
203 
deanonymize_lifetime(lt: &mut Lifetime)204 fn deanonymize_lifetime(lt: &mut Lifetime) {
205     if lt.ident == "_" {
206         lt.ident = format_ident!("static");
207     }
208 }
209 
deanonymize_path(path: &mut Path)210 fn deanonymize_path(path: &mut Path) {
211     for seg in path.segments.iter_mut() {
212         match &mut seg.arguments {
213             PathArguments::None => (),
214             PathArguments::AngleBracketed(abga) => {
215                 for ga in abga.args.iter_mut() {
216                     if let GenericArgument::Lifetime(lt) = ga {
217                         deanonymize_lifetime(lt)
218                     }
219                 }
220             },
221             _ => compile_error(seg.arguments.span(),
222                 "Methods returning functions are TODO"),
223         }
224     }
225 }
226 
227 /// Replace any references to the anonymous lifetime `'_` with `'static`.
deanonymize(literal_type: &mut Type)228 fn deanonymize(literal_type: &mut Type) {
229     match literal_type {
230         Type::Array(ta) => deanonymize(ta.elem.as_mut()),
231         Type::BareFn(tbf) => {
232             if let ReturnType::Type(_, ref mut bt) = tbf.output {
233                 deanonymize(bt.as_mut());
234             }
235             for input in tbf.inputs.iter_mut() {
236                 deanonymize(&mut input.ty);
237             }
238         },
239         Type::Group(tg) => deanonymize(tg.elem.as_mut()),
240         Type::Infer(_) => (),
241         Type::Never(_) => (),
242         Type::Paren(tp) => deanonymize(tp.elem.as_mut()),
243         Type::Path(tp) => {
244             if let Some(ref mut qself) = tp.qself {
245                 deanonymize(qself.ty.as_mut());
246             }
247             deanonymize_path(&mut tp.path);
248         },
249         Type::Ptr(tptr) => deanonymize(tptr.elem.as_mut()),
250         Type::Reference(tr) => {
251             if let Some(lt) = tr.lifetime.as_mut() {
252                 deanonymize_lifetime(lt)
253             }
254             deanonymize(tr.elem.as_mut());
255         },
256         Type::Slice(s) => deanonymize(s.elem.as_mut()),
257         Type::TraitObject(tto) => {
258             for tpb in tto.bounds.iter_mut() {
259                 match tpb {
260                     TypeParamBound::Trait(tb) => deanonymize_path(&mut tb.path),
261                     TypeParamBound::Lifetime(lt) => deanonymize_lifetime(lt),
262                     _ => ()
263                 }
264             }
265         },
266         Type::Tuple(tt) => {
267             for ty in tt.elems.iter_mut() {
268                 deanonymize(ty)
269             }
270         }
271         x => compile_error(x.span(), "Unimplemented type for deanonymize")
272     }
273 }
274 
275 // If there are any closures in the argument list, turn them into boxed
276 // functions
declosurefy(gen: &Generics, args: &Punctuated<FnArg, Token![,]>) -> (Generics, Vec<FnArg>, Vec<TokenStream>)277 fn declosurefy(gen: &Generics, args: &Punctuated<FnArg, Token![,]>) ->
278     (Generics, Vec<FnArg>, Vec<TokenStream>)
279 {
280     let mut hm = HashMap::default();
281 
282     let mut save_fn_types = |ident: &Ident, tpb: &TypeParamBound| {
283         if let TypeParamBound::Trait(tb) = tpb {
284             let fident = &tb.path.segments.last().unwrap().ident;
285             if ["Fn", "FnMut", "FnOnce"].iter().any(|s| fident == *s) {
286                 let newty: Type = parse2(quote!(Box<dyn #tb>)).unwrap();
287                 let subst_ty: Type = parse2(quote!(#ident)).unwrap();
288                 assert!(hm.insert(subst_ty, newty).is_none(),
289                     "A generic parameter had two Fn bounds?");
290             }
291         }
292     };
293 
294     // First, build a HashMap of all Fn generic types
295     for g in gen.params.iter() {
296         if let GenericParam::Type(tp) = g {
297             for tpb in tp.bounds.iter() {
298                 save_fn_types(&tp.ident, tpb);
299             }
300         }
301     }
302     if let Some(wc) = &gen.where_clause {
303         for pred in wc.predicates.iter() {
304             if let WherePredicate::Type(pt) = pred {
305                 let bounded_ty = &pt.bounded_ty;
306                 if let Ok(ident) = parse2::<Ident>(quote!(#bounded_ty)) {
307                     for tpb in pt.bounds.iter() {
308                         save_fn_types(&ident, tpb);
309                     }
310                 } else {
311                     // We can't yet handle where clauses this complicated
312                 }
313             }
314         }
315     }
316 
317     // Then remove those types from both the Generics' params and where clause
318     let should_remove = |ident: &Ident| {
319             let ty: Type = parse2(quote!(#ident)).unwrap();
320             hm.contains_key(&ty)
321     };
322     let params = gen.params.iter()
323         .filter(|g| {
324             if let GenericParam::Type(tp) = g {
325                 !should_remove(&tp.ident)
326             } else {
327                 true
328             }
329         }).cloned()
330         .collect::<Punctuated<_, _>>();
331     let mut wc2 = gen.where_clause.clone();
332     if let Some(wc) = &mut wc2 {
333         wc.predicates = wc.predicates.iter()
334             .filter(|wp| {
335                 if let WherePredicate::Type(pt) = wp {
336                     let bounded_ty = &pt.bounded_ty;
337                     if let Ok(ident) = parse2::<Ident>(quote!(#bounded_ty)) {
338                         !should_remove(&ident)
339                     } else {
340                         // We can't yet handle where clauses this complicated
341                         true
342                     }
343                 } else {
344                     true
345                 }
346             }).cloned()
347             .collect::<Punctuated<_, _>>();
348         if wc.predicates.is_empty() {
349             wc2 = None;
350         }
351     }
352     let outg = Generics {
353         lt_token: if params.is_empty() { None } else { gen.lt_token },
354         gt_token: if params.is_empty() { None } else { gen.gt_token },
355         params,
356         where_clause: wc2
357     };
358 
359     // Next substitute Box<Fn> into the arguments
360     let outargs = args.iter().map(|arg| {
361         if let FnArg::Typed(pt) = arg {
362             let mut immutable_pt = pt.clone();
363             demutify_arg(&mut immutable_pt);
364             if let Some(newty) = hm.get(&pt.ty) {
365                 FnArg::Typed(PatType {
366                     attrs: Vec::default(),
367                     pat: immutable_pt.pat,
368                     colon_token: pt.colon_token,
369                     ty: Box::new(newty.clone())
370                 })
371             } else {
372                 FnArg::Typed(PatType {
373                     attrs: Vec::default(),
374                     pat: immutable_pt.pat,
375                     colon_token: pt.colon_token,
376                     ty: pt.ty.clone()
377                 })
378             }
379         } else {
380             arg.clone()
381         }
382     }).collect();
383 
384     // Finally, Box any closure arguments
385     // use filter_map to remove the &self argument
386     let callargs = args.iter().filter_map(|arg| {
387         match arg {
388             FnArg::Typed(pt) => {
389                 let mut pt2 = pt.clone();
390                 demutify_arg(&mut pt2);
391                 let pat = &pt2.pat;
392                 if pat_is_self(pat) {
393                     None
394                 } else if hm.contains_key(&pt.ty) {
395                     Some(quote!(Box::new(#pat)))
396                 } else {
397                     Some(quote!(#pat))
398                 }
399             },
400             FnArg::Receiver(_) => None,
401         }
402     }).collect();
403     (outg, outargs, callargs)
404 }
405 
406 /// Replace any "impl trait" types with "Box<dyn trait>" or equivalent.
deimplify(rt: &mut ReturnType)407 fn deimplify(rt: &mut ReturnType) {
408     if let ReturnType::Type(_, ty) = rt {
409         if let Type::ImplTrait(ref tit) = &**ty {
410             let needs_pin = tit.bounds
411                 .iter()
412                 .any(|tpb| {
413                     if let TypeParamBound::Trait(tb) = tpb {
414                         if let Some(seg) = tb.path.segments.last() {
415                             seg.ident == "Future" || seg.ident == "Stream"
416                         } else {
417                             // It might still be a Future, but we can't guess
418                             // what names it might be imported under.  Too bad.
419                             false
420                         }
421                     } else {
422                         false
423                     }
424                 });
425             let bounds = &tit.bounds;
426             if needs_pin {
427                 *ty = parse2(quote!(::std::pin::Pin<Box<dyn #bounds>>)).unwrap();
428             } else {
429                 *ty = parse2(quote!(Box<dyn #bounds>)).unwrap();
430             }
431         }
432     }
433 }
434 
435 /// Remove any generics that place constraints on Self.
dewhereselfify(generics: &mut Generics)436 fn dewhereselfify(generics: &mut Generics) {
437     if let Some(ref mut wc) = &mut generics.where_clause {
438         let new_predicates = wc.predicates.iter()
439             .filter(|wp| match wp {
440                 WherePredicate::Type(pt) => {
441                     pt.bounded_ty != parse2(quote!(Self)).unwrap()
442                 },
443                 _ => true
444             }).cloned()
445             .collect::<Punctuated<WherePredicate, Token![,]>>();
446         wc.predicates = new_predicates;
447     }
448     if generics.where_clause.as_ref()
449         .map(|wc| wc.predicates.is_empty())
450         .unwrap_or(false)
451     {
452         generics.where_clause = None;
453     }
454 }
455 
456 /// Remove any mutability qualifiers from a method's argument list
demutify(inputs: &mut Punctuated<FnArg, token::Comma>)457 fn demutify(inputs: &mut Punctuated<FnArg, token::Comma>) {
458     for arg in inputs.iter_mut() {
459         match arg {
460             FnArg::Receiver(r) => if r.reference.is_none() {
461                 r.mutability = None
462             },
463             FnArg::Typed(pt) => demutify_arg(pt),
464         }
465     }
466 }
467 
468 /// Remove any "mut" from a method argument's binding.
demutify_arg(arg: &mut PatType)469 fn demutify_arg(arg: &mut PatType) {
470     match *arg.pat {
471         Pat::Wild(_) => {
472             compile_error(arg.span(),
473                 "Mocked methods must have named arguments");
474         },
475         Pat::Ident(ref mut pat_ident) => {
476             if let Some(r) = &pat_ident.by_ref {
477                 compile_error(r.span(),
478                     "Mockall does not support by-reference argument bindings");
479             }
480             if let Some((_at, subpat)) = &pat_ident.subpat {
481                 compile_error(subpat.span(),
482                     "Mockall does not support subpattern bindings");
483             }
484             pat_ident.mutability = None;
485         },
486         _ => {
487             compile_error(arg.span(), "Unsupported argument type");
488         }
489     };
490 }
491 
deselfify_path(path: &mut Path, actual: &Ident, generics: &Generics)492 fn deselfify_path(path: &mut Path, actual: &Ident, generics: &Generics) {
493     for seg in path.segments.iter_mut() {
494         if seg.ident == "Self" {
495             seg.ident = actual.clone();
496             if let PathArguments::None = seg.arguments {
497                 if !generics.params.is_empty() {
498                     let args = generics.params.iter()
499                         .map(|gp| {
500                             match gp {
501                                 GenericParam::Type(tp) => {
502                                     let ident = tp.ident.clone();
503                                     GenericArgument::Type(
504                                         Type::Path(
505                                             TypePath {
506                                                 qself: None,
507                                                 path: Path::from(ident)
508                                             }
509                                         )
510                                     )
511                                 },
512                                 GenericParam::Lifetime(ld) =>{
513                                     GenericArgument::Lifetime(
514                                         ld.lifetime.clone()
515                                     )
516                                 }
517                                 _ => unimplemented!(),
518                             }
519                         }).collect::<Punctuated<_, _>>();
520                     seg.arguments = PathArguments::AngleBracketed(
521                         AngleBracketedGenericArguments {
522                             colon2_token: None,
523                             lt_token: generics.lt_token.unwrap(),
524                             args,
525                             gt_token: generics.gt_token.unwrap(),
526                         }
527                     );
528                 }
529             } else {
530                 compile_error(seg.arguments.span(),
531                     "Type arguments after Self are unexpected");
532             }
533         }
534         if let PathArguments::AngleBracketed(abga) = &mut seg.arguments
535         {
536             for arg in abga.args.iter_mut() {
537                 match arg {
538                     GenericArgument::Type(ty) =>
539                         deselfify(ty, actual, generics),
540                     GenericArgument::AssocType(at) =>
541                         deselfify(&mut at.ty, actual, generics),
542                     _ => /* Nothing to do */(),
543                 }
544             }
545         }
546     }
547 }
548 
549 /// Replace any references to `Self` in `literal_type` with `actual`.
550 /// `generics` is the Generics field of the parent struct.  Useful for
551 /// constructor methods.
deselfify(literal_type: &mut Type, actual: &Ident, generics: &Generics)552 fn deselfify(literal_type: &mut Type, actual: &Ident, generics: &Generics) {
553     match literal_type {
554         Type::Slice(s) => {
555             deselfify(s.elem.as_mut(), actual, generics);
556         },
557         Type::Array(a) => {
558             deselfify(a.elem.as_mut(), actual, generics);
559         },
560         Type::Ptr(p) => {
561             deselfify(p.elem.as_mut(), actual, generics);
562         },
563         Type::Reference(r) => {
564             deselfify(r.elem.as_mut(), actual, generics);
565         },
566         Type::Tuple(tuple) => {
567             for elem in tuple.elems.iter_mut() {
568                 deselfify(elem, actual, generics);
569             }
570         }
571         Type::Path(type_path) => {
572             if let Some(ref mut qself) = type_path.qself {
573                 deselfify(qself.ty.as_mut(), actual, generics);
574             }
575             deselfify_path(&mut type_path.path, actual, generics);
576         },
577         Type::Paren(p) => {
578             deselfify(p.elem.as_mut(), actual, generics);
579         },
580         Type::Group(g) => {
581             deselfify(g.elem.as_mut(), actual, generics);
582         },
583         Type::Macro(_) | Type::Verbatim(_) => {
584             compile_error(literal_type.span(),
585                 "mockall_derive does not support this type as a return argument");
586         },
587         Type::TraitObject(tto) => {
588             // Change types like `dyn Self` into `dyn MockXXX`.
589             for bound in tto.bounds.iter_mut() {
590                 if let TypeParamBound::Trait(t) = bound {
591                     deselfify_path(&mut t.path, actual, generics);
592                 }
593             }
594         },
595         Type::ImplTrait(_) => {
596             /* Should've already been flagged as a compile_error */
597         },
598         Type::BareFn(_) => {
599             /* Bare functions can't have Self arguments.  Nothing to do */
600         },
601         Type::Infer(_) | Type::Never(_) =>
602         {
603             /* Nothing to do */
604         },
605         _ => compile_error(literal_type.span(), "Unsupported type"),
606     }
607 }
608 
609 /// Change any `Self` in a method's arguments' types with `actual`.
610 /// `generics` is the Generics field of the parent struct.
deselfify_args( args: &mut Punctuated<FnArg, Token![,]>, actual: &Ident, generics: &Generics)611 fn deselfify_args(
612     args: &mut Punctuated<FnArg, Token![,]>,
613     actual: &Ident,
614     generics: &Generics)
615 {
616     for arg in args.iter_mut() {
617         match arg {
618             FnArg::Receiver(r) => {
619                 if r.colon_token.is_some() {
620                     deselfify(r.ty.as_mut(), actual, generics)
621                 }
622             },
623             FnArg::Typed(pt) => deselfify(pt.ty.as_mut(), actual, generics)
624         }
625     }
626 }
627 
find_ident_from_path(path: &Path) -> (Ident, PathArguments)628 fn find_ident_from_path(path: &Path) -> (Ident, PathArguments) {
629     if path.segments.len() != 1 {
630         compile_error(path.span(),
631             "mockall_derive only supports structs defined in the current module");
632         return (Ident::new("", path.span()), PathArguments::None);
633     }
634     let last_seg = path.segments.last().unwrap();
635     (last_seg.ident.clone(), last_seg.arguments.clone())
636 }
637 
find_lifetimes_in_tpb(bound: &TypeParamBound) -> HashSet<Lifetime>638 fn find_lifetimes_in_tpb(bound: &TypeParamBound) -> HashSet<Lifetime> {
639     let mut ret = HashSet::default();
640     match bound {
641         TypeParamBound::Lifetime(lt) => {
642             ret.insert(lt.clone());
643         },
644         TypeParamBound::Trait(tb) => {
645             ret.extend(find_lifetimes_in_path(&tb.path));
646         },
647         _ => ()
648     };
649     ret
650 }
651 
find_lifetimes_in_path(path: &Path) -> HashSet<Lifetime>652 fn find_lifetimes_in_path(path: &Path) -> HashSet<Lifetime> {
653     let mut ret = HashSet::default();
654     for seg in path.segments.iter() {
655         if let PathArguments::AngleBracketed(abga) = &seg.arguments {
656             for arg in abga.args.iter() {
657                 match arg {
658                     GenericArgument::Lifetime(lt) => {
659                         ret.insert(lt.clone());
660                     },
661                     GenericArgument::Type(ty) => {
662                         ret.extend(find_lifetimes(ty));
663                     },
664                     GenericArgument::AssocType(at) => {
665                         ret.extend(find_lifetimes(&at.ty));
666                     },
667                     GenericArgument::Constraint(c) => {
668                         for bound in c.bounds.iter() {
669                             ret.extend(find_lifetimes_in_tpb(bound));
670                         }
671                     },
672                     GenericArgument::Const(_) => (),
673                     _ => ()
674                 }
675             }
676         }
677     }
678     ret
679 }
680 
find_lifetimes(ty: &Type) -> HashSet<Lifetime>681 fn find_lifetimes(ty: &Type) -> HashSet<Lifetime> {
682     match ty {
683         Type::Array(ta) => find_lifetimes(ta.elem.as_ref()),
684         Type::Group(tg) => find_lifetimes(tg.elem.as_ref()),
685         Type::Infer(_ti) => HashSet::default(),
686         Type::Never(_tn) => HashSet::default(),
687         Type::Paren(tp) => find_lifetimes(tp.elem.as_ref()),
688         Type::Path(tp) => {
689             let mut ret = find_lifetimes_in_path(&tp.path);
690             if let Some(qs) = &tp.qself {
691                 ret.extend(find_lifetimes(qs.ty.as_ref()));
692             }
693             ret
694         },
695         Type::Ptr(tp) => find_lifetimes(tp.elem.as_ref()),
696         Type::Reference(tr) => {
697             let mut ret = find_lifetimes(tr.elem.as_ref());
698             if let Some(lt) = &tr.lifetime {
699                 ret.insert(lt.clone());
700             }
701             ret
702         },
703         Type::Slice(ts) => find_lifetimes(ts.elem.as_ref()),
704         Type::TraitObject(tto) => {
705             let mut ret = HashSet::default();
706             for bound in tto.bounds.iter() {
707                 ret.extend(find_lifetimes_in_tpb(bound));
708             }
709             ret
710         }
711         Type::Tuple(tt) => {
712             let mut ret = HashSet::default();
713             for ty in tt.elems.iter() {
714                 ret.extend(find_lifetimes(ty));
715             }
716             ret
717         },
718         Type::ImplTrait(tit) => {
719             let mut ret = HashSet::default();
720             for tpb in tit.bounds.iter() {
721                 ret.extend(find_lifetimes_in_tpb(tpb));
722             }
723             ret
724         },
725         _ => {
726             compile_error(ty.span(), "unsupported type in this context");
727             HashSet::default()
728         }
729     }
730 }
731 
732 
733 struct AttrFormatter<'a>{
734     attrs: &'a [Attribute],
735     async_trait: bool,
736     doc: bool,
737 }
738 
739 impl<'a> AttrFormatter<'a> {
new(attrs: &'a [Attribute]) -> AttrFormatter<'a>740     fn new(attrs: &'a [Attribute]) -> AttrFormatter<'a> {
741         Self {
742             attrs,
743             async_trait: true,
744             doc: true
745         }
746     }
747 
async_trait(&mut self, allowed: bool) -> &mut Self748     fn async_trait(&mut self, allowed: bool) -> &mut Self {
749         self.async_trait = allowed;
750         self
751     }
752 
doc(&mut self, allowed: bool) -> &mut Self753     fn doc(&mut self, allowed: bool) -> &mut Self {
754         self.doc = allowed;
755         self
756     }
757 
758     // XXX This logic requires that attributes are imported with their
759     // standard names.
760     #[allow(clippy::needless_bool)]
761     #[allow(clippy::if_same_then_else)]
format(&mut self) -> Vec<Attribute>762     fn format(&mut self) -> Vec<Attribute> {
763         self.attrs.iter()
764             .filter(|attr| {
765                 let i = attr.path().segments.last().map(|ps| &ps.ident);
766                 if is_concretize(attr) {
767                     // Internally used attribute.  Never emit.
768                     false
769                 } else if i.is_none() {
770                     false
771                 } else if *i.as_ref().unwrap() == "derive" {
772                     // We can't usefully derive any traits.  Ignore them
773                     false
774                 } else if *i.as_ref().unwrap() == "doc" {
775                     self.doc
776                 } else if *i.as_ref().unwrap() == "async_trait" {
777                     self.async_trait
778                 } else if *i.as_ref().unwrap() == "instrument" {
779                     // We can't usefully instrument the mock method, so just
780                     // ignore this attribute.
781                     // https://docs.rs/tracing/0.1.23/tracing/attr.instrument.html
782                     false
783                 } else if *i.as_ref().unwrap() == "link_name" {
784                     // This shows up sometimes when mocking ffi functions.  We
785                     // must not emit it on anything that isn't an ffi definition
786                     false
787                 } else {
788                     true
789                 }
790             }).cloned()
791             .collect()
792     }
793 }
794 
795 /// Determine if this Pat is any kind of `self` binding
pat_is_self(pat: &Pat) -> bool796 fn pat_is_self(pat: &Pat) -> bool {
797     if let Pat::Ident(pi) = pat {
798         pi.ident == "self"
799     } else {
800         false
801     }
802 }
803 
804 /// Add `levels` `super::` to the path.  Return the number of levels added.
supersuperfy_path(path: &mut Path, levels: usize) -> usize805 fn supersuperfy_path(path: &mut Path, levels: usize) -> usize {
806     if let Some(t) = path.segments.last_mut() {
807         match &mut t.arguments {
808             PathArguments::None => (),
809             PathArguments::AngleBracketed(ref mut abga) => {
810                 for arg in abga.args.iter_mut() {
811                     match arg {
812                         GenericArgument::Type(ref mut ty) => {
813                             *ty = supersuperfy(ty, levels);
814                         },
815                         GenericArgument::AssocType(ref mut at) => {
816                             at.ty = supersuperfy(&at.ty, levels);
817                         },
818                         GenericArgument::Constraint(ref mut constraint) => {
819                             supersuperfy_bounds(&mut constraint.bounds, levels);
820                         },
821                         _ => (),
822                     }
823                 }
824             },
825             PathArguments::Parenthesized(ref mut pga) => {
826                 for input in pga.inputs.iter_mut() {
827                     *input = supersuperfy(input, levels);
828                 }
829                 if let ReturnType::Type(_, ref mut ty) = pga.output {
830                     *ty = Box::new(supersuperfy(ty, levels));
831                 }
832             },
833         }
834     }
835     if let Some(t) = path.segments.first() {
836         if t.ident == "super" {
837             let mut ident = format_ident!("super");
838             ident.set_span(path.segments.span());
839             let ps = PathSegment {
840                 ident,
841                 arguments: PathArguments::None
842             };
843             for _ in 0..levels {
844                 path.segments.insert(0, ps.clone());
845             }
846             levels
847         } else {
848             0
849         }
850     } else {
851         0
852     }
853 }
854 
855 /// Replace any references to `super::X` in `original` with `super::super::X`.
supersuperfy(original: &Type, levels: usize) -> Type856 fn supersuperfy(original: &Type, levels: usize) -> Type {
857     let mut output = original.clone();
858     fn recurse(t: &mut Type, levels: usize) {
859         match t {
860             Type::Slice(s) => {
861                 recurse(s.elem.as_mut(), levels);
862             },
863             Type::Array(a) => {
864                 recurse(a.elem.as_mut(), levels);
865             },
866             Type::Ptr(p) => {
867                 recurse(p.elem.as_mut(), levels);
868             },
869             Type::Reference(r) => {
870                 recurse(r.elem.as_mut(), levels);
871             },
872             Type::BareFn(bfn) => {
873                 if let ReturnType::Type(_, ref mut bt) = bfn.output {
874                     recurse(bt.as_mut(), levels);
875                 }
876                 for input in bfn.inputs.iter_mut() {
877                     recurse(&mut input.ty, levels);
878                 }
879             },
880             Type::Tuple(tuple) => {
881                 for elem in tuple.elems.iter_mut() {
882                     recurse(elem, levels);
883                 }
884             }
885             Type::Path(type_path) => {
886                 let added = supersuperfy_path(&mut type_path.path, levels);
887                 if let Some(ref mut qself) = type_path.qself {
888                     recurse(qself.ty.as_mut(), levels);
889                     qself.position += added;
890                 }
891             },
892             Type::Paren(p) => {
893                 recurse(p.elem.as_mut(), levels);
894             },
895             Type::Group(g) => {
896                 recurse(g.elem.as_mut(), levels);
897             },
898             Type::Macro(_) | Type::Verbatim(_) => {
899                 compile_error(t.span(),
900                     "mockall_derive does not support this type in this position");
901             },
902             Type::TraitObject(tto) => {
903                 for bound in tto.bounds.iter_mut() {
904                     if let TypeParamBound::Trait(tb) = bound {
905                         supersuperfy_path(&mut tb.path, levels);
906                     }
907                 }
908             },
909             Type::ImplTrait(_) => {
910                 /* Should've already been flagged as a compile error */
911             },
912             Type::Infer(_) | Type::Never(_) =>
913             {
914                 /* Nothing to do */
915             },
916             _ => compile_error(t.span(), "Unsupported type"),
917         }
918     }
919     recurse(&mut output, levels);
920     output
921 }
922 
supersuperfy_generics(generics: &mut Generics, levels: usize)923 fn supersuperfy_generics(generics: &mut Generics, levels: usize) {
924     for param in generics.params.iter_mut() {
925         if let GenericParam::Type(tp) = param {
926             supersuperfy_bounds(&mut tp.bounds, levels);
927             if let Some(ty) = tp.default.as_mut() {
928                 *ty = supersuperfy(ty, levels);
929             }
930         }
931     }
932     if let Some(wc) = generics.where_clause.as_mut() {
933         for wp in wc.predicates.iter_mut() {
934             if let WherePredicate::Type(pt) = wp {
935                 pt.bounded_ty = supersuperfy(&pt.bounded_ty, levels);
936                 supersuperfy_bounds(&mut pt.bounds, levels);
937             }
938         }
939     }
940 }
941 
supersuperfy_bounds( bounds: &mut Punctuated<TypeParamBound, Token![+]>, levels: usize)942 fn supersuperfy_bounds(
943     bounds: &mut Punctuated<TypeParamBound, Token![+]>,
944     levels: usize)
945 {
946     for bound in bounds.iter_mut() {
947         if let TypeParamBound::Trait(tb) = bound {
948             supersuperfy_path(&mut tb.path, levels);
949         }
950     }
951 }
952 
953 /// Generate a suitable mockall::Key generic paramter from any Generics
gen_keyid(g: &Generics) -> impl ToTokens954 fn gen_keyid(g: &Generics) -> impl ToTokens {
955     match g.params.len() {
956         0 => quote!(<()>),
957         1 => {
958             let (_, tg, _) = g.split_for_impl();
959             quote!(#tg)
960         },
961         _ => {
962             // Rust doesn't support variadic Generics, so mockall::Key must
963             // always have exactly one generic type.  We need to add parentheses
964             // around whatever type generics the caller passes.
965             let tps = g.type_params()
966             .map(|tp| tp.ident.clone())
967             .collect::<Punctuated::<Ident, Token![,]>>();
968             quote!(<(#tps)>)
969         }
970     }
971 }
972 
973 /// Generate a mock identifier from the regular one: eg "Foo" => "MockFoo"
gen_mock_ident(ident: &Ident) -> Ident974 fn gen_mock_ident(ident: &Ident) -> Ident {
975     format_ident!("Mock{}", ident)
976 }
977 
978 /// Generate an identifier for the mock struct's private module: eg "Foo" =>
979 /// "__mock_Foo"
gen_mod_ident(struct_: &Ident, trait_: Option<&Ident>) -> Ident980 fn gen_mod_ident(struct_: &Ident, trait_: Option<&Ident>) -> Ident {
981     if let Some(t) = trait_ {
982         format_ident!("__mock_{struct_}_{}", t)
983     } else {
984         format_ident!("__mock_{struct_}")
985     }
986 }
987 
988 /// Combine two Generics structs, producing a new one that has the union of
989 /// their parameters.
merge_generics(x: &Generics, y: &Generics) -> Generics990 fn merge_generics(x: &Generics, y: &Generics) -> Generics {
991     /// Compare only the identifiers of two GenericParams
992     fn cmp_gp_idents(x: &GenericParam, y: &GenericParam) -> bool {
993         use GenericParam::*;
994 
995         match (x, y) {
996             (Type(xtp), Type(ytp)) => xtp.ident == ytp.ident,
997             (Lifetime(xld), Lifetime(yld)) => xld.lifetime == yld.lifetime,
998             (Const(xc), Const(yc)) => xc.ident == yc.ident,
999             _ => false
1000         }
1001     }
1002 
1003     /// Compare only the identifiers of two WherePredicates
1004     fn cmp_wp_idents(x: &WherePredicate, y: &WherePredicate) -> bool {
1005         use WherePredicate::*;
1006 
1007         match (x, y) {
1008             (Type(xpt), Type(ypt)) => xpt.bounded_ty == ypt.bounded_ty,
1009             (Lifetime(xpl), Lifetime(ypl)) => xpl.lifetime == ypl.lifetime,
1010             _ => false
1011         }
1012     }
1013 
1014     let mut out = if x.lt_token.is_none() && x.where_clause.is_none() {
1015         y.clone()
1016     } else if y.lt_token.is_none() && y.where_clause.is_none() {
1017         x.clone()
1018     } else {
1019         let mut out = x.clone();
1020         // First merge the params
1021         'outer_param: for yparam in y.params.iter() {
1022             // XXX: O(n^2) loop
1023             for outparam in out.params.iter_mut() {
1024                 if cmp_gp_idents(outparam, yparam) {
1025                     if let (GenericParam::Type(ref mut ot),
1026                             GenericParam::Type(yt)) = (outparam, yparam)
1027                     {
1028                         ot.attrs.extend(yt.attrs.iter().cloned());
1029                         ot.colon_token = ot.colon_token.or(yt.colon_token);
1030                         ot.eq_token = ot.eq_token.or(yt.eq_token);
1031                         if ot.default.is_none() {
1032                             ot.default = yt.default.clone();
1033                         }
1034                         // XXX this might result in duplicate bounds
1035                         if ot.bounds != yt.bounds {
1036                             ot.bounds.extend(yt.bounds.iter().cloned());
1037                         }
1038                     }
1039                     continue 'outer_param;
1040                 }
1041             }
1042             out.params.push(yparam.clone());
1043         }
1044         out
1045     };
1046     // Then merge the where clauses
1047     match (&mut out.where_clause, &y.where_clause) {
1048         (_, None) => (),
1049         (None, Some(wc)) => out.where_clause = Some(wc.clone()),
1050         (Some(out_wc), Some(y_wc)) => {
1051             'outer_wc: for ypred in y_wc.predicates.iter() {
1052                 // XXX: O(n^2) loop
1053                 for outpred in out_wc.predicates.iter_mut() {
1054                     if cmp_wp_idents(outpred, ypred) {
1055                         if let (WherePredicate::Type(ref mut ot),
1056                                 WherePredicate::Type(yt)) = (outpred, ypred)
1057                         {
1058                             match (&mut ot.lifetimes, &yt.lifetimes) {
1059                                 (_, None) => (),
1060                                 (None, Some(bl)) =>
1061                                     ot.lifetimes = Some(bl.clone()),
1062                                 (Some(obl), Some(ybl)) =>
1063                                     // XXX: might result in duplicates
1064                                     obl.lifetimes.extend(
1065                                         ybl.lifetimes.iter().cloned()),
1066                             };
1067                             // XXX: might result in duplicate bounds
1068                             if ot.bounds != yt.bounds {
1069                                 ot.bounds.extend(yt.bounds.iter().cloned())
1070                             }
1071                         }
1072                         continue 'outer_wc;
1073                     }
1074                 }
1075                 out_wc.predicates.push(ypred.clone());
1076             }
1077         }
1078     }
1079     out
1080 }
1081 
lifetimes_to_generic_params(lv: &Punctuated<LifetimeParam, Token![,]>) -> Punctuated<GenericParam, Token![,]>1082 fn lifetimes_to_generic_params(lv: &Punctuated<LifetimeParam, Token![,]>)
1083     -> Punctuated<GenericParam, Token![,]>
1084 {
1085     lv.iter()
1086         .map(|lt| GenericParam::Lifetime(lt.clone()))
1087         .collect()
1088 }
1089 
1090 /// Transform a Vec of lifetimes into a Generics
lifetimes_to_generics(lv: &Punctuated<LifetimeParam, Token![,]>)-> Generics1091 fn lifetimes_to_generics(lv: &Punctuated<LifetimeParam, Token![,]>)-> Generics {
1092     if lv.is_empty() {
1093             Generics::default()
1094     } else {
1095         let params = lifetimes_to_generic_params(lv);
1096         Generics {
1097             lt_token: Some(Token![<](lv[0].span())),
1098             gt_token: Some(Token![>](lv[0].span())),
1099             params,
1100             where_clause: None
1101         }
1102     }
1103 }
1104 
1105 /// Split a generics list into three: one for type generics and where predicates
1106 /// that relate to the signature, one for lifetimes that relate to the arguments
1107 /// only, and one for lifetimes that relate to the return type only.
split_lifetimes( generics: Generics, args: &[FnArg], rt: &ReturnType) -> (Generics, Punctuated<LifetimeParam, token::Comma>, Punctuated<LifetimeParam, token::Comma>)1108 fn split_lifetimes(
1109     generics: Generics,
1110     args: &[FnArg],
1111     rt: &ReturnType)
1112     -> (Generics,
1113         Punctuated<LifetimeParam, token::Comma>,
1114         Punctuated<LifetimeParam, token::Comma>)
1115 {
1116     if generics.lt_token.is_none() {
1117         return (generics, Default::default(), Default::default());
1118     }
1119 
1120     // Check which types and lifetimes are referenced by the arguments
1121     let mut alts = HashSet::<Lifetime>::default();
1122     let mut rlts = HashSet::<Lifetime>::default();
1123     for arg in args {
1124         match arg {
1125             FnArg::Receiver(r) => {
1126                 if let Some((_, Some(lt))) = &r.reference {
1127                     alts.insert(lt.clone());
1128                 }
1129             },
1130             FnArg::Typed(pt) => {
1131                 alts.extend(find_lifetimes(pt.ty.as_ref()));
1132             },
1133         };
1134     };
1135 
1136     if let ReturnType::Type(_, ty) = rt {
1137         rlts.extend(find_lifetimes(ty));
1138     }
1139 
1140     let mut tv = Punctuated::new();
1141     let mut alv = Punctuated::new();
1142     let mut rlv = Punctuated::new();
1143     for p in generics.params.into_iter() {
1144         match p {
1145             GenericParam::Lifetime(ltd) if rlts.contains(&ltd.lifetime) =>
1146                 rlv.push(ltd),
1147             GenericParam::Lifetime(ltd) if alts.contains(&ltd.lifetime) =>
1148                 alv.push(ltd),
1149             GenericParam::Lifetime(_) => {
1150                 // Probably a lifetime parameter from the impl block that isn't
1151                 // used by this particular method
1152             },
1153             GenericParam::Type(_) => tv.push(p),
1154             _ => (),
1155         }
1156     }
1157 
1158     let tg = if tv.is_empty() {
1159         Generics::default()
1160     } else {
1161         Generics {
1162             lt_token: generics.lt_token,
1163             gt_token: generics.gt_token,
1164             params: tv,
1165             where_clause: generics.where_clause
1166         }
1167     };
1168 
1169     (tg, alv, rlv)
1170 }
1171 
1172 /// Return the visibility that should be used for expectation!, given the
1173 /// original method's visibility.
1174 ///
1175 /// # Arguments
1176 /// - `vis`:    Original visibility of the item
1177 /// - `levels`: How many modules will the mock item be nested in?
expectation_visibility(vis: &Visibility, levels: usize) -> Visibility1178 fn expectation_visibility(vis: &Visibility, levels: usize)
1179     -> Visibility
1180 {
1181     if levels == 0 {
1182         return vis.clone();
1183     }
1184 
1185     let in_token = Token![in](vis.span());
1186     let super_token = Token![super](vis.span());
1187     match vis {
1188         Visibility::Inherited => {
1189             // Private items need pub(in super::[...]) for each level
1190             let mut path = Path::from(super_token);
1191             for _ in 1..levels {
1192                 path.segments.push(super_token.into());
1193             }
1194             Visibility::Restricted(VisRestricted{
1195                 pub_token: Token![pub](vis.span()),
1196                 paren_token: token::Paren::default(),
1197                 in_token: Some(in_token),
1198                 path: Box::new(path)
1199             })
1200         },
1201         Visibility::Restricted(vr) => {
1202             // crate => don't change
1203             // in crate::* => don't change
1204             // super => in super::super::super
1205             // self => in super::super
1206             // in anything_else => super::super::anything_else
1207             if vr.path.segments.first().unwrap().ident == "crate" {
1208                 Visibility::Restricted(vr.clone())
1209             } else {
1210                 let mut out = vr.clone();
1211                 out.in_token = Some(in_token);
1212                 for _ in 0..levels {
1213                     out.path.segments.insert(0, super_token.into());
1214                 }
1215                 Visibility::Restricted(out)
1216             }
1217         },
1218         _ => vis.clone()
1219     }
1220 }
1221 
staticize(generics: &Generics) -> Generics1222 fn staticize(generics: &Generics) -> Generics {
1223     let mut ret = generics.clone();
1224     for lt in ret.lifetimes_mut() {
1225         lt.lifetime = Lifetime::new("'static", Span::call_site());
1226     };
1227     ret
1228 }
1229 
mock_it<M: Into<MockableItem>>(inputs: M) -> TokenStream1230 fn mock_it<M: Into<MockableItem>>(inputs: M) -> TokenStream
1231 {
1232     let mockable: MockableItem = inputs.into();
1233     let mock = MockItem::from(mockable);
1234     let ts = mock.into_token_stream();
1235     if env::var("MOCKALL_DEBUG").is_ok() {
1236         println!("{ts}");
1237     }
1238     ts
1239 }
1240 
do_mock_once(input: TokenStream) -> TokenStream1241 fn do_mock_once(input: TokenStream) -> TokenStream
1242 {
1243     let item: MockableStruct = match syn::parse2(input) {
1244         Ok(mock) => mock,
1245         Err(err) => {
1246             return err.to_compile_error();
1247         }
1248     };
1249     mock_it(item)
1250 }
1251 
do_mock(input: TokenStream) -> TokenStream1252 fn do_mock(input: TokenStream) -> TokenStream
1253 {
1254     cfg_if! {
1255         if #[cfg(reprocheck)] {
1256             let ts_a = do_mock_once(input.clone());
1257             let ts_b = do_mock_once(input.clone());
1258             assert_eq!(ts_a.to_string(), ts_b.to_string());
1259         }
1260     }
1261     do_mock_once(input)
1262 }
1263 
1264 #[proc_macro_attribute]
concretize( _attrs: proc_macro::TokenStream, input: proc_macro::TokenStream) -> proc_macro::TokenStream1265 pub fn concretize(
1266     _attrs: proc_macro::TokenStream,
1267     input: proc_macro::TokenStream) -> proc_macro::TokenStream
1268 {
1269     // Do nothing.  This "attribute" is processed as text by the real proc
1270     // macros.
1271     input
1272 }
1273 
1274 #[proc_macro]
mock(input: proc_macro::TokenStream) -> proc_macro::TokenStream1275 pub fn mock(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
1276     do_mock(input.into()).into()
1277 }
1278 
1279 #[proc_macro_attribute]
automock(attrs: proc_macro::TokenStream, input: proc_macro::TokenStream) -> proc_macro::TokenStream1280 pub fn automock(attrs: proc_macro::TokenStream, input: proc_macro::TokenStream)
1281     -> proc_macro::TokenStream
1282 {
1283     let attrs: proc_macro2::TokenStream = attrs.into();
1284     let input: proc_macro2::TokenStream = input.into();
1285     do_automock(attrs, input).into()
1286 }
1287 
do_automock_once(attrs: TokenStream, input: TokenStream) -> TokenStream1288 fn do_automock_once(attrs: TokenStream, input: TokenStream) -> TokenStream {
1289     let mut output = input.clone();
1290     let attrs: Attrs = match parse2(attrs) {
1291         Ok(a) => a,
1292         Err(err) => {
1293             return err.to_compile_error();
1294         }
1295     };
1296     let item: Item = match parse2(input) {
1297         Ok(item) => item,
1298         Err(err) => {
1299             return err.to_compile_error();
1300         }
1301     };
1302     output.extend(mock_it((attrs, item)));
1303     output
1304 }
1305 
do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream1306 fn do_automock(attrs: TokenStream, input: TokenStream) -> TokenStream {
1307     cfg_if! {
1308         if #[cfg(reprocheck)] {
1309             let ts_a = do_automock_once(attrs.clone(), input.clone());
1310             let ts_b = do_automock_once(attrs.clone(), input.clone());
1311             assert_eq!(ts_a.to_string(), ts_b.to_string());
1312         }
1313     }
1314     do_automock_once(attrs, input)
1315 }
1316 
1317 #[cfg(test)]
1318 mod t {
1319     use super::*;
1320 
assert_contains(output: &str, tokens: TokenStream)1321 fn assert_contains(output: &str, tokens: TokenStream) {
1322     let s = tokens.to_string();
1323     assert!(output.contains(&s), "output does not contain {:?}", &s);
1324 }
1325 
assert_not_contains(output: &str, tokens: TokenStream)1326 fn assert_not_contains(output: &str, tokens: TokenStream) {
1327     let s = tokens.to_string();
1328     assert!(!output.contains(&s), "output does not contain {:?}", &s);
1329 }
1330 
1331 /// Various tests for overall code generation that are hard or impossible to
1332 /// write as integration tests
1333 mod mock {
1334     use std::str::FromStr;
1335     use super::super::*;
1336     use super::*;
1337 
1338     #[test]
inherent_method_visibility()1339     fn inherent_method_visibility() {
1340         let code = "
1341             Foo {
1342                 fn foo(&self);
1343                 pub fn bar(&self);
1344                 pub(crate) fn baz(&self);
1345                 pub(super) fn bean(&self);
1346                 pub(in crate::outer) fn boom(&self);
1347             }
1348         ";
1349         let ts = proc_macro2::TokenStream::from_str(code).unwrap();
1350         let output = do_mock(ts).to_string();
1351         assert_not_contains(&output, quote!(pub fn foo));
1352         assert!(!output.contains(") fn foo"));
1353         assert_contains(&output, quote!(pub fn bar));
1354         assert_contains(&output, quote!(pub(crate) fn baz));
1355         assert_contains(&output, quote!(pub(super) fn bean));
1356         assert_contains(&output, quote!(pub(in crate::outer) fn boom));
1357 
1358         assert_not_contains(&output, quote!(pub fn expect_foo));
1359         assert!(!output.contains("pub fn expect_foo"));
1360         assert!(!output.contains(") fn expect_foo"));
1361         assert_contains(&output, quote!(pub fn expect_bar));
1362         assert_contains(&output, quote!(pub(crate) fn expect_baz));
1363         assert_contains(&output, quote!(pub(super) fn expect_bean));
1364         assert_contains(&output, quote!(pub(in crate::outer) fn expect_boom));
1365     }
1366 
1367     #[test]
specific_impl()1368     fn specific_impl() {
1369         let code = "
1370             pub Foo<T: 'static> {}
1371             impl Bar for Foo<u32> {
1372                 fn bar(&self);
1373             }
1374             impl Bar for Foo<i32> {
1375                 fn bar(&self);
1376             }
1377         ";
1378         let ts = proc_macro2::TokenStream::from_str(code).unwrap();
1379         let output = do_mock(ts).to_string();
1380         assert_contains(&output, quote!(impl Bar for MockFoo<u32>));
1381         assert_contains(&output, quote!(impl Bar for MockFoo<i32>));
1382         // Ensure we don't duplicate the checkpoint function
1383         assert_not_contains(&output, quote!(
1384             self.Bar_expectations.checkpoint();
1385             self.Bar_expectations.checkpoint();
1386         ));
1387         // The expect methods should return specific types, not generic ones
1388         assert_contains(&output, quote!(
1389             pub fn expect_bar(&mut self) -> &mut __mock_MockFoo_Bar::__bar::Expectation<u32>
1390         ));
1391         assert_contains(&output, quote!(
1392             pub fn expect_bar(&mut self) -> &mut __mock_MockFoo_Bar::__bar::Expectation<i32>
1393         ));
1394     }
1395 }
1396 
1397 /// Various tests for overall code generation that are hard or impossible to
1398 /// write as integration tests
1399 mod automock {
1400     use std::str::FromStr;
1401     use super::super::*;
1402     use super::*;
1403 
1404     #[test]
doc_comments()1405     fn doc_comments() {
1406         let code = "
1407             mod foo {
1408                 /// Function docs
1409                 pub fn bar() { unimplemented!() }
1410             }
1411         ";
1412         let ts = proc_macro2::TokenStream::from_str(code).unwrap();
1413         let attrs_ts = proc_macro2::TokenStream::from_str("").unwrap();
1414         let output = do_automock(attrs_ts, ts).to_string();
1415         assert_contains(&output, quote!(#[doc=" Function docs"] pub fn bar));
1416     }
1417 
1418     #[test]
method_visibility()1419     fn method_visibility() {
1420         let code = "
1421         impl Foo {
1422             fn foo(&self) {}
1423             pub fn bar(&self) {}
1424             pub(super) fn baz(&self) {}
1425             pub(crate) fn bang(&self) {}
1426             pub(in super::x) fn bean(&self) {}
1427         }";
1428         let ts = proc_macro2::TokenStream::from_str(code).unwrap();
1429         let attrs_ts = proc_macro2::TokenStream::from_str("").unwrap();
1430         let output = do_automock(attrs_ts, ts).to_string();
1431         assert_not_contains(&output, quote!(pub fn foo));
1432         assert!(!output.contains(") fn foo"));
1433         assert_not_contains(&output, quote!(pub fn expect_foo));
1434         assert!(!output.contains(") fn expect_foo"));
1435         assert_contains(&output, quote!(pub fn bar));
1436         assert_contains(&output, quote!(pub fn expect_bar));
1437         assert_contains(&output, quote!(pub(super) fn baz));
1438         assert_contains(&output, quote!(pub(super) fn expect_baz));
1439         assert_contains(&output, quote!(pub ( crate ) fn bang));
1440         assert_contains(&output, quote!(pub ( crate ) fn expect_bang));
1441         assert_contains(&output, quote!(pub ( in super :: x ) fn bean));
1442         assert_contains(&output, quote!(pub ( in super :: x ) fn expect_bean));
1443     }
1444 
1445     #[test]
1446     #[should_panic(expected = "can only mock inline modules")]
external_module()1447     fn external_module() {
1448         let code = "mod foo;";
1449         let ts = proc_macro2::TokenStream::from_str(code).unwrap();
1450         let attrs_ts = proc_macro2::TokenStream::from_str("").unwrap();
1451         do_automock(attrs_ts, ts).to_string();
1452     }
1453 
1454     #[test]
trait_visibility()1455     fn trait_visibility() {
1456         let code = "
1457         pub(super) trait Foo {}
1458         ";
1459         let attrs_ts = proc_macro2::TokenStream::from_str("").unwrap();
1460         let ts = proc_macro2::TokenStream::from_str(code).unwrap();
1461         let output = do_automock(attrs_ts, ts).to_string();
1462         assert_contains(&output, quote!(pub ( super ) struct MockFoo));
1463     }
1464 }
1465 
1466 mod concretize_args {
1467     use super::*;
1468 
check_concretize( sig: TokenStream, expected_inputs: &[TokenStream], expected_call_exprs: &[TokenStream])1469     fn check_concretize(
1470         sig: TokenStream,
1471         expected_inputs: &[TokenStream],
1472         expected_call_exprs: &[TokenStream])
1473     {
1474         let f: Signature = parse2(sig).unwrap();
1475         let (generics, inputs, call_exprs) =
1476             concretize_args(&f.generics, &f.inputs);
1477         assert!(generics.params.is_empty());
1478         assert_eq!(inputs.len(), expected_inputs.len());
1479         assert_eq!(call_exprs.len(), expected_call_exprs.len());
1480         for i in 0..inputs.len() {
1481             let actual = &inputs[i];
1482             let exp = &expected_inputs[i];
1483             assert_eq!(quote!(#actual).to_string(), quote!(#exp).to_string());
1484         }
1485         for i in 0..call_exprs.len() {
1486             let actual = &call_exprs[i];
1487             let exp = &expected_call_exprs[i];
1488             assert_eq!(quote!(#actual).to_string(), quote!(#exp).to_string());
1489         }
1490     }
1491 
1492     #[test]
bystanders()1493     fn bystanders() {
1494         check_concretize(
1495             quote!(fn foo<P: AsRef<Path>>(x: i32, p: P, y: &f64)),
1496             &[quote!(x: i32), quote!(p: &(dyn AsRef<Path>)), quote!(y: &f64)],
1497             &[quote!(x), quote!(&p), quote!(y)]
1498         );
1499     }
1500 
1501     #[test]
multi_bounds()1502     fn multi_bounds() {
1503         check_concretize(
1504             quote!(fn foo<P: AsRef<String> + AsMut<String>>(p: P)),
1505             &[quote!(p: &(dyn AsRef<String> + AsMut<String>))],
1506             &[quote!(&p)]
1507         );
1508     }
1509 
1510     #[test]
mutable_reference_arg()1511     fn mutable_reference_arg() {
1512         check_concretize(
1513             quote!(fn foo<P: AsMut<Path>>(p: &mut P)),
1514             &[quote!(p: &mut (dyn AsMut<Path>))],
1515             &[quote!(p)]
1516         );
1517     }
1518 
1519     #[test]
mutable_reference_multi_bounds()1520     fn mutable_reference_multi_bounds() {
1521         check_concretize(
1522             quote!(fn foo<P: AsRef<String> + AsMut<String>>(p: &mut P)),
1523             &[quote!(p: &mut (dyn AsRef<String> + AsMut<String>))],
1524             &[quote!(p)]
1525         );
1526     }
1527 
1528     #[test]
reference_arg()1529     fn reference_arg() {
1530         check_concretize(
1531             quote!(fn foo<P: AsRef<Path>>(p: &P)),
1532             &[quote!(p: &(dyn AsRef<Path>))],
1533             &[quote!(p)]
1534         );
1535     }
1536 
1537     #[test]
simple()1538     fn simple() {
1539         check_concretize(
1540             quote!(fn foo<P: AsRef<Path>>(p: P)),
1541             &[quote!(p: &(dyn AsRef<Path>))],
1542             &[quote!(&p)]
1543         );
1544     }
1545 
1546     #[test]
slice()1547     fn slice() {
1548         check_concretize(
1549             quote!(fn foo<P: AsRef<Path>>(p: &[P])),
1550             &[quote!(p: &[&(dyn AsRef<Path>)])],
1551             &[quote!(&(0..p.len()).map(|__mockall_i| &p[__mockall_i] as &(dyn AsRef<Path>)).collect::<Vec<_>>())]
1552         );
1553     }
1554 
1555     #[test]
slice_with_multi_bounds()1556     fn slice_with_multi_bounds() {
1557         check_concretize(
1558             quote!(fn foo<P: AsRef<Path> + AsMut<String>>(p: &[P])),
1559             &[quote!(p: &[&(dyn AsRef<Path> + AsMut<String>)])],
1560             &[quote!(&(0..p.len()).map(|__mockall_i| &p[__mockall_i] as &(dyn AsRef<Path> + AsMut<String>)).collect::<Vec<_>>())]
1561         );
1562     }
1563 
1564     #[test]
where_clause()1565     fn where_clause() {
1566         check_concretize(
1567             quote!(fn foo<P>(p: P) where P: AsRef<Path>),
1568             &[quote!(p: &(dyn AsRef<Path>))],
1569             &[quote!(&p)]
1570         );
1571     }
1572 }
1573 
1574 mod deimplify {
1575     use super::*;
1576 
check_deimplify(orig_ts: TokenStream, expected_ts: TokenStream)1577     fn check_deimplify(orig_ts: TokenStream, expected_ts: TokenStream) {
1578         let mut orig: ReturnType = parse2(orig_ts).unwrap();
1579         let expected: ReturnType = parse2(expected_ts).unwrap();
1580         deimplify(&mut orig);
1581         assert_eq!(quote!(#orig).to_string(), quote!(#expected).to_string());
1582     }
1583 
1584     // Future is a special case
1585     #[test]
impl_future()1586     fn impl_future() {
1587         check_deimplify(
1588             quote!(-> impl Future<Output=i32>),
1589             quote!(-> ::std::pin::Pin<Box<dyn Future<Output=i32>>>)
1590         );
1591     }
1592 
1593     // Future is a special case, wherever it appears
1594     #[test]
impl_future_reverse()1595     fn impl_future_reverse() {
1596         check_deimplify(
1597             quote!(-> impl Send + Future<Output=i32>),
1598             quote!(-> ::std::pin::Pin<Box<dyn Send + Future<Output=i32>>>)
1599         );
1600     }
1601 
1602     // Stream is a special case
1603     #[test]
impl_stream()1604     fn impl_stream() {
1605         check_deimplify(
1606             quote!(-> impl Stream<Item=i32>),
1607             quote!(-> ::std::pin::Pin<Box<dyn Stream<Item=i32>>>)
1608         );
1609     }
1610 
1611     #[test]
impl_trait()1612     fn impl_trait() {
1613         check_deimplify(
1614             quote!(-> impl Foo),
1615             quote!(-> Box<dyn Foo>)
1616         );
1617     }
1618 
1619     // With extra bounds
1620     #[test]
impl_trait2()1621     fn impl_trait2() {
1622         check_deimplify(
1623             quote!(-> impl Foo + Send),
1624             quote!(-> Box<dyn Foo + Send>)
1625         );
1626     }
1627 }
1628 
1629 mod deselfify {
1630     use super::*;
1631 
check_deselfify( orig_ts: TokenStream, actual_ts: TokenStream, generics_ts: TokenStream, expected_ts: TokenStream)1632     fn check_deselfify(
1633         orig_ts: TokenStream,
1634         actual_ts: TokenStream,
1635         generics_ts: TokenStream,
1636         expected_ts: TokenStream)
1637     {
1638         let mut ty: Type = parse2(orig_ts).unwrap();
1639         let actual: Ident = parse2(actual_ts).unwrap();
1640         let generics: Generics = parse2(generics_ts).unwrap();
1641         let expected: Type = parse2(expected_ts).unwrap();
1642         deselfify(&mut ty, &actual, &generics);
1643         assert_eq!(quote!(#ty).to_string(),
1644                    quote!(#expected).to_string());
1645     }
1646 
1647     #[test]
arc()1648     fn arc() {
1649         check_deselfify(
1650             quote!(Arc<Self>),
1651             quote!(Foo),
1652             quote!(),
1653             quote!(Arc<Foo>)
1654         );
1655     }
1656     #[test]
future()1657     fn future() {
1658         check_deselfify(
1659             quote!(Box<dyn Future<Output=Self>>),
1660             quote!(Foo),
1661             quote!(),
1662             quote!(Box<dyn Future<Output=Foo>>)
1663         );
1664     }
1665 
1666     #[test]
qself()1667     fn qself() {
1668         check_deselfify(
1669             quote!(<Self as Self>::Self),
1670             quote!(Foo),
1671             quote!(),
1672             quote!(<Foo as Foo>::Foo)
1673         );
1674     }
1675 
1676     #[test]
trait_object()1677     fn trait_object() {
1678         check_deselfify(
1679             quote!(Box<dyn Self>),
1680             quote!(Foo),
1681             quote!(),
1682             quote!(Box<dyn Foo>)
1683         );
1684     }
1685 
1686     // A trait object with multiple bounds
1687     #[test]
trait_object2()1688     fn trait_object2() {
1689         check_deselfify(
1690             quote!(Box<dyn Self + Send>),
1691             quote!(Foo),
1692             quote!(),
1693             quote!(Box<dyn Foo + Send>)
1694         );
1695     }
1696 }
1697 
1698 mod dewhereselfify {
1699     use super::*;
1700 
1701     #[test]
lifetime()1702     fn lifetime() {
1703         let mut meth: ImplItemFn = parse2(quote!(
1704                 fn foo<'a>(&self) where 'a: 'static, Self: Sized {}
1705         )).unwrap();
1706         let expected: ImplItemFn = parse2(quote!(
1707                 fn foo<'a>(&self) where 'a: 'static {}
1708         )).unwrap();
1709         dewhereselfify(&mut meth.sig.generics);
1710         assert_eq!(meth, expected);
1711     }
1712 
1713     #[test]
normal_method()1714     fn normal_method() {
1715         let mut meth: ImplItemFn = parse2(quote!(
1716                 fn foo(&self) where Self: Sized {}
1717         )).unwrap();
1718         let expected: ImplItemFn = parse2(quote!(
1719                 fn foo(&self) {}
1720         )).unwrap();
1721         dewhereselfify(&mut meth.sig.generics);
1722         assert_eq!(meth, expected);
1723     }
1724 
1725     #[test]
with_real_generics()1726     fn with_real_generics() {
1727         let mut meth: ImplItemFn = parse2(quote!(
1728                 fn foo<T>(&self, t: T) where Self: Sized, T: Copy {}
1729         )).unwrap();
1730         let expected: ImplItemFn = parse2(quote!(
1731                 fn foo<T>(&self, t: T) where T: Copy {}
1732         )).unwrap();
1733         dewhereselfify(&mut meth.sig.generics);
1734         assert_eq!(meth, expected);
1735     }
1736 }
1737 
1738 mod gen_keyid {
1739     use super::*;
1740 
check_gen_keyid(orig: TokenStream, expected: TokenStream)1741     fn check_gen_keyid(orig: TokenStream, expected: TokenStream) {
1742         let g: Generics = parse2(orig).unwrap();
1743         let keyid = gen_keyid(&g);
1744         assert_eq!(quote!(#keyid).to_string(), quote!(#expected).to_string());
1745     }
1746 
1747     #[test]
empty()1748     fn empty() {
1749         check_gen_keyid(quote!(), quote!(<()>));
1750     }
1751 
1752     #[test]
onetype()1753     fn onetype() {
1754         check_gen_keyid(quote!(<T>), quote!(<T>));
1755     }
1756 
1757     #[test]
twotypes()1758     fn twotypes() {
1759         check_gen_keyid(quote!(<T, V>), quote!(<(T, V)>));
1760     }
1761 }
1762 
1763 mod merge_generics {
1764     use super::*;
1765 
1766     #[test]
both()1767     fn both() {
1768         let mut g1: Generics = parse2(quote!(<T: 'static, V: Copy> )).unwrap();
1769         let wc1: WhereClause = parse2(quote!(where T: Default)).unwrap();
1770         g1.where_clause = Some(wc1);
1771 
1772         let mut g2: Generics = parse2(quote!(<Q: Send, V: Clone>)).unwrap();
1773         let wc2: WhereClause = parse2(quote!(where T: Sync, Q: Debug)).unwrap();
1774         g2.where_clause = Some(wc2);
1775 
1776         let gm = super::merge_generics(&g1, &g2);
1777         let gm_wc = &gm.where_clause;
1778 
1779         let ge: Generics = parse2(quote!(
1780                 <T: 'static, V: Copy + Clone, Q: Send>
1781         )).unwrap();
1782         let wce: WhereClause = parse2(quote!(
1783             where T: Default + Sync, Q: Debug
1784         )).unwrap();
1785 
1786         assert_eq!(quote!(#ge #wce).to_string(),
1787                    quote!(#gm #gm_wc).to_string());
1788     }
1789 
1790     #[test]
eq()1791     fn eq() {
1792         let mut g1: Generics = parse2(quote!(<T: 'static, V: Copy> )).unwrap();
1793         let wc1: WhereClause = parse2(quote!(where T: Default)).unwrap();
1794         g1.where_clause = Some(wc1.clone());
1795 
1796         let gm = super::merge_generics(&g1, &g1);
1797         let gm_wc = &gm.where_clause;
1798 
1799         assert_eq!(quote!(#g1 #wc1).to_string(),
1800                    quote!(#gm #gm_wc).to_string());
1801     }
1802 
1803     #[test]
lhs_only()1804     fn lhs_only() {
1805         let mut g1: Generics = parse2(quote!(<T: 'static, V: Copy> )).unwrap();
1806         let wc1: WhereClause = parse2(quote!(where T: Default)).unwrap();
1807         g1.where_clause = Some(wc1.clone());
1808 
1809         let g2 = Generics::default();
1810 
1811         let gm = super::merge_generics(&g1, &g2);
1812         let gm_wc = &gm.where_clause;
1813 
1814         assert_eq!(quote!(#g1 #wc1).to_string(),
1815                    quote!(#gm #gm_wc).to_string());
1816     }
1817 
1818     #[test]
lhs_wc_only()1819     fn lhs_wc_only() {
1820         let mut g1 = Generics::default();
1821         let wc1: WhereClause = parse2(quote!(where T: Default)).unwrap();
1822         g1.where_clause = Some(wc1.clone());
1823 
1824         let g2 = Generics::default();
1825 
1826         let gm = super::merge_generics(&g1, &g2);
1827         let gm_wc = &gm.where_clause;
1828 
1829         assert_eq!(quote!(#g1 #wc1).to_string(),
1830                    quote!(#gm #gm_wc).to_string());
1831     }
1832 
1833     #[test]
rhs_only()1834     fn rhs_only() {
1835         let g1 = Generics::default();
1836         let mut g2: Generics = parse2(quote!(<Q: Send, V: Clone>)).unwrap();
1837         let wc2: WhereClause = parse2(quote!(where T: Sync, Q: Debug)).unwrap();
1838         g2.where_clause = Some(wc2.clone());
1839 
1840         let gm = super::merge_generics(&g1, &g2);
1841         let gm_wc = &gm.where_clause;
1842 
1843         assert_eq!(quote!(#g2 #wc2).to_string(),
1844                    quote!(#gm #gm_wc).to_string());
1845     }
1846 }
1847 
1848 mod supersuperfy {
1849     use super::*;
1850 
check_supersuperfy(orig: TokenStream, expected: TokenStream)1851     fn check_supersuperfy(orig: TokenStream, expected: TokenStream) {
1852         let orig_ty: Type = parse2(orig).unwrap();
1853         let expected_ty: Type = parse2(expected).unwrap();
1854         let output = supersuperfy(&orig_ty, 1);
1855         assert_eq!(quote!(#output).to_string(),
1856                    quote!(#expected_ty).to_string());
1857     }
1858 
1859     #[test]
array()1860     fn array() {
1861         check_supersuperfy(
1862             quote!([super::X; n]),
1863             quote!([super::super::X; n])
1864         );
1865     }
1866 
1867     #[test]
barefn()1868     fn barefn() {
1869         check_supersuperfy(
1870             quote!(fn(super::A) -> super::B),
1871             quote!(fn(super::super::A) -> super::super::B)
1872         );
1873     }
1874 
1875     #[test]
group()1876     fn group() {
1877         let orig = TypeGroup {
1878             group_token: token::Group::default(),
1879             elem: Box::new(parse2(quote!(super::T)).unwrap())
1880         };
1881         let expected = TypeGroup {
1882             group_token: token::Group::default(),
1883             elem: Box::new(parse2(quote!(super::super::T)).unwrap())
1884         };
1885         let output = supersuperfy(&Type::Group(orig), 1);
1886         assert_eq!(quote!(#output).to_string(),
1887                    quote!(#expected).to_string());
1888     }
1889 
1890     // Just check that it doesn't panic
1891     #[test]
infer()1892     fn infer() {
1893         check_supersuperfy( quote!(_), quote!(_));
1894     }
1895 
1896     // Just check that it doesn't panic
1897     #[test]
never()1898     fn never() {
1899         check_supersuperfy( quote!(!), quote!(!));
1900     }
1901 
1902     #[test]
paren()1903     fn paren() {
1904         check_supersuperfy(
1905             quote!((super::X)),
1906             quote!((super::super::X))
1907         );
1908     }
1909 
1910     #[test]
path()1911     fn path() {
1912         check_supersuperfy(
1913             quote!(::super::SuperT<u32>),
1914             quote!(::super::super::SuperT<u32>)
1915         );
1916     }
1917 
1918     #[test]
path_with_qself()1919     fn path_with_qself() {
1920         check_supersuperfy(
1921             quote!(<super::X as super::Y>::Foo<u32>),
1922             quote!(<super::super::X as super::super::Y>::Foo<u32>),
1923         );
1924     }
1925 
1926     #[test]
angle_bracketed_generic_arguments()1927     fn angle_bracketed_generic_arguments() {
1928         check_supersuperfy(
1929             quote!(mod_::T<super::X>),
1930             quote!(mod_::T<super::super::X>)
1931         );
1932     }
1933 
1934     #[test]
ptr()1935     fn ptr() {
1936         check_supersuperfy(
1937             quote!(*const super::X),
1938             quote!(*const super::super::X)
1939         );
1940     }
1941 
1942     #[test]
reference()1943     fn reference() {
1944         check_supersuperfy(
1945             quote!(&'a mut super::X),
1946             quote!(&'a mut super::super::X)
1947         );
1948     }
1949 
1950     #[test]
slice()1951     fn slice() {
1952         check_supersuperfy(
1953             quote!([super::X]),
1954             quote!([super::super::X])
1955         );
1956     }
1957 
1958     #[test]
trait_object()1959     fn trait_object() {
1960         check_supersuperfy(
1961             quote!(dyn super::X + super::Y),
1962             quote!(dyn super::super::X + super::super::Y)
1963         );
1964     }
1965 
1966     #[test]
tuple()1967     fn tuple() {
1968         check_supersuperfy(
1969             quote!((super::A, super::B)),
1970             quote!((super::super::A, super::super::B))
1971         );
1972     }
1973 }
1974 
1975 mod supersuperfy_generics {
1976     use super::*;
1977 
check_supersuperfy_generics( orig: TokenStream, orig_wc: TokenStream, expected: TokenStream, expected_wc: TokenStream)1978     fn check_supersuperfy_generics(
1979         orig: TokenStream,
1980         orig_wc: TokenStream,
1981         expected: TokenStream,
1982         expected_wc: TokenStream)
1983     {
1984         let mut orig_g: Generics = parse2(orig).unwrap();
1985         orig_g.where_clause = parse2(orig_wc).unwrap();
1986         let mut expected_g: Generics = parse2(expected).unwrap();
1987         expected_g.where_clause = parse2(expected_wc).unwrap();
1988         let mut output: Generics = orig_g;
1989         supersuperfy_generics(&mut output, 1);
1990         let (o_ig, o_tg, o_wc) = output.split_for_impl();
1991         let (e_ig, e_tg, e_wc) = expected_g.split_for_impl();
1992         assert_eq!(quote!(#o_ig).to_string(), quote!(#e_ig).to_string());
1993         assert_eq!(quote!(#o_tg).to_string(), quote!(#e_tg).to_string());
1994         assert_eq!(quote!(#o_wc).to_string(), quote!(#e_wc).to_string());
1995     }
1996 
1997     #[test]
default()1998     fn default() {
1999         check_supersuperfy_generics(
2000             quote!(<T: X = super::Y>), quote!(),
2001             quote!(<T: X = super::super::Y>), quote!(),
2002         );
2003     }
2004 
2005     #[test]
empty()2006     fn empty() {
2007         check_supersuperfy_generics(quote!(), quote!(), quote!(), quote!());
2008     }
2009 
2010     #[test]
everything()2011     fn everything() {
2012         check_supersuperfy_generics(
2013             quote!(<T: super::A = super::B>),
2014             quote!(where super::C: super::D),
2015             quote!(<T: super::super::A = super::super::B>),
2016             quote!(where super::super::C: super::super::D),
2017         );
2018     }
2019 
2020     #[test]
bound()2021     fn bound() {
2022         check_supersuperfy_generics(
2023             quote!(<T: super::A>), quote!(),
2024             quote!(<T: super::super::A>), quote!(),
2025         );
2026     }
2027 
2028     #[test]
closure()2029     fn closure() {
2030         check_supersuperfy_generics(
2031             quote!(<F: Fn(u32) -> super::SuperT>), quote!(),
2032             quote!(<F: Fn(u32) -> super::super::SuperT>), quote!(),
2033         );
2034     }
2035 
2036     #[test]
wc_bounded_ty()2037     fn wc_bounded_ty() {
2038         check_supersuperfy_generics(
2039             quote!(), quote!(where super::T: X),
2040             quote!(), quote!(where super::super::T: X),
2041         );
2042     }
2043 
2044     #[test]
wc_bounds()2045     fn wc_bounds() {
2046         check_supersuperfy_generics(
2047             quote!(), quote!(where T: super::X),
2048             quote!(), quote!(where T: super::super::X),
2049         );
2050     }
2051 }
2052 }
2053