Opt out of trait bounds on type params for #[derive(Animate)]

This allows us to not generate trait bounds for field types anymore,
by excluding bounds for type parameters used only in fields annotated
with `#[animation(error)]`.

The syntax is `#[animation(no_bound(Foo, Bar))]` where `Foo` is a type
parameter for the type on which we derive things. Ideally this should
be an attribute on the type parameter but this isn't stable yet.
This commit is contained in:
Anthony Ramine 2018-03-11 14:53:33 +01:00
parent 29e10d4f88
commit 5cc2d7c4b3
3 changed files with 24 additions and 13 deletions

View file

@ -2,23 +2,31 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cg::{self, WhereClause};
use cg;
use darling::util::IdentList;
use quote::Tokens;
use syn::{DeriveInput, Path};
use synstructure::{Structure, VariantInfo};
pub fn derive(input: DeriveInput) -> Tokens {
let name = &input.ident;
let trait_path = parse_quote!(values::animated::Animate);
let (impl_generics, ty_generics, mut where_clause) =
cg::trait_parts(&input, &trait_path);
pub fn derive(mut input: DeriveInput) -> Tokens {
let input_attrs = cg::parse_input_attrs::<AnimateInputAttrs>(&input);
let no_bound = input_attrs.no_bound.unwrap_or_default();
let mut where_clause = input.generics.where_clause.take();
for param in input.generics.type_params() {
if !no_bound.contains(&param.ident) {
cg::add_predicate(
&mut where_clause,
parse_quote!(#param: ::values::animated::Animate),
);
}
}
input.generics.where_clause = where_clause;
let s = Structure::new(&input);
let mut append_error_clause = s.variants().len() > 1;
let mut match_body = s.variants().iter().fold(quote!(), |body, variant| {
let arm = match derive_variant_arm(variant, &mut where_clause) {
let arm = match derive_variant_arm(variant) {
Ok(arm) => arm,
Err(()) => {
append_error_clause = true;
@ -38,6 +46,9 @@ pub fn derive(input: DeriveInput) -> Tokens {
}
}
let name = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
quote! {
impl #impl_generics ::values::animated::Animate for #name #ty_generics #where_clause {
#[allow(unused_variables, unused_imports)]
@ -55,10 +66,7 @@ pub fn derive(input: DeriveInput) -> Tokens {
}
}
fn derive_variant_arm(
variant: &VariantInfo,
where_clause: &mut WhereClause,
) -> Result<Tokens, ()> {
fn derive_variant_arm(variant: &VariantInfo) -> Result<Tokens, ()> {
let variant_attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
if variant_attrs.error {
return Err(());
@ -78,7 +86,6 @@ fn derive_variant_arm(
let #result = ::std::clone::Clone::clone(#this);
}
} else {
where_clause.add_trait_bound(&result.ast().ty);
quote! {
let #result =
::values::animated::Animate::animate(#this, #other, procedure)?;
@ -97,6 +104,7 @@ fn derive_variant_arm(
#[derive(Default, FromDeriveInput)]
struct AnimateInputAttrs {
fallback: Option<Path>,
no_bound: Option<IdentList>,
}
#[darling(attributes(animation), default)]