abi_stable_derive/stable_abi/
generic_params.rs

1use super::*;
2
3use crate::utils::{expr_from_ident, type_from_ident};
4
5pub(super) struct GenericParams<'a> {
6    generics: &'a syn::Generics,
7    type_param_range: StartLen,
8    const_param_range: StartLen,
9    ctokens: &'a CommonTokens<'a>,
10}
11
12impl<'a> GenericParams<'a> {
13    pub(super) fn new(
14        ds: &'a DataStructure<'a>,
15        shared_vars: &mut SharedVars<'a>,
16        config: &'a StableAbiOptions<'a>,
17        ctokens: &'a CommonTokens<'a>,
18    ) -> Self {
19        let generics = ds.generics;
20        let arenas = shared_vars.arenas();
21        let type_param_range: StartLen = {
22            let shared_vars = std::cell::RefCell::new(&mut *shared_vars);
23            let phantom_type_params = config.phantom_type_params.iter().map(|ty| {
24                let ty: &'a syn::Type = ty;
25                shared_vars
26                    .borrow_mut()
27                    .push_type(LayoutConstructor::Regular, ty)
28                    .to_u10()
29            });
30
31            let type_param_bounds = config
32                .type_param_bounds
33                .iter()
34                .filter(|(_, bounds)| **bounds == ASTypeParamBound::NoBound)
35                .map(|(type_param, &bounds)| {
36                    let type_ = {
37                        let x = type_from_ident(type_param.clone());
38                        arenas.alloc(x)
39                    };
40
41                    let layout_ctor = bounds.into_::<LayoutConstructor>();
42                    shared_vars
43                        .borrow_mut()
44                        .push_type(layout_ctor, type_)
45                        .to_u10()
46                });
47
48            let mut iter = type_param_bounds.chain(phantom_type_params);
49            let first = iter.next().unwrap_or(0);
50            let mut last = first;
51            for elem in iter {
52                assert!(
53                    first <= elem,
54                    "BUG:\
55                    The type parameters must all be stored contiguously in the SharedVars.\n\
56                    last={} elem={}\
57                    ",
58                    last,
59                    elem,
60                );
61                last = elem;
62            }
63            StartLen {
64                start: first,
65                len: last - first,
66            }
67        };
68
69        let const_param_range = {
70            let const_params = generics
71                .const_params()
72                .map(|cp| arenas.alloc(expr_from_ident(cp.ident.clone())))
73                .chain(config.phantom_const_params.iter().cloned());
74            shared_vars.extend_with_constants(const_params)
75        };
76
77        Self {
78            generics,
79            type_param_range,
80            const_param_range,
81            ctokens,
82        }
83    }
84}
85
86impl<'a> ToTokens for GenericParams<'a> {
87    fn to_tokens(&self, ts: &mut TokenStream2) {
88        let lifetimes = &self
89            .generics
90            .lifetimes()
91            .map(|x| &x.lifetime)
92            .collect::<Vec<_>>();
93        let type_param_range = self.type_param_range.tokenizer(self.ctokens.as_ref());
94        let const_param_range = self.const_param_range.tokenizer(self.ctokens.as_ref());
95        quote!(abi_stable::tl_genparams!(
96            #(#lifetimes),*;
97            #type_param_range;
98            #const_param_range
99        ))
100        .to_tokens(ts);
101    }
102}