diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index f0d68b56fcf..e653508390f 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -62,9 +62,9 @@ pub enum ShapeSource { #[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq)] #[derive(ToComputedValue, ToCss)] pub enum BasicShape { - Inset(InsetRect), - Circle(Circle), - Ellipse(Ellipse), + Inset(#[css(field_bound)] InsetRect), + Circle(#[css(field_bound)] Circle), + Ellipse(#[css(field_bound)] Ellipse), Polygon(Polygon), } diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs index 4423d4c50d3..54b5cbbbb4a 100644 --- a/components/style/values/generics/border.rs +++ b/components/style/values/generics/border.rs @@ -32,7 +32,7 @@ pub struct BorderImageSlice { /// A generic value for the `border-*-radius` longhand properties. #[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug)] #[derive(MallocSizeOf, PartialEq, ToComputedValue, ToCss)] -pub struct BorderCornerRadius(pub Size); +pub struct BorderCornerRadius(#[css(field_bound)] pub Size); impl BorderCornerRadius { /// Trivially create a `BorderCornerRadius`. @@ -44,7 +44,7 @@ impl BorderCornerRadius { /// A generic value for the `border-spacing` property. #[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf)] #[derive(PartialEq, ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)] -pub struct BorderSpacing(pub Size); +pub struct BorderSpacing(#[css(field_bound)] pub Size); impl BorderSpacing { /// Trivially create a `BorderCornerRadius`. diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 7584e5cdf48..400ce823518 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -250,7 +250,6 @@ pub enum TransformOperation #[css(comma, function = "interpolatematrix")] InterpolateMatrix { #[compute(ignore_bound)] - #[css(ignore_bound)] from_list: Transform< TransformOperation< Angle, @@ -261,7 +260,6 @@ pub enum TransformOperation >, >, #[compute(ignore_bound)] - #[css(ignore_bound)] to_list: Transform< TransformOperation< Angle, @@ -279,7 +277,6 @@ pub enum TransformOperation #[css(comma, function = "accumulatematrix")] AccumulateMatrix { #[compute(ignore_bound)] - #[css(ignore_bound)] from_list: Transform< TransformOperation< Angle, @@ -290,7 +287,6 @@ pub enum TransformOperation >, >, #[compute(ignore_bound)] - #[css(ignore_bound)] to_list: Transform< TransformOperation< Angle, diff --git a/components/style_derive/animate.rs b/components/style_derive/animate.rs index ddf3cf1ec91..f96469c079e 100644 --- a/components/style_derive/animate.rs +++ b/components/style_derive/animate.rs @@ -32,16 +32,22 @@ pub fn derive(input: DeriveInput) -> Tokens { let field_attrs = cg::parse_field_attrs::(&result.ast()); if field_attrs.constant { if cg::is_parameterized(&result.ast().ty, &where_clause.params, None) { - where_clause.add_predicate(cg::where_predicate( - result.ast().ty.clone(), - &parse_quote!(std::cmp::PartialEq), - None, - )); - where_clause.add_predicate(cg::where_predicate( - result.ast().ty.clone(), - &parse_quote!(std::clone::Clone), - None, - )); + cg::add_predicate( + &mut where_clause.inner, + cg::where_predicate( + result.ast().ty.clone(), + &parse_quote!(std::cmp::PartialEq), + None, + ), + ); + cg::add_predicate( + &mut where_clause.inner, + cg::where_predicate( + result.ast().ty.clone(), + &parse_quote!(std::clone::Clone), + None, + ), + ); } quote! { if #this != #other { diff --git a/components/style_derive/cg.rs b/components/style_derive/cg.rs index 3ed23226588..364fc63af13 100644 --- a/components/style_derive/cg.rs +++ b/components/style_derive/cg.rs @@ -5,11 +5,11 @@ use darling::{FromDeriveInput, FromField, FromVariant}; use quote::{ToTokens, Tokens}; use std::collections::HashSet; -use syn::{self, DeriveInput, Field, Ident}; -use syn::{ImplGenerics, Path, PathArguments, PathSegment, AngleBracketedGenericArguments, GenericParam}; -use syn::{QSelf, Type, TypeGenerics, TypeParam}; -use syn::{TypeSlice, TypeArray, TypeTuple, TypePath, TypeParen}; -use syn::{Variant, WherePredicate, GenericArgument, Binding}; +use syn::{self, AngleBracketedGenericArguments, Binding, DeriveInput, Field}; +use syn::{GenericArgument, GenericParam, Ident, ImplGenerics, Path}; +use syn::{PathArguments, PathSegment, QSelf, Type, TypeArray, TypeGenerics}; +use syn::{TypeParam, TypeParen, TypePath, TypeSlice, TypeTuple}; +use syn::{Variant, WherePredicate}; use syn::visit::{self, Visit}; use synstructure::{self, BindingInfo, BindStyle, VariantAst, VariantInfo}; @@ -42,13 +42,13 @@ impl<'input, 'path> WhereClause<'input, 'path> { let output = if let Some(output) = self.trait_output { output } else { - self.add_predicate(where_predicate(ty.clone(), trait_path, None)); + add_predicate(&mut self.inner, where_predicate(ty.clone(), trait_path, None)); return; }; if let Type::Path(syn::TypePath { ref path, .. }) = *ty { if path_to_ident(path).is_some() { - self.add_predicate(where_predicate(ty.clone(), trait_path, None)); + add_predicate(&mut self.inner, where_predicate(ty.clone(), trait_path, None)); return; } } @@ -64,29 +64,28 @@ impl<'input, 'path> WhereClause<'input, 'path> { Some((output, output_type)), ); - self.add_predicate(pred); + add_predicate(&mut self.inner, pred); if let Some(found) = found { for ident in found { let ty = Type::Path(syn::TypePath { qself: None, path: ident.into() }); if !self.bounded_types.contains(&ty) { self.bounded_types.insert(ty.clone()); - self.add_predicate( + add_predicate( + &mut self.inner, where_predicate(ty, trait_path, None), ); }; } } } +} - pub fn add_predicate(&mut self, pred: WherePredicate) { - if let Some(ref mut inner) = self.inner { - inner.predicates.push(pred); - } else { - self.inner = Some(parse_quote!(where)); - self.add_predicate(pred); - } - } +pub fn add_predicate( + where_clause: &mut Option, + pred: WherePredicate, +) { + where_clause.get_or_insert(parse_quote!(where)).predicates.push(pred); } pub fn fmap_match( diff --git a/components/style_derive/to_animated_zero.rs b/components/style_derive/to_animated_zero.rs index 674a0201fcc..8094e46874d 100644 --- a/components/style_derive/to_animated_zero.rs +++ b/components/style_derive/to_animated_zero.rs @@ -27,11 +27,14 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens { let field_attrs = cg::parse_field_attrs::(&binding.ast()); if field_attrs.constant { if cg::is_parameterized(&binding.ast().ty, &where_clause.params, None) { - where_clause.add_predicate(cg::where_predicate( - binding.ast().ty.clone(), - &parse_quote!(std::clone::Clone), - None, - )); + cg::add_predicate( + &mut where_clause.inner, + cg::where_predicate( + binding.ast().ty.clone(), + &parse_quote!(std::clone::Clone), + None, + ), + ); } quote! { let #mapped_binding = ::std::clone::Clone::clone(#binding); diff --git a/components/style_derive/to_computed_value.rs b/components/style_derive/to_computed_value.rs index 4e4b804a2cd..1a64faa480d 100644 --- a/components/style_derive/to_computed_value.rs +++ b/components/style_derive/to_computed_value.rs @@ -40,11 +40,14 @@ pub fn derive(input: DeriveInput) -> Tokens { let attrs = cg::parse_field_attrs::(&binding.ast()); if attrs.clone { if cg::is_parameterized(&binding.ast().ty, &where_clause.params, None) { - where_clause.add_predicate(cg::where_predicate( - binding.ast().ty.clone(), - &parse_quote!(std::clone::Clone), - None, - )); + cg::add_predicate( + &mut where_clause.inner, + cg::where_predicate( + binding.ast().ty.clone(), + &parse_quote!(std::clone::Clone), + None, + ), + ); } quote! { ::std::clone::Clone::clone(#binding) } } else { diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index f94da49cfaa..1d3a2f2d230 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -2,28 +2,41 @@ * 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::Override; use quote::{ToTokens, Tokens}; -use syn::{self, Data, Path}; +use syn::{self, Data, GenericParam, Path, WhereClause}; use synstructure::{BindingInfo, Structure, VariantInfo}; -pub fn derive(input: syn::DeriveInput) -> Tokens { - let name = &input.ident; - let trait_path = parse_quote!(::style_traits::ToCss); - let (impl_generics, ty_generics, mut where_clause) = - cg::trait_parts(&input, &trait_path); +pub fn derive(mut input: syn::DeriveInput) -> Tokens { + let mut where_clause = input.generics.where_clause.take(); + for param in &input.generics.params { + let param = match *param { + GenericParam::Type(ref param) => param, + _ => continue, + }; + cg::add_predicate( + &mut where_clause, + parse_quote!(#param: ::style_traits::ToCss), + ); + } let input_attrs = cg::parse_input_attrs::(&input); if let Data::Enum(_) = input.data { assert!(input_attrs.function.is_none(), "#[css(function)] is not allowed on enums"); assert!(!input_attrs.comma, "#[css(comma)] is not allowed on enums"); } - let s = Structure::new(&input); - let match_body = s.each_variant(|variant| { - derive_variant_arm(variant, &mut where_clause) - }); + let match_body = { + let s = Structure::new(&input); + s.each_variant(|variant| { + derive_variant_arm(variant, &mut where_clause) + }) + }; + input.generics.where_clause = where_clause; + + let name = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut impls = quote! { impl #impl_generics ::style_traits::ToCss for #name #ty_generics #where_clause { @@ -34,7 +47,7 @@ pub fn derive(input: syn::DeriveInput) -> Tokens { dest: &mut ::style_traits::CssWriter, ) -> ::std::fmt::Result where - W: ::std::fmt::Write + W: ::std::fmt::Write, { match *self { #match_body @@ -61,7 +74,7 @@ pub fn derive(input: syn::DeriveInput) -> Tokens { fn derive_variant_arm( variant: &VariantInfo, - where_clause: &mut WhereClause, + generics: &mut Option, ) -> Tokens { let bindings = variant.bindings(); let identifier = cg::to_css_identifier(variant.ast().ident.as_ref()); @@ -83,7 +96,7 @@ fn derive_variant_arm( ::std::fmt::Write::write_str(dest, #keyword) } } else if !bindings.is_empty() { - derive_variant_fields_expr(bindings, where_clause, separator) + derive_variant_fields_expr(bindings, generics, separator) } else { quote! { ::std::fmt::Write::write_str(dest, #identifier) @@ -109,7 +122,7 @@ fn derive_variant_arm( fn derive_variant_fields_expr( bindings: &[BindingInfo], - where_clause: &mut WhereClause, + where_clause: &mut Option, separator: &str, ) -> Tokens { let mut iter = bindings.iter().filter_map(|binding| { @@ -125,8 +138,9 @@ fn derive_variant_fields_expr( None => return quote! { Ok(()) }, }; if !attrs.iterable && iter.peek().is_none() { - if !attrs.ignore_bound { - where_clause.add_trait_bound(&first.ast().ty); + if attrs.field_bound { + let ty = &first.ast().ty; + cg::add_predicate(where_clause, parse_quote!(#ty: ::style_traits::ToCss)); } let mut expr = quote! { ::style_traits::ToCss::to_css(#first, dest) }; if let Some(condition) = attrs.skip_if { @@ -154,7 +168,7 @@ fn derive_variant_fields_expr( fn derive_single_field_expr( field: &BindingInfo, attrs: CssFieldAttrs, - where_clause: &mut WhereClause, + where_clause: &mut Option, ) -> Tokens { let mut expr = if attrs.iterable { if let Some(if_empty) = attrs.if_empty { @@ -177,8 +191,9 @@ fn derive_single_field_expr( } } } else { - if !attrs.ignore_bound { - where_clause.add_trait_bound(&field.ast().ty); + if attrs.field_bound { + let ty = &field.ast().ty; + cg::add_predicate(where_clause, parse_quote!(#ty: ::style_traits::ToCss)); } quote! { writer.item(#field)?; } }; @@ -218,7 +233,7 @@ pub struct CssVariantAttrs { #[derive(Default, FromField)] struct CssFieldAttrs { if_empty: Option, - ignore_bound: bool, + field_bound: bool, iterable: bool, skip: bool, skip_if: Option,