|
1 | 1 | use crate::{methods::receiver::Receiver, self_type::SelfType}; |
2 | 2 | use proc_macro2::TokenStream; |
3 | 3 | use quote::{quote, ToTokens}; |
4 | | -use syn::{spanned::Spanned, Generics, PathArguments, Type, TypePath}; |
| 4 | +use syn::{spanned::Spanned, Generics, Ident, PathArguments, Type, TypePath}; |
5 | 5 |
|
6 | 6 | pub struct Signature<'a> { |
7 | 7 | name: &'a syn::Ident, |
@@ -152,11 +152,12 @@ impl<'a> Signature<'a> { |
152 | 152 | .as_ref() |
153 | 153 | .map(|method_data| method_data.generics.clone()); |
154 | 154 |
|
155 | | - let maybe_generics = generic_types_only(generics); |
| 155 | + let generic_idents = generic_type_idents(generics); |
| 156 | + let turbofish = turbofish(&generic_idents); |
156 | 157 |
|
157 | 158 | let proxy = match self.trait_path { |
158 | | - None => quote! { <#real_ty>::#name #maybe_generics }, |
159 | | - Some(path) => quote! { <#real_ty as #path>::#name #maybe_generics }, |
| 159 | + None => quote! { <#real_ty>::#name #turbofish }, |
| 160 | + Some(path) => quote! { <#real_ty as #path>::#name #turbofish }, |
160 | 161 | }; |
161 | 162 |
|
162 | 163 | let real_self_arg = self.method_data.as_ref().map(|_| { |
@@ -214,10 +215,16 @@ impl<'a> Signature<'a> { |
214 | 215 | }; |
215 | 216 |
|
216 | 217 | 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()); |
217 | 224 |
|
218 | 225 | quote! { |
219 | 226 | unsafe { |
220 | | - match _maybe_faux_faux.call_stub(<Self>::#faux_ident #maybe_generics, #fn_name, #args) { |
| 227 | + match _maybe_faux_faux.call_stub(<Self>::#faux_ident #turbofish, #fn_name, #args, #generics_str) { |
221 | 228 | std::result::Result::Ok(o) => o, |
222 | 229 | std::result::Result::Err(e) => panic!("{}", e), |
223 | 230 | } |
@@ -366,13 +373,14 @@ impl<'a> MethodData<'a> { |
366 | 373 |
|
367 | 374 | let generics_where_clause = &generics.where_clause; |
368 | 375 |
|
369 | | - let maybe_generics = generic_types_only(Some(generics.clone())); |
| 376 | + let generic_idents = generic_type_idents(Some(generics.clone())); |
| 377 | + let turbofish = turbofish(&generic_idents); |
370 | 378 |
|
371 | 379 | let when_method = syn::parse_quote! { |
372 | 380 | pub fn #when_ident<'m #maybe_comma #generics_contents>(&'m mut self) -> faux::When<'m, #receiver_ty, (#(#arg_types),*), #output, faux::matcher::AnyInvocation> #generics_where_clause { |
373 | 381 | match &mut self.0 { |
374 | 382 | faux::MaybeFaux::Faux(_maybe_faux_faux) => faux::When::new( |
375 | | - <Self>::#faux_ident #maybe_generics, |
| 383 | + <Self>::#faux_ident #turbofish, |
376 | 384 | #name_str, |
377 | 385 | _maybe_faux_faux |
378 | 386 | ), |
@@ -490,14 +498,21 @@ fn path_args_contains_self(path: &syn::Path, self_path: &syn::TypePath) -> bool |
490 | 498 | } |
491 | 499 | } |
492 | 500 |
|
493 | | -fn generic_types_only(generics: Option<Generics>) -> TokenStream { |
494 | | - if let Some(mut g) = generics { |
495 | | - let type_params = g |
496 | | - .type_params_mut() |
497 | | - .into_iter() |
498 | | - .map(|type_param| type_param.ident.clone()); |
499 | | - quote! { :: < #(#type_params),* > } |
500 | | - } else { |
| 501 | +fn generic_type_idents(generics: Option<Generics>) -> Vec<Ident> { |
| 502 | + generics |
| 503 | + .map(|g| { |
| 504 | + g.type_params() |
| 505 | + .into_iter() |
| 506 | + .map(|tp| tp.ident.clone()) |
| 507 | + .collect() |
| 508 | + }) |
| 509 | + .unwrap_or_default() |
| 510 | +} |
| 511 | + |
| 512 | +fn turbofish(idents: &[Ident]) -> TokenStream { |
| 513 | + if idents.is_empty() { |
501 | 514 | quote! {} |
| 515 | + } else { |
| 516 | + quote! { :: < #(#idents),* > } |
502 | 517 | } |
503 | 518 | } |
0 commit comments