Merge pull request #1213 from Osspial/assoc_type_derive
Support #[derive(Serialize, Deserialize)] when using associated types
This commit is contained in:
commit
a6e94e7122
@ -50,18 +50,39 @@ pub fn with_where_predicates(
|
|||||||
generics
|
generics
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_where_predicates_from_fields<F>(
|
pub fn with_where_predicates_from_fields<F, W>(
|
||||||
cont: &Container,
|
cont: &Container,
|
||||||
generics: &syn::Generics,
|
generics: &syn::Generics,
|
||||||
|
trait_bound: &syn::Path,
|
||||||
from_field: F,
|
from_field: F,
|
||||||
|
gen_bound_where: W,
|
||||||
) -> syn::Generics
|
) -> syn::Generics
|
||||||
where
|
where
|
||||||
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
|
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
|
||||||
|
W: Fn(&attr::Field) -> bool,
|
||||||
{
|
{
|
||||||
let predicates = cont.data
|
let predicates = cont.data
|
||||||
.all_fields()
|
.all_fields()
|
||||||
.flat_map(|field| from_field(&field.attrs))
|
.flat_map(|field| {
|
||||||
.flat_map(|predicates| predicates.to_vec());
|
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();
|
let mut generics = generics.clone();
|
||||||
generics.make_where_clause()
|
generics.make_where_clause()
|
||||||
|
@ -124,7 +124,15 @@ impl Parameters {
|
|||||||
fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generics {
|
fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generics {
|
||||||
let generics = bound::without_defaults(cont.generics);
|
let generics = bound::without_defaults(cont.generics);
|
||||||
|
|
||||||
let generics = bound::with_where_predicates_from_fields(cont, &generics, attr::Field::de_bound);
|
let delife = borrowed.de_lifetime();
|
||||||
|
let de_bound = parse_quote!(_serde::Deserialize<#delife>);
|
||||||
|
let generics = bound::with_where_predicates_from_fields(
|
||||||
|
cont,
|
||||||
|
&generics,
|
||||||
|
&de_bound,
|
||||||
|
attr::Field::de_bound,
|
||||||
|
|field| field.deserialize_with().is_none() && !field.skip_deserializing()
|
||||||
|
);
|
||||||
|
|
||||||
match cont.attrs.de_bound() {
|
match cont.attrs.de_bound() {
|
||||||
Some(predicates) => bound::with_where_predicates(&generics, predicates),
|
Some(predicates) => bound::with_where_predicates(&generics, predicates),
|
||||||
@ -136,12 +144,11 @@ fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generi
|
|||||||
attr::Default::None | attr::Default::Path(_) => generics,
|
attr::Default::None | attr::Default::Path(_) => generics,
|
||||||
};
|
};
|
||||||
|
|
||||||
let delife = borrowed.de_lifetime();
|
|
||||||
let generics = bound::with_bound(
|
let generics = bound::with_bound(
|
||||||
cont,
|
cont,
|
||||||
&generics,
|
&generics,
|
||||||
needs_deserialize_bound,
|
needs_deserialize_bound,
|
||||||
&parse_quote!(_serde::Deserialize<#delife>),
|
&de_bound,
|
||||||
);
|
);
|
||||||
|
|
||||||
bound::with_bound(
|
bound::with_bound(
|
||||||
|
@ -130,8 +130,14 @@ impl Parameters {
|
|||||||
fn build_generics(cont: &Container) -> syn::Generics {
|
fn build_generics(cont: &Container) -> syn::Generics {
|
||||||
let generics = bound::without_defaults(cont.generics);
|
let generics = bound::without_defaults(cont.generics);
|
||||||
|
|
||||||
let generics =
|
let trait_bound = parse_quote!(_serde::Serialize);
|
||||||
bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
|
let generics = bound::with_where_predicates_from_fields(
|
||||||
|
cont,
|
||||||
|
&generics,
|
||||||
|
&trait_bound,
|
||||||
|
attr::Field::ser_bound,
|
||||||
|
|field| field.serialize_with().is_none() && !field.skip_serializing()
|
||||||
|
);
|
||||||
|
|
||||||
match cont.attrs.ser_bound() {
|
match cont.attrs.ser_bound() {
|
||||||
Some(predicates) => bound::with_where_predicates(&generics, predicates),
|
Some(predicates) => bound::with_where_predicates(&generics, predicates),
|
||||||
@ -139,7 +145,7 @@ fn build_generics(cont: &Container) -> syn::Generics {
|
|||||||
cont,
|
cont,
|
||||||
&generics,
|
&generics,
|
||||||
needs_serialize_bound,
|
needs_serialize_bound,
|
||||||
&parse_quote!(_serde::Serialize),
|
&trait_bound
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,6 +539,30 @@ fn test_gen() {
|
|||||||
array: [u8; 256],
|
array: [u8; 256],
|
||||||
}
|
}
|
||||||
assert_ser::<BigArray>();
|
assert_ser::<BigArray>();
|
||||||
|
|
||||||
|
trait AssocSerde {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NoSerdeImpl;
|
||||||
|
impl AssocSerde for NoSerdeImpl {
|
||||||
|
type Assoc = u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct AssocDerive<T: AssocSerde> {
|
||||||
|
assoc: T::Assoc
|
||||||
|
}
|
||||||
|
|
||||||
|
assert::<AssocDerive<NoSerdeImpl>>();
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct AssocDeriveMulti<S, T: AssocSerde> {
|
||||||
|
s: S,
|
||||||
|
assoc: T::Assoc,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert::<AssocDeriveMulti<i32, NoSerdeImpl>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
x
Reference in New Issue
Block a user