2023-09-04 14:31:14 +00:00
|
|
|
use std::ops::ControlFlow;
|
|
|
|
|
|
2023-09-14 15:50:11 +00:00
|
|
|
use crate::Opaque;
|
|
|
|
|
|
|
|
|
|
use super::ty::{
|
|
|
|
|
Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind,
|
2023-09-21 12:18:10 +03:00
|
|
|
GenericArgs, Promoted, Region, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst,
|
2023-09-04 14:31:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub trait Folder: Sized {
|
|
|
|
|
type Break;
|
2023-09-28 19:21:12 +03:00
|
|
|
fn fold_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
|
2023-09-04 14:31:14 +00:00
|
|
|
ty.super_fold(self)
|
|
|
|
|
}
|
|
|
|
|
fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> {
|
|
|
|
|
c.super_fold(self)
|
|
|
|
|
}
|
2023-09-28 19:21:12 +03:00
|
|
|
fn fold_reg(&mut self, reg: &Region) -> ControlFlow<Self::Break, Region> {
|
2023-09-28 12:32:15 +03:00
|
|
|
reg.super_fold(self)
|
|
|
|
|
}
|
2023-09-04 14:31:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait Foldable: Sized + Clone {
|
|
|
|
|
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
self.super_fold(folder)
|
|
|
|
|
}
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for Ty {
|
|
|
|
|
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
2023-09-28 19:21:12 +03:00
|
|
|
folder.fold_ty(self)
|
2023-09-04 14:31:14 +00:00
|
|
|
}
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
let mut kind = self.kind();
|
|
|
|
|
match &mut kind {
|
|
|
|
|
super::ty::TyKind::RigidTy(ty) => *ty = ty.fold(folder)?,
|
|
|
|
|
super::ty::TyKind::Alias(_, alias) => alias.args = alias.args.fold(folder)?,
|
|
|
|
|
super::ty::TyKind::Param(_) => {}
|
|
|
|
|
super::ty::TyKind::Bound(_, _) => {}
|
|
|
|
|
}
|
|
|
|
|
ControlFlow::Continue(kind.into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for Const {
|
|
|
|
|
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
folder.fold_const(self)
|
|
|
|
|
}
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
let mut this = self.clone();
|
|
|
|
|
match &mut this.literal {
|
|
|
|
|
super::ty::ConstantKind::Allocated(alloc) => *alloc = alloc.fold(folder)?,
|
|
|
|
|
super::ty::ConstantKind::Unevaluated(uv) => *uv = uv.fold(folder)?,
|
2023-09-04 15:17:27 +00:00
|
|
|
super::ty::ConstantKind::Param(_) => {}
|
2023-09-04 14:31:14 +00:00
|
|
|
}
|
2023-09-04 15:07:17 +00:00
|
|
|
this.ty = this.ty.fold(folder)?;
|
2023-09-04 14:31:14 +00:00
|
|
|
ControlFlow::Continue(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for Opaque {
|
|
|
|
|
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
ControlFlow::Continue(self.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for Allocation {
|
|
|
|
|
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
ControlFlow::Continue(self.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for UnevaluatedConst {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
2023-09-04 15:07:17 +00:00
|
|
|
let UnevaluatedConst { def, args, promoted } = self;
|
2023-09-04 14:31:14 +00:00
|
|
|
ControlFlow::Continue(UnevaluatedConst {
|
|
|
|
|
def: def.fold(folder)?,
|
|
|
|
|
args: args.fold(folder)?,
|
|
|
|
|
promoted: promoted.fold(folder)?,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for ConstDef {
|
|
|
|
|
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
|
2023-09-28 00:20:32 +02:00
|
|
|
ControlFlow::Continue(*self)
|
2023-09-04 14:31:14 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Foldable> Foldable for Option<T> {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
ControlFlow::Continue(match self {
|
|
|
|
|
Some(val) => Some(val.fold(folder)?),
|
|
|
|
|
None => None,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for Promoted {
|
|
|
|
|
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
|
2023-09-28 00:20:32 +02:00
|
|
|
ControlFlow::Continue(*self)
|
2023-09-04 14:31:14 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for GenericArgs {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
ControlFlow::Continue(GenericArgs(self.0.fold(folder)?))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-21 12:18:10 +03:00
|
|
|
impl Foldable for Region {
|
2023-09-28 12:32:15 +03:00
|
|
|
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
2023-09-28 19:21:12 +03:00
|
|
|
folder.fold_reg(self)
|
2023-09-28 12:32:15 +03:00
|
|
|
}
|
2023-09-28 19:43:28 +03:00
|
|
|
fn super_fold<V: Folder>(&self, _: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
ControlFlow::Continue(self.clone())
|
2023-09-21 12:18:10 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-04 14:31:14 +00:00
|
|
|
impl Foldable for GenericArgKind {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
let mut this = self.clone();
|
|
|
|
|
match &mut this {
|
|
|
|
|
GenericArgKind::Lifetime(lt) => *lt = lt.fold(folder)?,
|
|
|
|
|
GenericArgKind::Type(t) => *t = t.fold(folder)?,
|
|
|
|
|
GenericArgKind::Const(c) => *c = c.fold(folder)?,
|
|
|
|
|
}
|
|
|
|
|
ControlFlow::Continue(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for RigidTy {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
let mut this = self.clone();
|
|
|
|
|
match &mut this {
|
|
|
|
|
RigidTy::Bool
|
|
|
|
|
| RigidTy::Char
|
|
|
|
|
| RigidTy::Int(_)
|
|
|
|
|
| RigidTy::Uint(_)
|
|
|
|
|
| RigidTy::Float(_)
|
|
|
|
|
| RigidTy::Never
|
|
|
|
|
| RigidTy::Foreign(_)
|
|
|
|
|
| RigidTy::Str => {}
|
|
|
|
|
RigidTy::Array(t, c) => {
|
|
|
|
|
*t = t.fold(folder)?;
|
|
|
|
|
*c = c.fold(folder)?;
|
|
|
|
|
}
|
|
|
|
|
RigidTy::Slice(inner) => *inner = inner.fold(folder)?,
|
|
|
|
|
RigidTy::RawPtr(ty, _) => *ty = ty.fold(folder)?,
|
2023-09-28 19:46:39 +03:00
|
|
|
RigidTy::Ref(reg, ty, _) => {
|
|
|
|
|
*reg = reg.fold(folder)?;
|
|
|
|
|
*ty = ty.fold(folder)?
|
|
|
|
|
}
|
2023-09-04 14:31:14 +00:00
|
|
|
RigidTy::FnDef(_, args) => *args = args.fold(folder)?,
|
|
|
|
|
RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?,
|
|
|
|
|
RigidTy::Closure(_, args) => *args = args.fold(folder)?,
|
|
|
|
|
RigidTy::Generator(_, args, _) => *args = args.fold(folder)?,
|
|
|
|
|
RigidTy::Dynamic(pred, r, _) => {
|
|
|
|
|
*pred = pred.fold(folder)?;
|
|
|
|
|
*r = r.fold(folder)?;
|
|
|
|
|
}
|
|
|
|
|
RigidTy::Tuple(fields) => *fields = fields.fold(folder)?,
|
|
|
|
|
RigidTy::Adt(_, args) => *args = args.fold(folder)?,
|
|
|
|
|
}
|
|
|
|
|
ControlFlow::Continue(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Foldable> Foldable for Vec<T> {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
let mut this = self.clone();
|
|
|
|
|
for arg in &mut this {
|
|
|
|
|
*arg = arg.fold(folder)?;
|
|
|
|
|
}
|
|
|
|
|
ControlFlow::Continue(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Foldable> Foldable for Binder<T> {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
ControlFlow::Continue(Self {
|
|
|
|
|
value: self.value.fold(folder)?,
|
|
|
|
|
bound_vars: self.bound_vars.clone(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for ExistentialPredicate {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
let mut this = self.clone();
|
|
|
|
|
match &mut this {
|
|
|
|
|
ExistentialPredicate::Trait(tr) => tr.generic_args = tr.generic_args.fold(folder)?,
|
|
|
|
|
ExistentialPredicate::Projection(p) => {
|
|
|
|
|
p.term = p.term.fold(folder)?;
|
|
|
|
|
p.generic_args = p.generic_args.fold(folder)?;
|
|
|
|
|
}
|
|
|
|
|
ExistentialPredicate::AutoTrait(_) => {}
|
|
|
|
|
}
|
|
|
|
|
ControlFlow::Continue(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for TermKind {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
ControlFlow::Continue(match self {
|
|
|
|
|
TermKind::Type(t) => TermKind::Type(t.fold(folder)?),
|
|
|
|
|
TermKind::Const(c) => TermKind::Const(c.fold(folder)?),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Foldable for FnSig {
|
|
|
|
|
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
|
|
|
|
|
ControlFlow::Continue(Self {
|
|
|
|
|
inputs_and_output: self.inputs_and_output.fold(folder)?,
|
|
|
|
|
c_variadic: self.c_variadic,
|
|
|
|
|
unsafety: self.unsafety,
|
|
|
|
|
abi: self.abi.clone(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-09-04 15:18:53 +00:00
|
|
|
|
|
|
|
|
pub enum Never {}
|
|
|
|
|
|
|
|
|
|
/// In order to instantiate a `Foldable`'s generic parameters with specific arguments,
|
|
|
|
|
/// `GenericArgs` can be used as a `Folder` that replaces all mentions of generic params
|
|
|
|
|
/// with the entries in its list.
|
|
|
|
|
impl Folder for GenericArgs {
|
|
|
|
|
type Break = Never;
|
|
|
|
|
|
2023-09-28 19:21:12 +03:00
|
|
|
fn fold_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
|
2023-09-04 15:18:53 +00:00
|
|
|
ControlFlow::Continue(match ty.kind() {
|
|
|
|
|
TyKind::Param(p) => self[p],
|
|
|
|
|
_ => *ty,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> {
|
|
|
|
|
ControlFlow::Continue(match &c.literal {
|
|
|
|
|
ConstantKind::Param(p) => self[p.clone()].clone(),
|
|
|
|
|
_ => c.clone(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|