aboutsummaryrefslogtreecommitdiffstats
path: root/components/style_derive/compute_squared_distance.rs
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2018-03-11 14:53:33 +0100
committerAnthony Ramine <n.oxyde@gmail.com>2018-03-12 09:48:24 +0100
commit6f7425059c69e6ad41589f32f5a0465a7bfca8cc (patch)
tree9e1e14623327849c244c9a05f4b4da5d7fcfca2d /components/style_derive/compute_squared_distance.rs
parent5cc2d7c4b3813af240fec6b01c8f4895202be7f9 (diff)
downloadservo-6f7425059c69e6ad41589f32f5a0465a7bfca8cc.tar.gz
servo-6f7425059c69e6ad41589f32f5a0465a7bfca8cc.zip
Opt out of bounds on type params for #[derive(ComputeSquaredDistance)]
Diffstat (limited to 'components/style_derive/compute_squared_distance.rs')
-rw-r--r--components/style_derive/compute_squared_distance.rs95
1 files changed, 62 insertions, 33 deletions
diff --git a/components/style_derive/compute_squared_distance.rs b/components/style_derive/compute_squared_distance.rs
index 6254340e358..c978751054d 100644
--- a/components/style_derive/compute_squared_distance.rs
+++ b/components/style_derive/compute_squared_distance.rs
@@ -4,48 +4,67 @@
use animate::AnimationVariantAttrs;
use cg;
+use darling::util::IdentList;
use quote::Tokens;
use syn::{DeriveInput, Path};
use synstructure;
-pub fn derive(input: DeriveInput) -> Tokens {
- let name = &input.ident;
- let trait_path = parse_quote!(values::distance::ComputeSquaredDistance);
- 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::<DistanceInputAttrs>(&input);
- let s = synstructure::Structure::new(&input);
- let mut append_error_clause = s.variants().len() > 1;
-
- let mut match_body = s.variants().iter().fold(quote!(), |body, variant| {
- let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
- if attrs.error {
- append_error_clause = true;
- return body;
+ 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::distance::ComputeSquaredDistance),
+ );
}
+ }
- let (this_pattern, this_info) = cg::ref_pattern(&variant, "this");
- let (other_pattern, other_info) = cg::ref_pattern(&variant, "other");
- let sum = if this_info.is_empty() {
- quote! { ::values::distance::SquaredDistance::from_sqrt(0.) }
- } else {
- let mut sum = quote!();
- sum.append_separated(this_info.iter().zip(&other_info).map(|(this, other)| {
- where_clause.add_trait_bound(&this.ast().ty);
- quote! {
- ::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)?
+ let (mut match_body, append_error_clause) = {
+ let s = synstructure::Structure::new(&input);
+ let mut append_error_clause = s.variants().len() > 1;
+
+ let match_body = s.variants().iter().fold(quote!(), |body, variant| {
+ let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
+ if attrs.error {
+ append_error_clause = true;
+ return body;
+ }
+
+ let (this_pattern, this_info) = cg::ref_pattern(&variant, "this");
+ let (other_pattern, other_info) = cg::ref_pattern(&variant, "other");
+ let sum = if this_info.is_empty() {
+ quote! { ::values::distance::SquaredDistance::from_sqrt(0.) }
+ } else {
+ let mut sum = quote!();
+ sum.append_separated(this_info.iter().zip(&other_info).map(|(this, other)| {
+ let field_attrs = cg::parse_field_attrs::<DistanceFieldAttrs>(&this.ast());
+ if field_attrs.field_bound {
+ let ty = &this.ast().ty;
+ cg::add_predicate(
+ &mut where_clause,
+ parse_quote!(#ty: ::values::distance::ComputeSquaredDistance),
+ );
+ }
+ quote! {
+ ::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)?
+ }
+ }), quote!(+));
+ sum
+ };
+ quote! {
+ #body
+ (&#this_pattern, &#other_pattern) => {
+ Ok(#sum)
}
- }), quote!(+));
- sum
- };
- quote! {
- #body
- (&#this_pattern, &#other_pattern) => {
- Ok(#sum)
}
- }
- });
+ });
+
+ (match_body, append_error_clause)
+ };
+ input.generics.where_clause = where_clause;
if append_error_clause {
if let Some(fallback) = input_attrs.fallback {
@@ -57,6 +76,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::distance::ComputeSquaredDistance for #name #ty_generics #where_clause {
#[allow(unused_variables, unused_imports)]
@@ -77,4 +99,11 @@ pub fn derive(input: DeriveInput) -> Tokens {
#[derive(Default, FromDeriveInput)]
struct DistanceInputAttrs {
fallback: Option<Path>,
+ no_bound: Option<IdentList>,
+}
+
+#[darling(attributes(distance), default)]
+#[derive(Default, FromField)]
+struct DistanceFieldAttrs {
+ field_bound: bool,
}