1use proc_macro2::TokenStream;
2
3use std::collections::BTreeMap;
4
5use super::func::WrappedType;
6use super::generics::ParsedGenerics;
7
8use quote::*;
9use syn::*;
10
11pub fn gen_forward(tr: ItemTrait, ext_path: Option<TokenStream>) -> TokenStream {
12 let crate_path = crate::util::crate_path();
13
14 let mut types = BTreeMap::new();
15
16 types.insert(
17 format_ident!("Self"),
18 WrappedType {
19 ty: parse2(quote!(Self)).unwrap(),
20 ty_ret_tmp: None,
21 ty_static: None,
22 return_conv: None,
23 lifetime_bound: None,
24 lifetime_type_bound: None,
25 other_bounds: None,
26 other_bounds_simple: None,
27 impl_return_conv: None,
28 inject_ret_tmp: false,
29 unbounded_hrtb: false,
30 },
31 );
32
33 let mut wrapped_types = TokenStream::new();
34
35 let (funcs, generics, _, _) = super::traits::parse_trait(
36 &tr,
37 &crate_path,
38 false,
39 |(ty_ident, _, ty_where_clause, _), _, _, _, _, _, _| {
40 if let Some(ident) = ty_ident {
41 wrapped_types.extend(quote!(type #ident = CGlueT::#ident #ty_where_clause;));
42 }
43 },
44 );
45
46 let ParsedGenerics {
47 life_declare,
48 life_use,
49 gen_declare,
50 gen_use,
51 gen_where_bounds,
52 ..
53 } = &generics;
54
55 let trait_name = &tr.ident;
56
57 let mut impls = TokenStream::new();
58
59 let mut need_mut = false;
60
61 for func in funcs {
62 let nm = func.forward_wrapped_trait_impl(&mut impls);
63 need_mut = nm || need_mut;
64 }
65
66 let mut required_mutability = TokenStream::new();
67
68 required_mutability.extend(quote!(::core::ops::Deref<Target = CGlueT>));
69
70 if need_mut {
71 required_mutability.extend(quote!( + ::core::ops::DerefMut))
72 }
73
74 let tr_impl = if ext_path.is_some() {
75 quote!()
76 } else {
77 quote!(#tr)
78 };
79
80 let needs_send = tr.supertraits.iter().any(|s| {
81 if let TypeParamBound::Trait(tr) = s {
82 tr.path.get_ident().map(|i| i == "Send") == Some(true)
83 } else {
84 false
85 }
86 });
87
88 let send_bound = if needs_send { quote!(+ Send) } else { quote!() };
89 quote! {
90 #tr_impl
91
92 impl<#life_declare CGlueO: #required_mutability #send_bound, CGlueT, #gen_declare> #ext_path #trait_name<#life_use #gen_use> for #crate_path::forward::Fwd<CGlueO> where CGlueT: #ext_path #trait_name<#life_use #gen_use>, #gen_where_bounds {
93 #wrapped_types
94 #impls
95 }
96 }
97}