moverox_codegen/
generics.rs1use std::collections::HashSet;
2
3use quote::quote;
4use unsynn::{Ident, ToTokens as _, TokenStream};
5
6use crate::Result;
7
8pub(super) trait GenericsExt {
9 fn to_rust(&self) -> TokenStream;
10
11 fn type_generics(
13 &self,
14 thecrate: &TokenStream,
15 otw_types: HashSet<Ident>,
16 ) -> Result<TokenStream>;
17
18 fn phantoms(&self) -> impl Iterator<Item = &Ident>;
19}
20
21impl GenericsExt for move_syn::Generics {
22 fn to_rust(&self) -> TokenStream {
23 let idents = self.generics().map(|g| &g.ident);
24 quote! {
25 <#(#idents),*>
26 }
27 }
28
29 fn type_generics(
30 &self,
31 thecrate: &TokenStream,
32 mut otw_types: HashSet<Ident>,
33 ) -> Result<TokenStream> {
34 let idents: Vec<_> = self
35 .generics()
36 .map(|g| &g.ident)
37 .map(|ident| {
38 if otw_types.remove(ident) {
39 quote!(#ident = #thecrate::Otw)
40 } else {
41 ident.to_token_stream()
42 }
43 })
44 .collect();
45
46 if !otw_types.is_empty() {
47 let excess = otw_types
48 .into_iter()
49 .map(|ident| ident.to_string())
50 .reduce(|a, b| a + ", " + &b)
51 .unwrap_or_default();
52 return Err(format!("Not a type parameter of this datatype: {excess}").into());
53 }
54
55 Ok(quote! {
56 <#(#idents),*>
57 })
58 }
59
60 fn phantoms(&self) -> impl Iterator<Item = &Ident> {
61 self.generics()
62 .filter(|d| d.phantom.is_some())
63 .map(|d| &d.ident)
64 }
65}