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(<[syn
::WherePredicate
]>::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(<[syn
::WherePredicate
]>::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(_
) => {}
187 #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
192 fn visit_path_segment(&mut self, segment
: &'ast syn
::PathSegment
) {
193 self.visit_path_arguments(&segment
.arguments
);
196 fn visit_path_arguments(&mut self, arguments
: &'ast syn
::PathArguments
) {
198 syn
::PathArguments
::None
=> {}
199 syn
::PathArguments
::AngleBracketed(arguments
) => {
200 for arg
in &arguments
.args
{
202 syn
::GenericArgument
::Type(arg
) => self.visit_type(arg
),
203 syn
::GenericArgument
::Binding(arg
) => self.visit_type(&arg
.ty
),
204 syn
::GenericArgument
::Lifetime(_
)
205 | syn
::GenericArgument
::Constraint(_
)
206 | syn
::GenericArgument
::Const(_
) => {}
210 syn
::PathArguments
::Parenthesized(arguments
) => {
211 for argument
in &arguments
.inputs
{
212 self.visit_type(argument
);
214 self.visit_return_type(&arguments
.output
);
219 fn visit_return_type(&mut self, return_type
: &'ast syn
::ReturnType
) {
221 syn
::ReturnType
::Default
=> {}
222 syn
::ReturnType
::Type(_
, output
) => self.visit_type(output
),
226 fn visit_type_param_bound(&mut self, bound
: &'ast syn
::TypeParamBound
) {
228 syn
::TypeParamBound
::Trait(bound
) => self.visit_path(&bound
.path
),
229 syn
::TypeParamBound
::Lifetime(_
) => {}
233 // Type parameter should not be considered used by a macro path.
235 // struct TypeMacro<T> {
237 // marker: PhantomData<T>,
239 fn visit_macro(&mut self, _mac
: &'ast syn
::Macro
) {}
242 let all_type_params
= generics
244 .map(|param
| param
.ident
.clone())
247 let mut visitor
= FindTyParams
{
249 relevant_type_params
: HashSet
::new(),
250 associated_type_usage
: Vec
::new(),
253 Data
::Enum(variants
) => {
254 for variant
in variants
.iter() {
255 let relevant_fields
= variant
258 .filter(|field
| filter(&field
.attrs
, Some(&variant
.attrs
)));
259 for field
in relevant_fields
{
260 visitor
.visit_field(field
.original
);
264 Data
::Struct(_
, fields
) => {
265 for field
in fields
.iter().filter(|field
| filter(&field
.attrs
, None
)) {
266 visitor
.visit_field(field
.original
);
271 let relevant_type_params
= visitor
.relevant_type_params
;
272 let associated_type_usage
= visitor
.associated_type_usage
;
273 let new_predicates
= generics
275 .map(|param
| param
.ident
.clone())
276 .filter(|id
| relevant_type_params
.contains(id
))
277 .map(|id
| syn
::TypePath
{
281 .chain(associated_type_usage
.into_iter().cloned())
283 syn
::WherePredicate
::Type(syn
::PredicateType
{
285 // the type parameter that is being bounded e.g. T
286 bounded_ty
: syn
::Type
::Path(bounded_ty
),
287 colon_token
: <Token
![:]>::default(),
288 // the bound e.g. Serialize
289 bounds
: vec
![syn
::TypeParamBound
::Trait(syn
::TraitBound
{
291 modifier
: syn
::TraitBoundModifier
::None
,
300 let mut generics
= generics
.clone();
304 .extend(new_predicates
);
308 pub fn with_self_bound(
310 generics
: &syn
::Generics
,
313 let mut generics
= generics
.clone();
317 .push(syn
::WherePredicate
::Type(syn
::PredicateType
{
319 // the type that is being bounded e.g. MyStruct<'a, T>
320 bounded_ty
: type_of_item(cont
),
321 colon_token
: <Token
![:]>::default(),
322 // the bound e.g. Default
323 bounds
: vec
![syn
::TypeParamBound
::Trait(syn
::TraitBound
{
325 modifier
: syn
::TraitBoundModifier
::None
,
335 pub fn with_lifetime_bound(generics
: &syn
::Generics
, lifetime
: &str) -> syn
::Generics
{
336 let bound
= syn
::Lifetime
::new(lifetime
, Span
::call_site());
337 let def
= syn
::LifetimeDef
{
339 lifetime
: bound
.clone(),
341 bounds
: Punctuated
::new(),
344 let params
= Some(syn
::GenericParam
::Lifetime(def
))
346 .chain(generics
.params
.iter().cloned().map(|mut param
| {
348 syn
::GenericParam
::Lifetime(param
) => {
349 param
.bounds
.push(bound
.clone());
351 syn
::GenericParam
::Type(param
) => {
354 .push(syn
::TypeParamBound
::Lifetime(bound
.clone()));
356 syn
::GenericParam
::Const(_
) => {}
368 fn type_of_item(cont
: &Container
) -> syn
::Type
{
369 syn
::Type
::Path(syn
::TypePath
{
373 segments
: vec
![syn
::PathSegment
{
374 ident
: cont
.ident
.clone(),
375 arguments
: syn
::PathArguments
::AngleBracketed(
376 syn
::AngleBracketedGenericArguments
{
378 lt_token
: <Token
![<]>::default(),
383 .map(|param
| match param
{
384 syn
::GenericParam
::Type(param
) => {
385 syn
::GenericArgument
::Type(syn
::Type
::Path(syn
::TypePath
{
387 path
: param
.ident
.clone().into(),
390 syn
::GenericParam
::Lifetime(param
) => {
391 syn
::GenericArgument
::Lifetime(param
.lifetime
.clone())
393 syn
::GenericParam
::Const(_
) => {
394 panic
!("Serde does not support const generics yet");
398 gt_token
: <Token
![>]>::default(),