зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1653339 - Teach style_derive's map_type_params about mapping self correctly. r=boris
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:
Родитель
63ae9a2469
Коммит
a4fa8230aa
|
@ -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()
|
||||
})
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче