Skip to content

Commit bfc9ccf

Browse files
committed
serde_derive: rewrite with_bound without filter/chain/vec allocation
1 parent 681270e commit bfc9ccf

File tree

1 file changed

+36
-28
lines changed

1 file changed

+36
-28
lines changed

serde_derive/src/bound.rs

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -274,39 +274,47 @@ pub fn with_bound(
274274

275275
let relevant_type_params = visitor.relevant_type_params;
276276
let associated_type_usage = visitor.associated_type_usage;
277-
let new_predicates = generics
278-
.type_params()
279-
.map(|param| param.ident.clone())
280-
.filter(|id| relevant_type_params.contains(id))
281-
.map(|id| syn::TypePath {
282-
qself: None,
283-
path: id.into(),
284-
})
285-
.chain(associated_type_usage.into_iter().cloned())
286-
.map(|bounded_ty| {
287-
syn::WherePredicate::Type(syn::PredicateType {
288-
lifetimes: None,
289-
// the type parameter that is being bounded e.g. T
290-
bounded_ty: syn::Type::Path(bounded_ty),
291-
colon_token: <Token![:]>::default(),
292-
// the bound e.g. Serialize
293-
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
277+
278+
fn make_where_bounded_type(
279+
bounded_ty: syn::TypePath,
280+
bound: &syn::Path,
281+
) -> syn::WherePredicate {
282+
syn::WherePredicate::Type(syn::PredicateType {
283+
lifetimes: None,
284+
// the type parameter that is being bounded e.g. T
285+
bounded_ty: syn::Type::Path(bounded_ty),
286+
colon_token: <Token![:]>::default(),
287+
// the bound e.g. Serialize
288+
bounds: {
289+
let mut punct = Punctuated::new();
290+
punct.push(syn::TypeParamBound::Trait(syn::TraitBound {
294291
paren_token: None,
295292
modifier: syn::TraitBoundModifier::None,
296293
lifetimes: None,
297294
path: bound.clone(),
298-
})]
299-
.into_iter()
300-
.collect(),
301-
})
302-
});
295+
}));
296+
punct
297+
},
298+
})
299+
}
303300

304-
let mut generics = generics.clone();
305-
generics
306-
.make_where_clause()
307-
.predicates
308-
.extend(new_predicates);
309-
generics
301+
let mut dst_generics = generics.clone();
302+
let dst_predicates = &mut dst_generics.make_where_clause().predicates;
303+
for param in generics.type_params() {
304+
let id = &param.ident;
305+
if !relevant_type_params.contains(id) {
306+
continue;
307+
}
308+
let bounded_ty = syn::TypePath {
309+
qself: None,
310+
path: id.clone().into(),
311+
};
312+
dst_predicates.push(make_where_bounded_type(bounded_ty, bound));
313+
}
314+
for bounded_ty in associated_type_usage {
315+
dst_predicates.push(make_where_bounded_type(bounded_ty.clone(), bound));
316+
}
317+
dst_generics
310318
}
311319

312320
pub fn with_self_bound(

0 commit comments

Comments
 (0)