mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
Refactor how we handle trait bounds in style_derive
For the traits we derive which methods don't depend on associated types (i.e. all of them but ToAnimatedValue and ToComputedValue), we now add trait bounds for the actual field types directly, instead of bounding the type parameters.
This commit is contained in:
parent
13d47ba69a
commit
04ad28b564
8 changed files with 75 additions and 58 deletions
|
@ -28,9 +28,7 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
let mut computations = quote!();
|
let mut computations = quote!();
|
||||||
let iter = result_info.iter().zip(this_info.iter().zip(&other_info));
|
let iter = result_info.iter().zip(this_info.iter().zip(&other_info));
|
||||||
computations.append_all(iter.map(|(result, (this, other))| {
|
computations.append_all(iter.map(|(result, (this, other))| {
|
||||||
where_clause.predicates.push(
|
where_clause.add_trait_bound(this.field.ty.clone());
|
||||||
cg::where_predicate(this.field.ty.clone(), trait_path),
|
|
||||||
);
|
|
||||||
quote! {
|
quote! {
|
||||||
let #result = ::values::animated::Animate::animate(#this, #other, procedure)?;
|
let #result = ::values::animated::Animate::animate(#this, #other, procedure)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,39 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use darling::FromVariant;
|
use darling::FromVariant;
|
||||||
use quote::Tokens;
|
use quote::{ToTokens, Tokens};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use syn::{AngleBracketedParameterData, Body, DeriveInput, Ident, ImplGenerics};
|
use syn::{self, AngleBracketedParameterData, Body, DeriveInput, Ident};
|
||||||
use syn::{Path, PathParameters, PathSegment, PolyTraitRef, QSelf};
|
use syn::{ImplGenerics, Path, PathParameters, PathSegment, PolyTraitRef};
|
||||||
use syn::{TraitBoundModifier, Ty, TyGenerics, TyParam, TyParamBound};
|
use syn::{QSelf, TraitBoundModifier, Ty, TyGenerics, TyParam, TyParamBound};
|
||||||
use syn::{Variant, WhereBoundPredicate, WhereClause, WherePredicate};
|
use syn::{Variant, WhereBoundPredicate, WherePredicate};
|
||||||
use syn::visit::{self, Visitor};
|
use syn::visit::{self, Visitor};
|
||||||
use synstructure::{self, BindOpts, BindStyle, BindingInfo};
|
use synstructure::{self, BindOpts, BindStyle, BindingInfo};
|
||||||
|
|
||||||
|
pub struct WhereClause<'input, 'path> {
|
||||||
|
clause: syn::WhereClause,
|
||||||
|
params: &'input [TyParam],
|
||||||
|
trait_path: &'path [&'path str],
|
||||||
|
bounded_types: HashSet<Ty>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input, 'path> ToTokens for WhereClause<'input, 'path> {
|
||||||
|
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||||
|
self.clause.to_tokens(tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input, 'path> WhereClause<'input, 'path> {
|
||||||
|
pub fn add_trait_bound(&mut self, ty: Ty) {
|
||||||
|
if is_parameterized(&ty, self.params) && !self.bounded_types.contains(&ty) {
|
||||||
|
self.bounded_types.insert(ty.clone());
|
||||||
|
self.clause.predicates.push(where_predicate(ty, self.trait_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fmap_match<F>(
|
pub fn fmap_match<F>(
|
||||||
input: &DeriveInput,
|
input: &DeriveInput,
|
||||||
bind_style: BindStyle,
|
bind_style: BindStyle,
|
||||||
|
@ -35,11 +58,11 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmap_trait_parts<'a>(
|
pub fn fmap_trait_parts<'input, 'path>(
|
||||||
input: &'a DeriveInput,
|
input: &'input DeriveInput,
|
||||||
trait_path: &[&str],
|
trait_path: &'path [&'path str],
|
||||||
trait_output: &str,
|
trait_output: &str,
|
||||||
) -> (ImplGenerics<'a>, TyGenerics<'a>, WhereClause, Path) {
|
) -> (ImplGenerics<'input>, TyGenerics<'input>, WhereClause<'input, 'path>, Path) {
|
||||||
let (impl_generics, ty_generics, where_clause) = trait_parts(input, trait_path);
|
let (impl_generics, ty_generics, where_clause) = trait_parts(input, trait_path);
|
||||||
let output_ty = PathSegment {
|
let output_ty = PathSegment {
|
||||||
ident: input.ident.clone(),
|
ident: input.ident.clone(),
|
||||||
|
@ -115,18 +138,17 @@ pub fn ref_pattern<'a>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trait_parts<'a>(
|
pub fn trait_parts<'input, 'path>(
|
||||||
input: &'a DeriveInput,
|
input: &'input DeriveInput,
|
||||||
trait_path: &[&str],
|
trait_path: &'path [&'path str],
|
||||||
) -> (ImplGenerics<'a>, TyGenerics<'a>, WhereClause) {
|
) -> (ImplGenerics<'input>, TyGenerics<'input>, WhereClause<'input, 'path>) {
|
||||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||||
let mut where_clause = where_clause.clone();
|
let where_clause = WhereClause {
|
||||||
for param in &input.generics.ty_params {
|
clause: where_clause.clone(),
|
||||||
where_clause.predicates.push(where_predicate(
|
params: &input.generics.ty_params,
|
||||||
Ty::Path(None, param.ident.clone().into()),
|
|
||||||
trait_path,
|
trait_path,
|
||||||
));
|
bounded_types: HashSet::new()
|
||||||
}
|
};
|
||||||
(impl_generics, ty_generics, where_clause)
|
(impl_generics, ty_generics, where_clause)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,7 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
} else {
|
} else {
|
||||||
let mut sum = quote!();
|
let mut sum = quote!();
|
||||||
sum.append_separated(this_info.iter().zip(&other_info).map(|(this, other)| {
|
sum.append_separated(this_info.iter().zip(&other_info).map(|(this, other)| {
|
||||||
where_clause.predicates.push(
|
where_clause.add_trait_bound(this.field.ty.clone());
|
||||||
cg::where_predicate(this.field.ty.clone(), trait_path),
|
|
||||||
);
|
|
||||||
quote! {
|
quote! {
|
||||||
::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)?
|
::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)?
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,10 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
None => return Some(quote!(false)),
|
None => return Some(quote!(false)),
|
||||||
Some(pair) => pair,
|
Some(pair) => pair,
|
||||||
};
|
};
|
||||||
|
where_clause.add_trait_bound(first.field.ty.clone());
|
||||||
let mut expr = quote!(::style_traits::HasViewportPercentage::has_viewport_percentage(#first));
|
let mut expr = quote!(::style_traits::HasViewportPercentage::has_viewport_percentage(#first));
|
||||||
for binding in rest {
|
for binding in rest {
|
||||||
where_clause.predicates.push(
|
where_clause.add_trait_bound(binding.field.ty.clone());
|
||||||
cg::where_predicate(binding.field.ty.clone(), trait_path),
|
|
||||||
);
|
|
||||||
expr = quote!(#expr || ::style_traits::HasViewportPercentage::has_viewport_percentage(#binding));
|
expr = quote!(#expr || ::style_traits::HasViewportPercentage::has_viewport_percentage(#binding));
|
||||||
}
|
}
|
||||||
Some(expr)
|
Some(expr)
|
||||||
|
|
|
@ -9,18 +9,20 @@ use synstructure::BindStyle;
|
||||||
|
|
||||||
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
let name = &input.ident;
|
let name = &input.ident;
|
||||||
let (impl_generics, ty_generics, where_clause, animated_value_type) =
|
let trait_path = &["values", "animated", "ToAnimatedValue"];
|
||||||
cg::fmap_trait_parts(
|
let (impl_generics, ty_generics, mut where_clause, animated_value_type) =
|
||||||
&input,
|
cg::fmap_trait_parts(&input, trait_path, "AnimatedValue");
|
||||||
&["values", "animated", "ToAnimatedValue"],
|
for param in &input.generics.ty_params {
|
||||||
"AnimatedValue",
|
where_clause.add_trait_bound(
|
||||||
|
syn::Ty::Path(None, param.ident.clone().into()),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let to_body = cg::fmap_match(&input, BindStyle::Move, |field| {
|
let to_body = cg::fmap_match(&input, BindStyle::Move, |binding| {
|
||||||
quote!(::values::animated::ToAnimatedValue::to_animated_value(#field))
|
quote!(::values::animated::ToAnimatedValue::to_animated_value(#binding))
|
||||||
});
|
});
|
||||||
let from_body = cg::fmap_match(&input, BindStyle::Move, |field| {
|
let from_body = cg::fmap_match(&input, BindStyle::Move, |binding| {
|
||||||
quote!(::values::animated::ToAnimatedValue::from_animated_value(#field))
|
quote!(::values::animated::ToAnimatedValue::from_animated_value(#binding))
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
|
|
@ -9,13 +9,13 @@ use synstructure::BindStyle;
|
||||||
|
|
||||||
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
let name = &input.ident;
|
let name = &input.ident;
|
||||||
let (impl_generics, ty_generics, where_clause) = cg::trait_parts(
|
let trait_path = &["values", "animated", "ToAnimatedZero"];
|
||||||
&input,
|
let (impl_generics, ty_generics, mut where_clause) =
|
||||||
&["values", "animated", "ToAnimatedZero"],
|
cg::trait_parts(&input, trait_path);
|
||||||
);
|
|
||||||
|
|
||||||
let to_body = cg::fmap_match(&input, BindStyle::Ref, |field| {
|
let to_body = cg::fmap_match(&input, BindStyle::Ref, |binding| {
|
||||||
quote! { ::values::animated::ToAnimatedZero::to_animated_zero(#field)? }
|
where_clause.add_trait_bound(binding.field.ty.clone());
|
||||||
|
quote! { ::values::animated::ToAnimatedZero::to_animated_zero(#binding)? }
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
|
|
@ -9,18 +9,20 @@ use synstructure::BindStyle;
|
||||||
|
|
||||||
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
let name = &input.ident;
|
let name = &input.ident;
|
||||||
let (impl_generics, ty_generics, where_clause, computed_value_type) =
|
let trait_path = &["values", "computed", "ToComputedValue"];
|
||||||
cg::fmap_trait_parts(
|
let (impl_generics, ty_generics, mut where_clause, computed_value_type) =
|
||||||
&input,
|
cg::fmap_trait_parts(&input, trait_path, "ComputedValue");
|
||||||
&["values", "computed", "ToComputedValue"],
|
for param in &input.generics.ty_params {
|
||||||
"ComputedValue",
|
where_clause.add_trait_bound(
|
||||||
|
syn::Ty::Path(None, param.ident.clone().into()),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let to_body = cg::fmap_match(&input, BindStyle::Ref, |field| {
|
let to_body = cg::fmap_match(&input, BindStyle::Ref, |binding| {
|
||||||
quote!(::values::computed::ToComputedValue::to_computed_value(#field, context))
|
quote!(::values::computed::ToComputedValue::to_computed_value(#binding, context))
|
||||||
});
|
});
|
||||||
let from_body = cg::fmap_match(&input, BindStyle::Ref, |field| {
|
let from_body = cg::fmap_match(&input, BindStyle::Ref, |binding| {
|
||||||
quote!(::values::computed::ToComputedValue::from_computed_value(#field))
|
quote!(::values::computed::ToComputedValue::from_computed_value(#binding))
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
|
|
@ -21,11 +21,7 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
let mut expr = if !bindings.is_empty() {
|
let mut expr = if !bindings.is_empty() {
|
||||||
let mut expr = quote! {};
|
let mut expr = quote! {};
|
||||||
for binding in bindings {
|
for binding in bindings {
|
||||||
if cg::is_parameterized(&binding.field.ty, &input.generics.ty_params) {
|
where_clause.add_trait_bound(binding.field.ty.clone());
|
||||||
where_clause.predicates.push(
|
|
||||||
cg::where_predicate(binding.field.ty.clone(), trait_path),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
expr = quote! {
|
expr = quote! {
|
||||||
#expr
|
#expr
|
||||||
writer.item(#binding)?;
|
writer.item(#binding)?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue