11use crate :: { methods:: receiver:: Receiver , self_type:: SelfType } ;
22use proc_macro2:: TokenStream ;
33use quote:: { quote, ToTokens } ;
4- use syn:: { spanned:: Spanned , PathArguments , Type , TypePath } ;
4+ use syn:: { spanned:: Spanned , Generics , Ident , PathArguments , Type , TypePath } ;
55
66pub struct Signature < ' a > {
77 name : & ' a syn:: Ident ,
@@ -14,6 +14,7 @@ pub struct Signature<'a> {
1414
1515pub struct MethodData < ' a > {
1616 receiver : Receiver ,
17+ generics : syn:: Generics ,
1718 arg_types : Vec < WhenArg < ' a > > ,
1819 is_private : bool ,
1920}
@@ -89,6 +90,7 @@ impl<'a> Signature<'a> {
8990 vis : & syn:: Visibility ,
9091 ) -> Signature < ' a > {
9192 let receiver = Receiver :: from_signature ( signature) ;
93+ let generics = signature. generics . clone ( ) ;
9294
9395 let output = match & signature. output {
9496 syn:: ReturnType :: Default => None ,
@@ -110,6 +112,7 @@ impl<'a> Signature<'a> {
110112
111113 MethodData {
112114 receiver,
115+ generics,
113116 arg_types,
114117 is_private : trait_path. is_none ( ) && * vis == syn:: Visibility :: Inherited ,
115118 }
@@ -144,9 +147,17 @@ impl<'a> Signature<'a> {
144147 let name = & self . name ;
145148 let args = & self . args ;
146149
150+ let generics = self
151+ . method_data
152+ . as_ref ( )
153+ . map ( |method_data| method_data. generics . clone ( ) ) ;
154+
155+ let generic_idents = generic_type_idents ( generics) ;
156+ let turbofish = turbofish ( & generic_idents) ;
157+
147158 let proxy = match self . trait_path {
148- None => quote ! { <#real_ty>:: #name } ,
149- Some ( path) => quote ! { <#real_ty as #path>:: #name } ,
159+ None => quote ! { <#real_ty>:: #name #turbofish } ,
160+ Some ( path) => quote ! { <#real_ty as #path>:: #name #turbofish } ,
150161 } ;
151162
152163 let real_self_arg = self . method_data . as_ref ( ) . map ( |_| {
@@ -204,10 +215,16 @@ impl<'a> Signature<'a> {
204215 } ;
205216
206217 let fn_name = name. to_string ( ) ;
218+ let mut generics_str = generic_idents
219+ . into_iter ( )
220+ . map ( |i| i. to_string ( ) )
221+ . collect :: < Vec < _ > > ( )
222+ . join ( "," ) ;
223+ generics_str. retain ( |c| !c. is_whitespace ( ) ) ;
207224
208225 quote ! {
209226 unsafe {
210- match _maybe_faux_faux. call_stub( <Self >:: #faux_ident, #fn_name, #args) {
227+ match _maybe_faux_faux. call_stub( <Self >:: #faux_ident #turbofish , #fn_name, #args, #generics_str ) {
211228 std:: result:: Result :: Ok ( o) => o,
212229 std:: result:: Result :: Err ( e) => panic!( "{}" , e) ,
213230 }
@@ -332,6 +349,7 @@ impl<'a> MethodData<'a> {
332349 let MethodData {
333350 arg_types,
334351 receiver,
352+ generics,
335353 ..
336354 } = self ;
337355 let receiver_ty = & receiver. ty ;
@@ -345,11 +363,23 @@ impl<'a> MethodData<'a> {
345363 let output = output. unwrap_or ( & empty) ;
346364 let name_str = name. to_string ( ) ;
347365
366+ let generics_contents = if generics. params . is_empty ( ) {
367+ None
368+ } else {
369+ let params = & generics. params ;
370+ Some ( quote ! { , #params } )
371+ } ;
372+
373+ let generics_where_clause = & generics. where_clause ;
374+
375+ let generic_idents = generic_type_idents ( Some ( generics. clone ( ) ) ) ;
376+ let turbofish = turbofish ( & generic_idents) ;
377+
348378 let when_method = syn:: parse_quote! {
349- pub fn #when_ident<' m>( & ' m mut self ) -> faux:: When <' m, #receiver_ty, ( #( #arg_types) , * ) , #output, faux:: matcher:: AnyInvocation > {
379+ pub fn #when_ident<' m #generics_contents >( & ' m mut self ) -> faux:: When <' m, #receiver_ty, ( #( #arg_types) , * ) , #output, faux:: matcher:: AnyInvocation > #generics_where_clause {
350380 match & mut self . 0 {
351381 faux:: MaybeFaux :: Faux ( _maybe_faux_faux) => faux:: When :: new(
352- <Self >:: #faux_ident,
382+ <Self >:: #faux_ident #turbofish ,
353383 #name_str,
354384 _maybe_faux_faux
355385 ) ,
@@ -362,7 +392,7 @@ impl<'a> MethodData<'a> {
362392 let faux_method = syn:: parse_quote! {
363393 #[ allow( clippy:: needless_arbitrary_self_type) ]
364394 #[ allow( clippy:: boxed_local) ]
365- pub fn #faux_ident( self : #receiver_ty, _: ( #( #arg_types) , * ) ) -> #output {
395+ pub fn #faux_ident #generics ( self : #receiver_ty, _: ( #( #arg_types) , * ) ) -> #output #generics_where_clause {
366396 panic!( #panic_message)
367397 }
368398 } ;
@@ -466,3 +496,22 @@ fn path_args_contains_self(path: &syn::Path, self_path: &syn::TypePath) -> bool
466496 }
467497 }
468498}
499+
500+ fn generic_type_idents ( generics : Option < Generics > ) -> Vec < Ident > {
501+ generics
502+ . map ( |g| {
503+ g. type_params ( )
504+ . into_iter ( )
505+ . map ( |tp| tp. ident . clone ( ) )
506+ . collect ( )
507+ } )
508+ . unwrap_or_default ( )
509+ }
510+
511+ fn turbofish ( idents : & [ Ident ] ) -> TokenStream {
512+ if idents. is_empty ( ) {
513+ quote ! { }
514+ } else {
515+ quote ! { :: < #( #idents) , * > }
516+ }
517+ }
0 commit comments