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
use proc_macro2::TokenStream;
use quote::{TokenStreamExt, ToTokens};
use syn::{GenericParam, Generics, Path, TraitBound, TraitBoundModifier, TypeParamBound};
use codegen::TraitImpl;
use usage::IdentSet;
pub trait OuterFromImpl<'a> {
fn trait_path(&self) -> Path;
fn base(&'a self) -> &'a TraitImpl<'a>;
fn trait_bound(&self) -> Path {
self.trait_path()
}
fn wrap<T: ToTokens>(&'a self, body: T, tokens: &mut TokenStream) {
let base = self.base();
let trayt = self.trait_path();
let ty_ident = base.ident;
let used = base.used_type_params();
let generics = compute_impl_bounds(self.trait_bound(), base.generics.clone(), &used);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
tokens.append_all(quote!(
impl #impl_generics #trayt for #ty_ident #ty_generics
#where_clause
{
#body
}
));
}
}
fn compute_impl_bounds(bound: Path, mut generics: Generics, applies_to: &IdentSet) -> Generics {
if generics.params.is_empty() {
return generics;
}
let added_bound = TypeParamBound::Trait(TraitBound {
paren_token: None,
modifier: TraitBoundModifier::None,
lifetimes: None,
path: bound,
});
for param in generics.params.iter_mut() {
if let GenericParam::Type(ref mut typ) = *param {
if applies_to.contains(&typ.ident) {
typ.bounds.push(added_bound.clone());
}
}
}
generics
}