Skip to content

Instantly share code, notes, and snippets.

@cynecx

cynecx/fold.rs Secret

Created April 11, 2021 17:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cynecx/3f406413e7c57e233d43a32abbbfcee8 to your computer and use it in GitHub Desktop.
Save cynecx/3f406413e7c57e233d43a32abbbfcee8 to your computer and use it in GitHub Desktop.
pub fn fold(self, f: &mut impl FnMut(&TypeRef) -> Option<TypeRef>) -> TypeRef {
return fold_type_ref(self, f);
// FIXME: Implement proper fold infra (trait TypeFoldable, trait TypeFolder, ...)
fn fold_vec_tr(v: Vec<TypeRef>, f: &mut impl FnMut(&TypeRef) -> Option<TypeRef>) -> Vec<TypeRef> {
for type_ref in v.iter_mut() {
replace_with(type_ref, |type_ref| {
if let Some(replacement) = f(&type_ref) {
replacement
} else {
fold_type_ref(type_ref, f)
}
});
}
v
}
fn fold_type_bound(type_bound: TypeBound, f: &mut impl FnMut(&TypeRef) -> Option<TypeRef>) -> TypeBound {
match bound {
TypeBound::Path(path) => TypeBound::Path(fold_path(path, f)),
ty_bound => ty_bound,
}
}
fn fold_vec_tb(v: Vec<TypeBound>, f: &mut impl FnMut(&TypeRef) -> Option<TypeRef>) -> Vec<TypeBound> {
for type_bound in v.iter_mut() {
replace_with(type_bound, |type_bound| {
fold_type_bound(type_bound, f)
});
}
v
}
fn fold_box(b: Box<TypeRef>, f: &mut impl FnMut(&TypeRef) -> Option<TypeRef>) -> Box<TypeRef> {
if let Some(replacement) = f(&*b) {
Box::new(replacement)
} else {
b
}
}
fn fold_type_ref(type_ref: TypeRef, f: &mut impl FnMut(&TypeRef) -> Option<TypeRef>) -> TypeRef {
if let Some(replacement) = f(&type_ref) {
return replacement;
}
match type_ref {
TypeRef::Fn(types, v) => TypeRef::Fn(fold_vec_tr(types, f), v),
TypeRef::Tuple(types) => TypeRef::Tuple(fold_vec_tr(types, f)),
TypeRef::RawPtr(type_ref, mt) => TypeRef::RawPtr(fold_box(type_ref, f), mt),
TypeRef::Reference(type_ref, lr, mt) => TypeRef::Reference(fold_box(type_ref, f), lr, mt),
TypeRef::Array(type_ref) => TypeRef::Array(fold_box(type_ref, f)),
TypeRef::Slice(type_ref) => TypeRef::Slice(fold_box(type_ref, f)),
TypeRef::ImplTrait(bounds) => TypeRef::ImplTrait(fold_vec_tb(bounds, f)),
TypeRef::DynTrait(bounds) => TypeRef::DynTrait(fold_vec_tb(bounds, f)),
TypeRef::Path(path) => TypeRef::Path(fold_path(path, f)),
TypeRef::Never | TypeRef::Placeholder | TypeRef::Macro | TypeRef::Error => type_ref,
}
}
fn fold_path(path: Path, f: &mut impl FnMut(&TypeRef) -> Option<TypeRef>) -> Path {
...
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment