Repository: serde-rs/serde
File: serde_derive/src/bound.rs (Rust)

Code before:
    predicates: &[syn::WherePredicate],
) -> syn::Generics {
    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .extend(predicates.into_iter().cloned());
    generics
}

pub fn with_where_predicates_from_fields<F, W>(
    cont: &Container,
    generics: &syn::Generics,
    trait_bound: &syn::Path,
    from_field: F,
    gen_bound_where: W,
) -> syn::Generics
where
    F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
    W: for<'a> Fn(&attr::Field) -> bool,
{
    let predicates = cont.data
        .all_fields()
        .flat_map(|field| {
            let field_ty = field.ty;
            let field_bound: Option<syn::WherePredicate> = match (field_ty, gen_bound_where(&field.attrs)) {
                (&syn::Type::Path(ref ty_path), true) => match (ty_path.path.segments.first(), generics.params.first()) {
                    (Some(syn::punctuated::Pair::Punctuated(ref t, _)), Some(syn::punctuated::Pair::End(&syn::GenericParam::Type(ref generic_ty))))
                        if generic_ty.ident == t.ident =>
                    {
                        let predicate: syn::WherePredicate = parse_quote!(#field_ty: #trait_bound);
                        Some(predicate)
                    },
                    _ => None
                },
                (_, _) => None
            };
            field_bound.into_iter().chain(from_field(&field.attrs).into_iter().flat_map(|predicates| predicates.to_vec()))
        });

    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .extend(predicates);
    generics
}

// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//

Review comment (suggestion):
Please make this work even if the associated type is not from the first generic parameter.

```rust
#[derive(Serialize, Deserialize)]
struct AssocDerive<S, T: AssocSerde> {
    s: S,
    assoc: T::Assoc,
}
```

Code after:
    predicates: &[syn::WherePredicate],
) -> syn::Generics {
    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .extend(predicates.into_iter().cloned());
    generics
}

pub fn with_where_predicates_from_fields<F, W>(
    cont: &Container,
    generics: &syn::Generics,
    trait_bound: &syn::Path,
    from_field: F,
    gen_bound_where: W,
) -> syn::Generics
where
    F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
    W: Fn(&attr::Field) -> bool,
{
    let predicates = cont.data
        .all_fields()
        .flat_map(|field| {
            let field_ty = field.ty;
            let matching_generic = |t: &syn::PathSegment, g: &syn::GenericParam| match *g {
                syn::GenericParam::Type(ref generic_ty)
                    if generic_ty.ident == t.ident => true,
                _ => false
            };

            let mut field_bound: Option<syn::WherePredicate> = None;
            if let syn::Type::Path(ref ty_path) = *field_ty {
                field_bound = match (gen_bound_where(&field.attrs), ty_path.path.segments.first()) {
                    (true, Some(syn::punctuated::Pair::Punctuated(ref t, _))) =>
                        if generics.params.iter().any(|g| matching_generic(t, g)) {
                            Some(parse_quote!(#field_ty: #trait_bound))
                        } else {None},
                    (_, _) => None
                };
            }
            field_bound.into_iter().chain(from_field(&field.attrs).into_iter().flat_map(|predicates| predicates.to_vec()))
        });

    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .extend(predicates);
    generics
}

// Puts the given bound on any generic type parameters that are used in fields