diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index d131f350393..bffedd845e3 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -408,7 +408,7 @@ impl ToCss for System { } /// -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToCss, ToShmem)] #[repr(u8)] pub enum Symbol { /// @@ -554,7 +554,7 @@ impl Parse for Fallback { } /// -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToCss, ToShmem)] #[repr(C)] pub struct Symbols(#[css(iterable)] pub crate::OwnedSlice); diff --git a/components/style/gecko_string_cache/namespace.rs b/components/style/gecko_string_cache/namespace.rs index 2dba484e002..dd3b52d2506 100644 --- a/components/style/gecko_string_cache/namespace.rs +++ b/components/style/gecko_string_cache/namespace.rs @@ -24,7 +24,7 @@ macro_rules! ns { } /// A Gecko namespace is just a wrapped atom. -#[derive(Clone, Debug, Default, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)] +#[derive(Clone, Debug, Default, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] #[repr(transparent)] pub struct Namespace(pub Atom); diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a232b275c88..c39dc6f23da 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1044,7 +1044,7 @@ pub enum LogicalGroup { } /// An identifier for a given longhand property. -#[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)] +#[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] #[repr(u16)] pub enum LonghandId { % for i, property in enumerate(data.longhands): @@ -1353,7 +1353,7 @@ where } /// An identifier for a given shorthand property. -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)] +#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] #[repr(u16)] pub enum ShorthandId { % for i, property in enumerate(data.shorthands): diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 6d17f9fa699..bafcf620530 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -178,7 +178,7 @@ impl ToAnimatedValue for FontSize { } } -#[derive(Clone, Debug, Eq, PartialEq, ToResolvedValue)] +#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToResolvedValue)] #[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf))] /// Specifies a prioritized list of font family names or generic family names. pub struct FontFamily { @@ -227,7 +227,7 @@ impl ToCss for FontFamily { } } -#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)] +#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] /// The name of a font family of choice pub struct FamilyName { @@ -270,7 +270,7 @@ impl ToCss for FamilyName { } } -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)] +#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] /// Font family names must either be given quoted as strings, /// or unquoted as a sequence of one or more identifiers. @@ -285,7 +285,7 @@ pub enum FontFamilyNameSyntax { Identifiers, } -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToShmem)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToComputedValue, ToResolvedValue, ToShmem)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize, Hash))] /// A set of faces that vary in weight, width or slope. pub enum SingleFontFamily { @@ -301,7 +301,7 @@ pub enum SingleFontFamily { /// `gfxPlatformFontList.h`s ranged array and `gfxFontFamilyList`'s /// sSingleGenerics are updated as well. #[derive( - Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, Parse, ToCss, ToResolvedValue, ToShmem, + Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, Parse, ToCss, ToComputedValue, ToResolvedValue, ToShmem, )] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[repr(u8)] @@ -427,16 +427,20 @@ impl SingleFontFamily { } #[cfg(feature = "servo")] -#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)] +#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] /// A list of SingleFontFamily pub struct FontFamilyList(Box<[SingleFontFamily]>); #[cfg(feature = "gecko")] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, ToComputedValue, ToResolvedValue)] /// A list of SingleFontFamily pub enum FontFamilyList { /// A strong reference to a Gecko SharedFontList object. - SharedFontList(RefPtr), + SharedFontList( + #[compute(no_field_bound)] + #[resolve(no_field_bound)] + RefPtr, + ), /// A font-family generic ID. Generic(GenericFontFamily), } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 9dac232d0d4..8c6dde8c738 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -203,6 +203,7 @@ impl Size { Serialize, ToAnimatedValue, ToAnimatedZero, + ToComputedValue, ToResolvedValue, ToShmem, )] diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 01bbfcf5cbd..ec9424468c9 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -21,10 +21,11 @@ use crate::media_queries::Device; use crate::properties; use crate::properties::{ComputedValues, LonghandId, StyleBuilder}; use crate::rule_cache::RuleCacheConditions; -use crate::Atom; +use crate::{ArcSlice, Atom}; #[cfg(feature = "servo")] use crate::Prefix; use euclid::default::Size2D; +use servo_arc::Arc; use std::cell::RefCell; use std::cmp; use std::f32; @@ -450,6 +451,46 @@ where } } +// NOTE(emilio): This is implementable more generically, but it's unlikely +// what you want there, as it forces you to have an extra allocation. +// +// We could do that if needed, ideally with specialization for the case where +// ComputedValue = T. But we don't need it for now. +impl ToComputedValue for Arc +where + T: ToComputedValue, +{ + type ComputedValue = Self; + + #[inline] + fn to_computed_value(&self, _: &Context) -> Self { + self.clone() + } + + #[inline] + fn from_computed_value(computed: &Self) -> Self { + computed.clone() + } +} + +// Same caveat as above applies. +impl ToComputedValue for ArcSlice +where + T: ToComputedValue, +{ + type ComputedValue = Self; + + #[inline] + fn to_computed_value(&self, _: &Context) -> Self { + self.clone() + } + + #[inline] + fn from_computed_value(computed: &Self) -> Self { + computed.clone() + } +} + trivial_to_computed_value!(()); trivial_to_computed_value!(bool); trivial_to_computed_value!(f32); @@ -464,6 +505,7 @@ trivial_to_computed_value!(Prefix); trivial_to_computed_value!(String); trivial_to_computed_value!(Box); trivial_to_computed_value!(crate::OwnedStr); +trivial_to_computed_value!(style_traits::values::specified::AllowedNumericType); #[allow(missing_docs)] #[derive( diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs index dc64063ba08..9e70d68f3c7 100644 --- a/components/style/values/generics/image.rs +++ b/components/style/values/generics/image.rs @@ -237,6 +237,8 @@ pub struct PaintWorklet { /// The arguments for the worklet. /// TODO: store a parsed representation of the arguments. #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")] + #[compute(no_field_bound)] + #[resolve(no_field_bound)] pub arguments: Vec>, } diff --git a/components/style/values/resolved/mod.rs b/components/style/values/resolved/mod.rs index 022cb7893c6..633bcd47997 100644 --- a/components/style/values/resolved/mod.rs +++ b/components/style/values/resolved/mod.rs @@ -6,7 +6,9 @@ //! there are used values. use crate::properties::ComputedValues; +use crate::ArcSlice; use cssparser; +use servo_arc::Arc; use smallvec::SmallVec; mod color; @@ -79,6 +81,7 @@ trivial_to_resolved_value!(computed::url::ComputedImageUrl); #[cfg(feature = "servo")] trivial_to_resolved_value!(html5ever::Prefix); trivial_to_resolved_value!(computed::LengthPercentage); +trivial_to_resolved_value!(style_traits::values::specified::AllowedNumericType); impl ToResolvedValue for (A, B) where @@ -214,3 +217,43 @@ where Self::from(Box::from_resolved_value(resolved.into_box())) } } + +// NOTE(emilio): This is implementable more generically, but it's unlikely what +// you want there, as it forces you to have an extra allocation. +// +// We could do that if needed, ideally with specialization for the case where +// ResolvedValue = T. But we don't need it for now. +impl ToResolvedValue for Arc +where + T: ToResolvedValue, +{ + type ResolvedValue = Self; + + #[inline] + fn to_resolved_value(self, _: &Context) -> Self { + self + } + + #[inline] + fn from_resolved_value(resolved: Self) -> Self { + resolved + } +} + +// Same caveat as above applies. +impl ToResolvedValue for ArcSlice +where + T: ToResolvedValue, +{ + type ResolvedValue = Self; + + #[inline] + fn to_resolved_value(self, _: &Context) -> Self { + self + } + + #[inline] + fn from_resolved_value(resolved: Self) -> Self { + resolved + } +} diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index d0160a32ae6..10f7f3efbfc 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -556,7 +556,7 @@ impl SpecifiedValueInfo for AlignItems { /// Value of the `justify-items` property /// /// -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToShmem)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToShmem)] #[repr(C)] pub struct JustifyItems(pub AlignFlags); diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs index 1b1ed74d568..28be8177cf4 100644 --- a/components/style/values/specified/border.rs +++ b/components/style/values/specified/border.rs @@ -234,7 +234,18 @@ impl Parse for BorderSpacing { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive( - Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, )] pub enum BorderImageRepeatKeyword { Stretch, diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 94c28d068f9..dd9f9d3b86d 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -492,7 +492,9 @@ impl ToComputedValue for FontStretch { SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, + ToComputedValue, ToCss, + ToResolvedValue, ToShmem, )] #[allow(missing_docs)] @@ -534,7 +536,9 @@ impl Default for KeywordSize { PartialEq, ToAnimatedValue, ToAnimatedZero, + ToComputedValue, ToCss, + ToResolvedValue, ToShmem, )] /// Additional information for keyword-derived font sizes. @@ -567,7 +571,7 @@ impl KeywordInfo { /// Computes the final size for this font-size keyword, accounting for /// text-zoom. fn to_computed_value(&self, context: &Context) -> CSSPixelLength { - let base = context.maybe_zoom_text(self.kw.to_computed_value(context).0); + let base = context.maybe_zoom_text(self.kw.to_length(context).0); base * self.factor + context.maybe_zoom_text(self.offset) } @@ -760,11 +764,10 @@ const LARGER_FONT_SIZE_RATIO: f32 = 1.2; /// The default font size. pub const FONT_MEDIUM_PX: i32 = 16; -#[cfg(feature = "servo")] -impl ToComputedValue for KeywordSize { - type ComputedValue = NonNegativeLength; +impl KeywordSize { #[inline] - fn to_computed_value(&self, _: &Context) -> NonNegativeLength { + #[cfg(feature = "servo")] + fn to_length(&self, _: &Context) -> NonNegativeLength { let medium = Length::new(FONT_MEDIUM_PX as f32); // https://drafts.csswg.org/css-fonts-3/#font-size-prop NonNegative(match *self { @@ -779,17 +782,9 @@ impl ToComputedValue for KeywordSize { }) } + #[cfg(feature = "gecko")] #[inline] - fn from_computed_value(_: &NonNegativeLength) -> Self { - unreachable!() - } -} - -#[cfg(feature = "gecko")] -impl ToComputedValue for KeywordSize { - type ComputedValue = NonNegativeLength; - #[inline] - fn to_computed_value(&self, cx: &Context) -> NonNegativeLength { + fn to_length(&self, cx: &Context) -> NonNegativeLength { use crate::context::QuirksMode; // The tables in this function are originally from @@ -857,11 +852,6 @@ impl ToComputedValue for KeywordSize { base_size * FONT_SIZE_FACTORS[html_size] as f32 / 100.0 }) } - - #[inline] - fn from_computed_value(_: &NonNegativeLength) -> Self { - unreachable!() - } } impl FontSize { diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs index 35385b75817..ae21e739973 100644 --- a/components/style/values/specified/position.rs +++ b/components/style/values/specified/position.rs @@ -539,7 +539,7 @@ impl TemplateAreas { Ok(TemplateAreas { areas: areas.into(), strings: strings.into(), - width: width, + width, }) } } @@ -589,7 +589,16 @@ impl Parse for TemplateAreasArc { /// A range of rows or columns. Using this instead of std::ops::Range for FFI /// purposes. #[repr(C)] -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)] +#[derive( + Clone, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] pub struct UnsignedRange { /// The start of the range. pub start: u32, @@ -597,7 +606,16 @@ pub struct UnsignedRange { pub end: u32, } -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)] +#[derive( + Clone, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] #[repr(C)] /// Not associated with any particular grid item, but can be referenced from the /// grid-placement properties. diff --git a/components/style/values/specified/svg_path.rs b/components/style/values/specified/svg_path.rs index 288f396b73c..edd2a10ba4b 100644 --- a/components/style/values/specified/svg_path.rs +++ b/components/style/values/specified/svg_path.rs @@ -35,7 +35,8 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; pub struct SVGPathData( // TODO(emilio): Should probably measure this somehow only from the // specified values. - #[ignore_malloc_size_of = "Arc"] pub crate::ArcSlice, + #[ignore_malloc_size_of = "Arc"] + pub crate::ArcSlice, ); impl SVGPathData { @@ -159,6 +160,8 @@ impl ComputeSquaredDistance for SVGPathData { Serialize, SpecifiedValueInfo, ToAnimatedZero, + ToComputedValue, + ToResolvedValue, ToShmem, )] #[allow(missing_docs)] @@ -488,6 +491,8 @@ impl ToCss for PathCommand { Serialize, SpecifiedValueInfo, ToAnimatedZero, + ToComputedValue, + ToResolvedValue, ToShmem, )] #[repr(u8)] @@ -518,7 +523,9 @@ impl IsAbsolute { Serialize, SpecifiedValueInfo, ToAnimatedZero, + ToComputedValue, ToCss, + ToResolvedValue, ToShmem, )] #[repr(C)] @@ -534,7 +541,7 @@ impl CoordPair { /// The EllipticalArc flag type. #[derive( - Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, SpecifiedValueInfo, ToShmem, + Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem, )] #[repr(C)] pub struct ArcFlag(bool); diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index 8f9a9bcb1cd..2a86cdbbc78 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -122,7 +122,7 @@ impl ToComputedValue for LineHeight { } /// A generic value for the `text-overflow` property. -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)] #[repr(C, u8)] pub enum TextOverflowSide { /// Clip inline content. @@ -687,7 +687,7 @@ pub enum TextEmphasisStyle { } /// Fill mode for the text-emphasis-style property -#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] +#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToComputedValue, ToResolvedValue, ToShmem)] #[repr(u8)] pub enum TextEmphasisFillMode { /// `filled` @@ -706,7 +706,18 @@ impl TextEmphasisFillMode { /// Shape keyword for the text-emphasis-style property #[derive( - Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToCss, + ToComputedValue, + ToResolvedValue, + ToShmem, )] #[repr(u8)] pub enum TextEmphasisShapeKeyword { diff --git a/components/style_derive/to_animated_value.rs b/components/style_derive/to_animated_value.rs index 51a73cbf4e1..45282f0c448 100644 --- a/components/style_derive/to_animated_value.rs +++ b/components/style_derive/to_animated_value.rs @@ -11,33 +11,25 @@ pub fn derive(input: DeriveInput) -> TokenStream { let trait_impl = |from_body, to_body| { quote! { #[inline] - fn from_animated_value(animated: Self::AnimatedValue) -> Self { - match animated { - #from_body - } + fn from_animated_value(from: Self::AnimatedValue) -> Self { + #from_body } #[inline] fn to_animated_value(self) -> Self::AnimatedValue { - match self { - #to_body - } + #to_body } } }; - // TODO(emilio): Consider optimizing away non-generic cases as well? - let non_generic_implementation = || None; - to_computed_value::derive_to_value( input, parse_quote!(crate::values::animated::ToAnimatedValue), parse_quote!(AnimatedValue), BindStyle::Move, - |_| false, + |_| Default::default(), |binding| quote!(crate::values::animated::ToAnimatedValue::from_animated_value(#binding)), |binding| quote!(crate::values::animated::ToAnimatedValue::to_animated_value(#binding)), trait_impl, - non_generic_implementation, ) } diff --git a/components/style_derive/to_computed_value.rs b/components/style_derive/to_computed_value.rs index ed6e07a2f5a..a109ffb1752 100644 --- a/components/style_derive/to_computed_value.rs +++ b/components/style_derive/to_computed_value.rs @@ -13,7 +13,7 @@ pub fn derive_to_value( output_type_name: Ident, bind_style: BindStyle, // Returns whether to apply the field bound for a given item. - mut field_bound: impl FnMut(&BindingInfo) -> bool, + mut binding_attrs: impl FnMut(&BindingInfo) -> ToValueAttrs, // Returns a token stream of the form: trait_path::from_foo(#binding) mut call_from: impl FnMut(&BindingInfo) -> TokenStream, mut call_to: impl FnMut(&BindingInfo) -> TokenStream, @@ -26,25 +26,9 @@ pub fn derive_to_value( // #second_arg // } mut trait_impl: impl FnMut(TokenStream, TokenStream) -> TokenStream, - // if this is provided, the derive for non-generic types will be simplified - // to this token stream, which should be the body of the impl block. - non_generic_implementation: impl FnOnce() -> Option, ) -> TokenStream { let name = &input.ident; - if input.generics.type_params().next().is_none() { - if let Some(non_generic_implementation) = non_generic_implementation() { - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - return quote! { - impl #impl_generics #trait_path for #name #ty_generics - #where_clause - { - #non_generic_implementation - } - }; - } - } - let mut where_clause = input.generics.where_clause.take(); cg::propagate_clauses_to_output_type( &mut where_clause, @@ -52,33 +36,96 @@ pub fn derive_to_value( &trait_path, &output_type_name, ); - let (to_body, from_body) = { - let params = input.generics.type_params().collect::>(); - for param in ¶ms { - cg::add_predicate(&mut where_clause, parse_quote!(#param: #trait_path)); + + let moves = match bind_style { + BindStyle::Move | BindStyle::MoveMut => true, + BindStyle::Ref | BindStyle::RefMut => false, + }; + + let params = input.generics.type_params().collect::>(); + for param in ¶ms { + cg::add_predicate(&mut where_clause, parse_quote!(#param: #trait_path)); + } + + let mut add_field_bound = |binding: &BindingInfo| { + let ty = &binding.ast().ty; + + let output_type = cg::map_type_params( + ty, + ¶ms, + &mut |ident| parse_quote!(<#ident as #trait_path>::#output_type_name), + ); + + cg::add_predicate( + &mut where_clause, + parse_quote!( + #ty: #trait_path<#output_type_name = #output_type> + ), + ); + }; + + let (to_body, from_body) = if params.is_empty() { + let mut s = synstructure::Structure::new(&input); + s.variants_mut().iter_mut().for_each(|v| { + v.bind_with(|_| bind_style); + }); + + for variant in s.variants() { + for binding in variant.bindings() { + let attrs = binding_attrs(&binding); + assert!( + !attrs.field_bound, + "It is default on a non-generic implementation", + ); + if !attrs.no_field_bound { + // Add field bounds to all bindings except the manually + // excluded. This ensures the correctness of the clone() / + // move based implementation. + add_field_bound(binding); + } + } } + let to_body = if moves { + quote! { self } + } else { + quote! { std::clone::Clone::clone(self) } + }; + + let from_body = if moves { + quote! { from } + } else { + quote! { std::clone::Clone::clone(from) } + }; + + (to_body, from_body) + } else { let to_body = cg::fmap_match(&input, bind_style, |binding| { - if field_bound(&binding) { - let ty = &binding.ast().ty; - - let output_type = cg::map_type_params( - ty, - ¶ms, - &mut |ident| parse_quote!(<#ident as #trait_path>::#output_type_name), - ); - - cg::add_predicate( - &mut where_clause, - parse_quote!( - #ty: #trait_path<#output_type_name = #output_type> - ), - ); + let attrs = binding_attrs(&binding); + assert!(!attrs.no_field_bound, "It doesn't make sense on a generic implementation"); + if attrs.field_bound { + add_field_bound(&binding); } call_to(&binding) }); + let from_body = cg::fmap_match(&input, bind_style, |binding| call_from(&binding)); + let self_ = if moves { quote! { self } } else { quote! { *self } }; + let from_ = if moves { quote! { from } } else { quote! { *from } }; + + let to_body = quote! { + match #self_ { + #to_body + } + }; + + let from_body = quote! { + match #from_ { + #from_body + } + }; + (to_body, from_body) }; @@ -101,53 +148,45 @@ pub fn derive(input: DeriveInput) -> TokenStream { let trait_impl = |from_body, to_body| { quote! { #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - match *computed { - #from_body - } + fn from_computed_value(from: &Self::ComputedValue) -> Self { + #from_body } #[allow(unused_variables)] #[inline] fn to_computed_value(&self, context: &crate::values::computed::Context) -> Self::ComputedValue { - match *self { - #to_body - } + #to_body } } }; - let non_generic_implementation = || { - Some(quote! { - type ComputedValue = Self; - - #[inline] - fn to_computed_value(&self, _: &crate::values::computed::Context) -> Self::ComputedValue { - std::clone::Clone::clone(self) - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - std::clone::Clone::clone(computed) - } - }) - }; - derive_to_value( input, parse_quote!(crate::values::computed::ToComputedValue), parse_quote!(ComputedValue), BindStyle::Ref, - |binding| cg::parse_field_attrs::(&binding.ast()).field_bound, + |binding| { + let attrs = cg::parse_field_attrs::(&binding.ast()); + ToValueAttrs { + field_bound: attrs.field_bound, + no_field_bound: attrs.no_field_bound, + } + }, |binding| quote!(crate::values::computed::ToComputedValue::from_computed_value(#binding)), |binding| quote!(crate::values::computed::ToComputedValue::to_computed_value(#binding, context)), trait_impl, - non_generic_implementation, ) } +#[derive(Default)] +pub struct ToValueAttrs { + pub field_bound: bool, + pub no_field_bound: bool, +} + #[darling(attributes(compute), default)] #[derive(Default, FromField)] struct ComputedValueAttrs { field_bound: bool, + no_field_bound: bool, } diff --git a/components/style_derive/to_resolved_value.rs b/components/style_derive/to_resolved_value.rs index 040cda954a8..f7ba2645e89 100644 --- a/components/style_derive/to_resolved_value.rs +++ b/components/style_derive/to_resolved_value.rs @@ -12,10 +12,8 @@ pub fn derive(input: DeriveInput) -> TokenStream { let trait_impl = |from_body, to_body| { quote! { #[inline] - fn from_resolved_value(resolved: Self::ResolvedValue) -> Self { - match resolved { - #from_body - } + fn from_resolved_value(from: Self::ResolvedValue) -> Self { + #from_body } #[inline] @@ -23,42 +21,26 @@ pub fn derive(input: DeriveInput) -> TokenStream { self, context: &crate::values::resolved::Context, ) -> Self::ResolvedValue { - match self { - #to_body - } + #to_body } } }; - let non_generic_implementation = || { - Some(quote! { - type ResolvedValue = Self; - - #[inline] - fn from_resolved_value(resolved: Self::ResolvedValue) -> Self { - resolved - } - - #[inline] - fn to_resolved_value( - self, - context: &crate::values::resolved::Context, - ) -> Self { - self - } - }) - }; - to_computed_value::derive_to_value( input, parse_quote!(crate::values::resolved::ToResolvedValue), parse_quote!(ResolvedValue), BindStyle::Move, - |binding| cg::parse_field_attrs::(&binding.ast()).field_bound, + |binding| { + let attrs = cg::parse_field_attrs::(&binding.ast()); + to_computed_value::ToValueAttrs { + field_bound: attrs.field_bound, + no_field_bound: attrs.no_field_bound, + } + }, |binding| quote!(crate::values::resolved::ToResolvedValue::from_resolved_value(#binding)), |binding| quote!(crate::values::resolved::ToResolvedValue::to_resolved_value(#binding, context)), trait_impl, - non_generic_implementation, ) } @@ -66,4 +48,5 @@ pub fn derive(input: DeriveInput) -> TokenStream { #[derive(Default, FromField)] struct ResolvedValueAttrs { field_bound: bool, + no_field_bound: bool, } diff --git a/components/style_traits/arc_slice.rs b/components/style_traits/arc_slice.rs index f5d0c56e7fc..8d55beff3c5 100644 --- a/components/style_traits/arc_slice.rs +++ b/components/style_traits/arc_slice.rs @@ -26,7 +26,7 @@ const ARC_SLICE_CANARY: u64 = 0xf3f3f3f3f3f3f3f3; /// cbindgen:derive-eq=false /// cbindgen:derive-neq=false #[repr(C)] -#[derive(Clone, Debug, Eq, PartialEq, ToShmem)] +#[derive(Debug, Eq, PartialEq, ToShmem)] pub struct ArcSlice(#[shmem(field_bound)] ThinArc); impl Deref for ArcSlice { @@ -39,6 +39,12 @@ impl Deref for ArcSlice { } } +impl Clone for ArcSlice { + fn clone(&self) -> Self { + ArcSlice(self.0.clone()) + } +} + lazy_static! { // ThinArc doesn't support alignments greater than align_of::. static ref EMPTY_ARC_SLICE: ArcSlice = {