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}