diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 06ce911d473..e6c24bfaf8e 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -18,6 +18,7 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance}; #[animate(no_bound(UrlPaintServer))] #[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq)] #[derive(ToAnimatedValue, ToComputedValue, ToCss)] +#[distance(no_bound(UrlPaintServer))] pub struct SVGPaint { /// The paint source pub kind: SVGPaintKind, @@ -33,6 +34,7 @@ pub struct SVGPaint { #[animate(no_bound(UrlPaintServer))] #[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq)] #[derive(ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)] +#[distance(no_bound(UrlPaintServer))] pub enum SVGPaintKind { /// `none` #[animation(error)] @@ -205,7 +207,11 @@ pub enum SVGLength { pub enum SVGStrokeDashArray { /// `[ | | ]#` #[css(comma)] - Values(#[css(if_empty = "none", iterable)] Vec), + Values( + #[css(if_empty = "none", iterable)] + #[distance(field_bound)] + Vec, + ), /// `context-value` ContextValue, } 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::(&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::(&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(¶m.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)? - } - }), quote!(+)); - sum - }; - quote! { - #body - (&#this_pattern, &#other_pattern) => { - Ok(#sum) + 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::(&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::(&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) + } + } + }); + + (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, + no_bound: Option, +} + +#[darling(attributes(distance), default)] +#[derive(Default, FromField)] +struct DistanceFieldAttrs { + field_bound: bool, }