1 use std
::collections
::HashSet
;
4 use syn
::punctuated
::{Pair, Punctuated}
;
6 use internals
::ast
::{Container, Data}
;
7 use internals
::{attr, ungroup}
;
11 // Remove the default from every type parameter because in the generated impls
12 // they look like associated types: "error: associated type bindings are not
14 pub fn without_defaults(generics
: &syn
::Generics
) -> syn
::Generics
{
19 .map(|param
| match param
{
20 syn
::GenericParam
::Type(param
) => syn
::GenericParam
::Type(syn
::TypeParam
{
32 pub fn with_where_predicates(
33 generics
: &syn
::Generics
,
34 predicates
: &[syn
::WherePredicate
],
36 let mut generics
= generics
.clone();
40 .extend(predicates
.iter().cloned());
44 pub fn with_where_predicates_from_fields(
46 generics
: &syn
::Generics
,
47 from_field
: fn(&attr
::Field
) -> Option
<&[syn
::WherePredicate
]>,
52 .filter_map(|field
| from_field(&field
.attrs
))
53 .flat_map(|predicates
| predicates
.to_vec());
55 let mut generics
= generics
.clone();
56 generics
.make_where_clause().predicates
.extend(predicates
);
60 pub fn with_where_predicates_from_variants(
62 generics
: &syn
::Generics
,
63 from_variant
: fn(&attr
::Variant
) -> Option
<&[syn
::WherePredicate
]>,
65 let variants
= match &cont
.data
{
66 Data
::Enum(variants
) => variants
,
67 Data
::Struct(_
, _
) => {
68 return generics
.clone();
72 let predicates
= variants
74 .filter_map(|variant
| from_variant(&variant
.attrs
))
75 .flat_map(|predicates
| predicates
.to_vec());
77 let mut generics
= generics
.clone();
78 generics
.make_where_clause().predicates
.extend(predicates
);
82 // Puts the given bound on any generic type parameters that are used in fields
83 // for which filter returns true.
85 // For example, the following struct needs the bound `A: Serialize, B:
88 // struct S<'b, A, B: 'b, C> {
91 // #[serde(skip_serializing)]
96 generics
: &syn
::Generics
,
97 filter
: fn(&attr
::Field
, Option
<&attr
::Variant
>) -> bool
,
100 struct FindTyParams
<'ast
> {
101 // Set of all generic type parameters on the current struct (A, B, C in
102 // the example). Initialized up front.
103 all_type_params
: HashSet
<syn
::Ident
>,
105 // Set of generic type parameters used in fields for which filter
106 // returns true (A and B in the example). Filled in as the visitor sees
108 relevant_type_params
: HashSet
<syn
::Ident
>,
110 // Fields whose type is an associated type of one of the generic type
112 associated_type_usage
: Vec
<&'ast syn
::TypePath
>,
115 impl<'ast
> FindTyParams
<'ast
> {
116 fn visit_field(&mut self, field
: &'ast syn
::Field
) {
117 if let syn
::Type
::Path(ty
) = ungroup(&field
.ty
) {
118 if let Some(Pair
::Punctuated(t
, _
)) = ty
.path
.segments
.pairs().next() {
119 if self.all_type_params
.contains(&t
.ident
) {
120 self.associated_type_usage
.push(ty
);
124 self.visit_type(&field
.ty
);
127 fn visit_path(&mut self, path
: &'ast syn
::Path
) {
128 if let Some(seg
) = path
.segments
.last() {
129 if seg
.ident
== "PhantomData" {
130 // Hardcoded exception, because PhantomData<T> implements
131 // Serialize and Deserialize whether or not T implements it.
135 if path
.leading_colon
.is_none() && path
.segments
.len() == 1 {
136 let id
= &path
.segments
[0].ident
;
137 if self.all_type_params
.contains(id
) {
138 self.relevant_type_params
.insert(id
.clone());
141 for segment
in &path
.segments
{
142 self.visit_path_segment(segment
);
146 // Everything below is simply traversing the syntax tree.
148 fn visit_type(&mut self, ty
: &'ast syn
::Type
) {
150 syn
::Type
::Array(ty
) => self.visit_type(&ty
.elem
),
151 syn
::Type
::BareFn(ty
) => {
152 for arg
in &ty
.inputs
{
153 self.visit_type(&arg
.ty
);
155 self.visit_return_type(&ty
.output
);
157 syn
::Type
::Group(ty
) => self.visit_type(&ty
.elem
),
158 syn
::Type
::ImplTrait(ty
) => {
159 for bound
in &ty
.bounds
{
160 self.visit_type_param_bound(bound
);
163 syn
::Type
::Macro(ty
) => self.visit_macro(&ty
.mac
),
164 syn
::Type
::Paren(ty
) => self.visit_type(&ty
.elem
),
165 syn
::Type
::Path(ty
) => {
166 if let Some(qself
) = &ty
.qself
{
167 self.visit_type(&qself
.ty
);
169 self.visit_path(&ty
.path
);
171 syn
::Type
::Ptr(ty
) => self.visit_type(&ty
.elem
),
172 syn
::Type
::Reference(ty
) => self.visit_type(&ty
.elem
),
173 syn
::Type
::Slice(ty
) => self.visit_type(&ty
.elem
),
174 syn
::Type
::TraitObject(ty
) => {
175 for bound
in &ty
.bounds
{
176 self.visit_type_param_bound(bound
);
179 syn
::Type
::Tuple(ty
) => {
180 for elem
in &ty
.elems
{
181 self.visit_type(elem
);
185 syn
::Type
::Infer(_
) | syn
::Type
::Never(_
) | syn
::Type
::Verbatim(_
) => {}
188 syn
::Type
::__TestExhaustive(_
) => unimplemented
!(),
194 fn visit_path_segment(&mut self, segment
: &'ast syn
::PathSegment
) {
195 self.visit_path_arguments(&segment
.arguments
);
198 fn visit_path_arguments(&mut self, arguments
: &'ast syn
::PathArguments
) {
200 syn
::PathArguments
::None
=> {}
201 syn
::PathArguments
::AngleBracketed(arguments
) => {
202 for arg
in &arguments
.args
{
204 syn
::GenericArgument
::Type(arg
) => self.visit_type(arg
),
205 syn
::GenericArgument
::Binding(arg
) => self.visit_type(&arg
.ty
),
206 syn
::GenericArgument
::Lifetime(_
)
207 | syn
::GenericArgument
::Constraint(_
)
208 | syn
::GenericArgument
::Const(_
) => {}
212 syn
::PathArguments
::Parenthesized(arguments
) => {
213 for argument
in &arguments
.inputs
{
214 self.visit_type(argument
);
216 self.visit_return_type(&arguments
.output
);
221 fn visit_return_type(&mut self, return_type
: &'ast syn
::ReturnType
) {
223 syn
::ReturnType
::Default
=> {}
224 syn
::ReturnType
::Type(_
, output
) => self.visit_type(output
),
228 fn visit_type_param_bound(&mut self, bound
: &'ast syn
::TypeParamBound
) {
230 syn
::TypeParamBound
::Trait(bound
) => self.visit_path(&bound
.path
),
231 syn
::TypeParamBound
::Lifetime(_
) => {}
235 // Type parameter should not be considered used by a macro path.
237 // struct TypeMacro<T> {
239 // marker: PhantomData<T>,
241 fn visit_macro(&mut self, _mac
: &'ast syn
::Macro
) {}
244 let all_type_params
= generics
246 .map(|param
| param
.ident
.clone())
249 let mut visitor
= FindTyParams
{
251 relevant_type_params
: HashSet
::new(),
252 associated_type_usage
: Vec
::new(),
255 Data
::Enum(variants
) => {
256 for variant
in variants
.iter() {
257 let relevant_fields
= variant
260 .filter(|field
| filter(&field
.attrs
, Some(&variant
.attrs
)));
261 for field
in relevant_fields
{
262 visitor
.visit_field(field
.original
);
266 Data
::Struct(_
, fields
) => {
267 for field
in fields
.iter().filter(|field
| filter(&field
.attrs
, None
)) {
268 visitor
.visit_field(field
.original
);
273 let relevant_type_params
= visitor
.relevant_type_params
;
274 let associated_type_usage
= visitor
.associated_type_usage
;
275 let new_predicates
= generics
277 .map(|param
| param
.ident
.clone())
278 .filter(|id
| relevant_type_params
.contains(id
))
279 .map(|id
| syn
::TypePath
{
283 .chain(associated_type_usage
.into_iter().cloned())
285 syn
::WherePredicate
::Type(syn
::PredicateType
{
287 // the type parameter that is being bounded e.g. T
288 bounded_ty
: syn
::Type
::Path(bounded_ty
),
289 colon_token
: <Token
![:]>::default(),
290 // the bound e.g. Serialize
291 bounds
: vec
![syn
::TypeParamBound
::Trait(syn
::TraitBound
{
293 modifier
: syn
::TraitBoundModifier
::None
,
302 let mut generics
= generics
.clone();
306 .extend(new_predicates
);
310 pub fn with_self_bound(
312 generics
: &syn
::Generics
,
315 let mut generics
= generics
.clone();
319 .push(syn
::WherePredicate
::Type(syn
::PredicateType
{
321 // the type that is being bounded e.g. MyStruct<'a, T>
322 bounded_ty
: type_of_item(cont
),
323 colon_token
: <Token
![:]>::default(),
324 // the bound e.g. Default
325 bounds
: vec
![syn
::TypeParamBound
::Trait(syn
::TraitBound
{
327 modifier
: syn
::TraitBoundModifier
::None
,
337 pub fn with_lifetime_bound(generics
: &syn
::Generics
, lifetime
: &str) -> syn
::Generics
{
338 let bound
= syn
::Lifetime
::new(lifetime
, Span
::call_site());
339 let def
= syn
::LifetimeDef
{
341 lifetime
: bound
.clone(),
343 bounds
: Punctuated
::new(),
346 let params
= Some(syn
::GenericParam
::Lifetime(def
))
348 .chain(generics
.params
.iter().cloned().map(|mut param
| {
350 syn
::GenericParam
::Lifetime(param
) => {
351 param
.bounds
.push(bound
.clone());
353 syn
::GenericParam
::Type(param
) => {
356 .push(syn
::TypeParamBound
::Lifetime(bound
.clone()));
358 syn
::GenericParam
::Const(_
) => {}
370 fn type_of_item(cont
: &Container
) -> syn
::Type
{
371 syn
::Type
::Path(syn
::TypePath
{
375 segments
: vec
![syn
::PathSegment
{
376 ident
: cont
.ident
.clone(),
377 arguments
: syn
::PathArguments
::AngleBracketed(
378 syn
::AngleBracketedGenericArguments
{
380 lt_token
: <Token
![<]>::default(),
385 .map(|param
| match param
{
386 syn
::GenericParam
::Type(param
) => {
387 syn
::GenericArgument
::Type(syn
::Type
::Path(syn
::TypePath
{
389 path
: param
.ident
.clone().into(),
392 syn
::GenericParam
::Lifetime(param
) => {
393 syn
::GenericArgument
::Lifetime(param
.lifetime
.clone())
395 syn
::GenericParam
::Const(_
) => {
396 panic
!("Serde does not support const generics yet");
400 gt_token
: <Token
![>]>::default(),