Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix derive Data when type param bounds are defined #1058

Merged
merged 14 commits into from
Jun 30, 2020
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ You can find its changes [documented below](#060---2020-06-01).
- macOS: Timers not firing during modal loop. ([#1028] by [@xStrom])
- GTK: Directory selection now properly ignores file filters. ([#957] by [@xStrom])
- GTK: Don't crash when receiving an external command while a file dialog is visible. ([#1043] by [@jneem])
- Fix derive `Data` when type param bounds are defined ([#1058] by [@chris-zen])
chris-zen marked this conversation as resolved.
Show resolved Hide resolved
- Ensure that `update` is called after all commands. ([#1062] by [@jneem])
- Fix derive `Data` when type param bounds are defined ([#1058] by [@chris-zen])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we have the entry twice :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♂️ sorry, I messed up while merging.


### Visual

Expand Down Expand Up @@ -236,11 +238,9 @@ Last release without a changelog :(
[@jrmuizel]: https://github.com/jrmuizel
[@scholtzan]: https://github.com/scholtzan
[@covercash2]: https://github.com/covercash2
<<<<<<< HEAD
[@raphlinus]: https://github.com/raphlinus
=======
[@binomial0]: https://github.com/binomial0
>>>>>>> master
[@chris-zen]: https://github.com/chris-zen

[#599]: https://github.com/linebender/druid/pull/599
[#611]: https://github.com/linebender/druid/pull/611
Expand Down Expand Up @@ -347,6 +347,7 @@ Last release without a changelog :(
[#1049]: https://github.com/linebender/druid/pull/1049
[#1050]: https://github.com/linebender/druid/pull/1050
[#1054]: https://github.com/linebender/druid/pull/1054
[#1058]: https://github.com/linebender/druid/pull/1058
[#1062]: https://github.com/linebender/druid/pull/1062

[Unreleased]: https://github.com/linebender/druid/compare/v0.6.0...master
Expand Down
38 changes: 21 additions & 17 deletions druid-derive/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ fn derive_struct(
input: &syn::DeriveInput,
s: &DataStruct,
) -> Result<proc_macro2::TokenStream, syn::Error> {
let generics_bounds = generics_bounds(&input.generics);
let generics = &input.generics;
let ident = &input.ident;
let impl_generics = generics_bounds(&input.generics);
let (_, ty_generics, where_clause) = &input.generics.split_for_impl();

let ty = &input.ident;
let fields = Fields::parse_ast(&s.fields)?;

let diff = if fields.len() > 0 {
Expand All @@ -54,7 +54,7 @@ fn derive_struct(
};

let res = quote! {
impl<#generics_bounds> druid::Data for #ty #generics {
impl<#impl_generics> ::druid::Data for #ident #ty_generics #where_clause {
fn same(&self, other: &Self) -> bool {
#diff
}
Expand All @@ -80,14 +80,13 @@ fn derive_enum(
input: &syn::DeriveInput,
s: &DataEnum,
) -> Result<proc_macro2::TokenStream, syn::Error> {
let ty = &input.ident;
let ident = &input.ident;
let impl_generics = generics_bounds(&input.generics);
let (_, ty_generics, where_clause) = &input.generics.split_for_impl();

if is_c_style_enum(&s) {
let generics_bounds = generics_bounds(&input.generics);
let generics = &input.generics;

let res = quote! {
impl<#generics_bounds> ::druid::Data for #ty #generics {
impl<#impl_generics> ::druid::Data for #ident #ty_generics #where_clause {
fn same(&self, other: &Self) -> bool { self == other }
}
};
Expand Down Expand Up @@ -132,7 +131,7 @@ fn derive_enum(
.collect();

Ok(quote! {
(#ty :: #variant { #( #lefts ),* }, #ty :: #variant { #( #rights ),* }) => {
(#ident :: #variant { #( #lefts ),* }, #ident :: #variant { #( #rights ),* }) => {
#( #tests )&&*
}
})
Expand All @@ -148,24 +147,21 @@ fn derive_enum(

if fields.iter().filter(|field| !field.ignore).count() > 0 {
Ok(quote! {
( #ty :: #variant( #(#vars_left),* ), #ty :: #variant( #(#vars_right),* )) => {
( #ident :: #variant( #(#vars_left),* ), #ident :: #variant( #(#vars_right),* )) => {
#( #tests )&&*
}
})
} else {
Ok(quote! {
( #ty :: #variant , #ty :: #variant ) => { true }
( #ident :: #variant , #ident :: #variant ) => { true }
})
}
}
})
.collect::<Result<Vec<proc_macro2::TokenStream>, syn::Error>>()?;

let generics_bounds = generics_bounds(&input.generics);
let generics = &input.generics;

let res = quote! {
impl<#generics_bounds> ::druid::Data for #ty #generics {
impl<#impl_generics> ::druid::Data for #ident #ty_generics #where_clause {
fn same(&self, other: &Self) -> bool {
match (self, other) {
#( #cases ),*
Expand All @@ -182,7 +178,15 @@ fn generics_bounds(generics: &syn::Generics) -> proc_macro2::TokenStream {
let res = generics.params.iter().map(|gp| {
use syn::GenericParam::*;
match gp {
Type(ty) => quote_spanned!(ty.span()=> #ty : ::druid::Data),
Type(ty) => {
let ident = &ty.ident;
let bounds = &ty.bounds;
if bounds.is_empty() {
quote_spanned!(ty.span()=> #ident : ::druid::Data)
} else {
quote_spanned!(ty.span()=> #ident : #bounds + ::druid::Data)
}
}
Lifetime(lf) => quote!(#lf),
Const(cst) => quote!(#cst),
}
Expand Down
43 changes: 43 additions & 0 deletions druid-derive/tests/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ struct MultiFieldStruct {
c: String,
}

trait UserTrait {}

#[derive(Clone, Data)]
struct TypeParamForUserTraitStruct<T: UserTrait + Data> {
a: T,
}

#[derive(Clone, Data)]
struct TypeParamForUserTraitWithWhereClauseStruct<T>
where
T: UserTrait,
{
b: T,
}

#[derive(Clone, Data)]
enum TypeParamForUserTraitAndLifetimeEnum<T: UserTrait + 'static> {
V1(T),
}

#[test]
fn test_data_derive_same() {
let plain = PlainStruct;
Expand Down Expand Up @@ -70,4 +90,27 @@ fn test_data_derive_same() {
c: "Fail".to_string()
})
);

#[derive(Clone, Data)]
struct Value(u32);

impl UserTrait for Value {}

let v = TypeParamForUserTraitStruct { a: Value(1) };
assert!(v.same(&v));
assert_eq!(false, v.same(&TypeParamForUserTraitStruct { a: Value(2) }));

let v = TypeParamForUserTraitWithWhereClauseStruct { b: Value(3) };
assert!(v.same(&v));
assert_eq!(
false,
v.same(&TypeParamForUserTraitWithWhereClauseStruct { b: Value(6) })
);

let v = TypeParamForUserTraitAndLifetimeEnum::V1(Value(10));
assert!(v.same(&v));
assert_eq!(
false,
v.same(&TypeParamForUserTraitAndLifetimeEnum::V1(Value(12)))
);
}