abi_stable_derive/stable_abi/
generic_params.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use super::*;

use crate::utils::{expr_from_ident, type_from_ident};

pub(super) struct GenericParams<'a> {
    generics: &'a syn::Generics,
    type_param_range: StartLen,
    const_param_range: StartLen,
    ctokens: &'a CommonTokens<'a>,
}

impl<'a> GenericParams<'a> {
    pub(super) fn new(
        ds: &'a DataStructure<'a>,
        shared_vars: &mut SharedVars<'a>,
        config: &'a StableAbiOptions<'a>,
        ctokens: &'a CommonTokens<'a>,
    ) -> Self {
        let generics = ds.generics;
        let arenas = shared_vars.arenas();
        let type_param_range: StartLen = {
            let shared_vars = std::cell::RefCell::new(&mut *shared_vars);
            let phantom_type_params = config.phantom_type_params.iter().map(|ty| {
                let ty: &'a syn::Type = ty;
                shared_vars
                    .borrow_mut()
                    .push_type(LayoutConstructor::Regular, ty)
                    .to_u10()
            });

            let type_param_bounds = config
                .type_param_bounds
                .iter()
                .filter(|(_, bounds)| **bounds == ASTypeParamBound::NoBound)
                .map(|(type_param, &bounds)| {
                    let type_ = {
                        let x = type_from_ident(type_param.clone());
                        arenas.alloc(x)
                    };

                    let layout_ctor = bounds.into_::<LayoutConstructor>();
                    shared_vars
                        .borrow_mut()
                        .push_type(layout_ctor, type_)
                        .to_u10()
                });

            let mut iter = type_param_bounds.chain(phantom_type_params);
            let first = iter.next().unwrap_or(0);
            let mut last = first;
            for elem in iter {
                assert!(
                    first <= elem,
                    "BUG:\
                    The type parameters must all be stored contiguously in the SharedVars.\n\
                    last={} elem={}\
                    ",
                    last,
                    elem,
                );
                last = elem;
            }
            StartLen {
                start: first,
                len: last - first,
            }
        };

        let const_param_range = {
            let const_params = generics
                .const_params()
                .map(|cp| arenas.alloc(expr_from_ident(cp.ident.clone())))
                .chain(config.phantom_const_params.iter().cloned());
            shared_vars.extend_with_constants(const_params)
        };

        Self {
            generics,
            type_param_range,
            const_param_range,
            ctokens,
        }
    }
}

impl<'a> ToTokens for GenericParams<'a> {
    fn to_tokens(&self, ts: &mut TokenStream2) {
        let lifetimes = &self
            .generics
            .lifetimes()
            .map(|x| &x.lifetime)
            .collect::<Vec<_>>();
        let type_param_range = self.type_param_range.tokenizer(self.ctokens.as_ref());
        let const_param_range = self.const_param_range.tokenizer(self.ctokens.as_ref());
        quote!(abi_stable::tl_genparams!(
            #(#lifetimes),*;
            #type_param_range;
            #const_param_range
        ))
        .to_tokens(ts);
    }
}