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
103
104
105
106
107
use std::iter;
use pmutil::ToTokensExt;
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{punctuated::Pair, *};
use crate::def_site;
mod generics;
#[derive(Debug, Clone)]
pub struct Derive<'a> {
input: &'a DeriveInput,
out: ItemImpl,
}
impl<'a> Derive<'a> {
pub fn new(input: &'a DeriveInput) -> Self {
let (generics, self_ty) = {
let params = input
.generics
.params
.clone()
.into_pairs()
.map(|mut pair| {
if let GenericParam::Type(ref mut t) = *pair.value_mut() {
t.eq_token = None;
t.default = None;
}
pair
})
.collect();
let generics = Generics {
params,
gt_token: input.generics.gt_token,
lt_token: input.generics.lt_token,
where_clause: input.generics.where_clause.clone(),
};
let ty: Box<Type> = {
let (_, ty_generics, _) = input.generics.split_for_impl();
let mut t = TokenStream::new();
input.ident.to_tokens(&mut t);
ty_generics.to_tokens(&mut t);
Box::new(parse(t.dump().into()).unwrap_or_else(|err| {
panic!("failed to parse type: {}\nType: {}", err, t.dump())
}))
};
(generics, ty)
};
Derive {
input,
out: ItemImpl {
attrs: vec![],
impl_token: def_site(),
brace_token: def_site(),
defaultness: None,
unsafety: None,
generics,
trait_: None,
self_ty,
items: Default::default(),
},
}
}
pub fn defaultness(&mut self, defaultness: Option<token::Default>) {
self.out.defaultness = defaultness;
}
pub fn unsafety(&mut self, unsafety: Option<token::Unsafe>) {
self.out.unsafety = unsafety;
}
pub fn input(&self) -> &DeriveInput {
self.input
}
pub fn append_to(mut self, item: ItemImpl) -> ItemImpl {
assert_eq!(self.out.trait_, None);
if !self.out.generics.params.empty_or_trailing() {
self.out.generics.params.push_punct(def_site());
}
self.out
.generics
.params
.extend(item.generics.params.into_pairs());
self.out.trait_ = item.trait_;
self.out.attrs.extend(item.attrs);
self.out.items.extend(item.items);
self.out
}
}