mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
style: Teach style_derive's map_type_params about mapping self correctly.
Consider the following: struct Complex<T> { something: T, #[compute(field_bound)] something_else: Generic<Self, T>, } That will generate: impl<T> ToComputedValue for Complex<T> where T: ToComputedValue, Generic<Self, T>: ToComputedValue<ComputedValue = Generic<Self, <T as ToComputedValue>::ComputedValue>>, { // ... } That last clause is obviously incorrect. map_type_params correctly maps the T, but it should know also about Self. Ideally we could just do the same as for T and do: <Self as ToComputedValue>::ComputedValue But that doesn't quite work, because we are in that implementation of the trait, and the compiler rightfully complains about we don't yet knowing the computed type. So we need to pass it explicitly, which is simple enough, if a bit annoying. Differential Revision: https://phabricator.services.mozilla.com/D83816
This commit is contained in:
parent
65a06d5003
commit
f27003c810
3 changed files with 22 additions and 13 deletions
|
@ -154,19 +154,19 @@ pub fn fmap_trait_output(input: &DeriveInput, trait_path: &Path, trait_output: &
|
|||
segment.into()
|
||||
}
|
||||
|
||||
pub fn map_type_params<F>(ty: &Type, params: &[&TypeParam], f: &mut F) -> Type
|
||||
pub fn map_type_params<F>(ty: &Type, params: &[&TypeParam], self_type: &Path, f: &mut F) -> Type
|
||||
where
|
||||
F: FnMut(&Ident) -> Type,
|
||||
{
|
||||
match *ty {
|
||||
Type::Slice(ref inner) => Type::from(TypeSlice {
|
||||
elem: Box::new(map_type_params(&inner.elem, params, f)),
|
||||
elem: Box::new(map_type_params(&inner.elem, params, self_type, f)),
|
||||
..inner.clone()
|
||||
}),
|
||||
Type::Array(ref inner) => {
|
||||
//ref ty, ref expr) => {
|
||||
Type::from(TypeArray {
|
||||
elem: Box::new(map_type_params(&inner.elem, params, f)),
|
||||
elem: Box::new(map_type_params(&inner.elem, params, self_type, f)),
|
||||
..inner.clone()
|
||||
})
|
||||
},
|
||||
|
@ -175,7 +175,7 @@ where
|
|||
elems: inner
|
||||
.elems
|
||||
.iter()
|
||||
.map(|ty| map_type_params(&ty, params, f))
|
||||
.map(|ty| map_type_params(&ty, params, self_type, f))
|
||||
.collect(),
|
||||
..inner.clone()
|
||||
}),
|
||||
|
@ -187,10 +187,16 @@ where
|
|||
if params.iter().any(|ref param| ¶m.ident == ident) {
|
||||
return f(ident);
|
||||
}
|
||||
if ident == "Self" {
|
||||
return Type::from(TypePath {
|
||||
qself: None,
|
||||
path: self_type.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Type::from(TypePath {
|
||||
qself: None,
|
||||
path: map_type_params_in_path(path, params, f),
|
||||
path: map_type_params_in_path(path, params, self_type, f),
|
||||
})
|
||||
},
|
||||
Type::Path(TypePath {
|
||||
|
@ -198,25 +204,25 @@ where
|
|||
ref path,
|
||||
}) => Type::from(TypePath {
|
||||
qself: qself.as_ref().map(|qself| QSelf {
|
||||
ty: Box::new(map_type_params(&qself.ty, params, f)),
|
||||
ty: Box::new(map_type_params(&qself.ty, params, self_type, f)),
|
||||
position: qself.position,
|
||||
..qself.clone()
|
||||
}),
|
||||
path: map_type_params_in_path(path, params, f),
|
||||
path: map_type_params_in_path(path, params, self_type, f),
|
||||
}),
|
||||
Type::Paren(ref inner) => Type::from(TypeParen {
|
||||
elem: Box::new(map_type_params(&inner.elem, params, f)),
|
||||
elem: Box::new(map_type_params(&inner.elem, params, self_type, f)),
|
||||
..inner.clone()
|
||||
}),
|
||||
Type::Group(ref inner) => Type::from(TypeGroup {
|
||||
elem: Box::new(map_type_params(&inner.elem, params, f)),
|
||||
elem: Box::new(map_type_params(&inner.elem, params, self_type, f)),
|
||||
..inner.clone()
|
||||
}),
|
||||
ref ty => panic!("type {:?} cannot be mapped yet", ty),
|
||||
}
|
||||
}
|
||||
|
||||
fn map_type_params_in_path<F>(path: &Path, params: &[&TypeParam], f: &mut F) -> Path
|
||||
fn map_type_params_in_path<F>(path: &Path, params: &[&TypeParam], self_type: &Path, f: &mut F) -> Path
|
||||
where
|
||||
F: FnMut(&Ident) -> Type,
|
||||
{
|
||||
|
@ -236,11 +242,11 @@ where
|
|||
.map(|arg| match arg {
|
||||
ty @ &GenericArgument::Lifetime(_) => ty.clone(),
|
||||
&GenericArgument::Type(ref data) => {
|
||||
GenericArgument::Type(map_type_params(data, params, f))
|
||||
GenericArgument::Type(map_type_params(data, params, self_type, f))
|
||||
},
|
||||
&GenericArgument::Binding(ref data) => {
|
||||
GenericArgument::Binding(Binding {
|
||||
ty: map_type_params(&data.ty, params, f),
|
||||
ty: map_type_params(&data.ty, params, self_type, f),
|
||||
..data.clone()
|
||||
})
|
||||
},
|
||||
|
|
|
@ -112,6 +112,7 @@ pub fn derive(mut input: DeriveInput) -> TokenStream {
|
|||
|
||||
let name = &input.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
impl #impl_generics style_traits::SpecifiedValueInfo for #name #ty_generics
|
||||
#where_clause
|
||||
|
|
|
@ -47,12 +47,15 @@ pub fn derive_to_value(
|
|||
cg::add_predicate(&mut where_clause, parse_quote!(#param: #trait_path));
|
||||
}
|
||||
|
||||
let computed_value_type = cg::fmap_trait_output(&input, &trait_path, &output_type_name);
|
||||
|
||||
let mut add_field_bound = |binding: &BindingInfo| {
|
||||
let ty = &binding.ast().ty;
|
||||
|
||||
let output_type = cg::map_type_params(
|
||||
ty,
|
||||
¶ms,
|
||||
&computed_value_type,
|
||||
&mut |ident| parse_quote!(<#ident as #trait_path>::#output_type_name),
|
||||
);
|
||||
|
||||
|
@ -142,7 +145,6 @@ pub fn derive_to_value(
|
|||
|
||||
input.generics.where_clause = where_clause;
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
let computed_value_type = cg::fmap_trait_output(&input, &trait_path, &output_type_name);
|
||||
|
||||
let impl_ = trait_impl(from_body, to_body);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue