cglue_gen/
forward.rs

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}