use std::ops::ControlFlow; use crate::Opaque; use super::ty::{ Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, }; pub trait Visitor: Sized { type Break; fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { ty.super_visit(self) } fn visit_const(&mut self, c: &Const) -> ControlFlow { c.super_visit(self) } fn visit_reg(&mut self, reg: &Region) -> ControlFlow { reg.super_visit(self) } } pub trait Visitable { fn visit(&self, visitor: &mut V) -> ControlFlow { self.super_visit(visitor) } fn super_visit(&self, visitor: &mut V) -> ControlFlow; } impl Visitable for Ty { fn visit(&self, visitor: &mut V) -> ControlFlow { visitor.visit_ty(self) } fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self.kind() { super::ty::TyKind::RigidTy(ty) => ty.visit(visitor)?, super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor)?, super::ty::TyKind::Param(_) => {} super::ty::TyKind::Bound(_, _) => {} } ControlFlow::Continue(()) } } impl Visitable for Const { fn visit(&self, visitor: &mut V) -> ControlFlow { visitor.visit_const(self) } fn super_visit(&self, visitor: &mut V) -> ControlFlow { match &self.kind() { super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?, super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?, super::ty::ConstantKind::Param(_) | super::ty::ConstantKind::ZeroSized => {} } self.ty().visit(visitor) } } impl Visitable for Opaque { fn super_visit(&self, _visitor: &mut V) -> ControlFlow { ControlFlow::Continue(()) } } impl Visitable for Allocation { fn super_visit(&self, _visitor: &mut V) -> ControlFlow { ControlFlow::Continue(()) } } impl Visitable for UnevaluatedConst { fn super_visit(&self, visitor: &mut V) -> ControlFlow { let UnevaluatedConst { def, args, promoted } = self; def.visit(visitor)?; args.visit(visitor)?; promoted.visit(visitor) } } impl Visitable for ConstDef { fn super_visit(&self, _visitor: &mut V) -> ControlFlow { ControlFlow::Continue(()) } } impl Visitable for Option { fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self { Some(val) => val.visit(visitor), None => ControlFlow::Continue(()), } } } impl Visitable for Promoted { fn super_visit(&self, _visitor: &mut V) -> ControlFlow { ControlFlow::Continue(()) } } impl Visitable for GenericArgs { fn super_visit(&self, visitor: &mut V) -> ControlFlow { self.0.visit(visitor) } } impl Visitable for Region { fn visit(&self, visitor: &mut V) -> ControlFlow { visitor.visit_reg(self) } fn super_visit(&self, _: &mut V) -> ControlFlow { ControlFlow::Continue(()) } } impl Visitable for GenericArgKind { fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self { GenericArgKind::Lifetime(lt) => lt.visit(visitor), GenericArgKind::Type(t) => t.visit(visitor), GenericArgKind::Const(c) => c.visit(visitor), } } } impl Visitable for RigidTy { fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self { RigidTy::Bool | RigidTy::Char | RigidTy::Int(_) | RigidTy::Uint(_) | RigidTy::Float(_) | RigidTy::Never | RigidTy::Foreign(_) | RigidTy::Str => ControlFlow::Continue(()), RigidTy::Array(t, c) => { t.visit(visitor)?; c.visit(visitor) } RigidTy::Slice(inner) => inner.visit(visitor), RigidTy::RawPtr(ty, _) => ty.visit(visitor), RigidTy::Ref(reg, ty, _) => { reg.visit(visitor); ty.visit(visitor) } RigidTy::FnDef(_, args) => args.visit(visitor), RigidTy::FnPtr(sig) => sig.visit(visitor), RigidTy::Closure(_, args) => args.visit(visitor), RigidTy::Coroutine(_, args, _) => args.visit(visitor), RigidTy::CoroutineWitness(_, args) => args.visit(visitor), RigidTy::Dynamic(pred, r, _) => { pred.visit(visitor)?; r.visit(visitor) } RigidTy::Tuple(fields) => fields.visit(visitor), RigidTy::Adt(_, args) => args.visit(visitor), } } } impl Visitable for Vec { fn super_visit(&self, visitor: &mut V) -> ControlFlow { for arg in self { arg.visit(visitor)?; } ControlFlow::Continue(()) } } impl Visitable for Binder { fn super_visit(&self, visitor: &mut V) -> ControlFlow { self.value.visit(visitor) } } impl Visitable for ExistentialPredicate { fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self { ExistentialPredicate::Trait(tr) => tr.generic_args.visit(visitor), ExistentialPredicate::Projection(p) => { p.term.visit(visitor)?; p.generic_args.visit(visitor) } ExistentialPredicate::AutoTrait(_) => ControlFlow::Continue(()), } } } impl Visitable for TermKind { fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self { TermKind::Type(t) => t.visit(visitor), TermKind::Const(c) => c.visit(visitor), } } } impl Visitable for FnSig { fn super_visit(&self, visitor: &mut V) -> ControlFlow { self.inputs_and_output.visit(visitor) } }