use effectful::{ effective::{Canonical, Effective}, environment::{Environment, InEnvironment}, higher_ranked::Rank1, DynBind, }; use crate::{ any::type_name, protocol::{walker::hint::HintMeta, DynVisitor}, Status, }; use super::VisitResult; pub trait Recoverable<'src, E: Environment>: DynBind { fn visit<'r>( &'r mut self, scope: DynRecoverableScope<'r, 'src, E>, ) -> Canonical<'r, VisitResult, E>; } impl<'u, 'src, E: 'static> type_name::Lower<'u, 'src, &'u &'src ()> for dyn Recoverable<'static, E> { type Lowered = dyn Recoverable<'src, E> + 'u; } impl<'u, 'src, E: 'static> type_name::Raise<'u, 'src, &'u &'src ()> for dyn Recoverable<'src, E> + 'u { type Raised = dyn Recoverable<'static, E>; } impl HintMeta for dyn Recoverable<'static, E> { type Known = Rank1<()>; type Hint = Rank1<()>; } impl InEnvironment for dyn Recoverable<'static, E> { type Env = E; } pub trait RecoverableScope<'src, E: Environment>: DynBind { fn new_walk<'r>(&'r mut self, visitor: DynVisitor<'r, 'src, E>) -> Canonical<'r, Status, E>; } pub type DynRecoverableScope<'r, 'src, E> = &'r mut dyn RecoverableScope<'src, E>; pub fn visit_recoverable<'r, 'src, E: Environment>( visitor: DynVisitor<'r, 'src, E>, scope: DynRecoverableScope<'r, 'src, E>, ) -> Canonical<'r, VisitResult, E> { if let Some(object) = visitor .into_inner() .as_any_trait_mut() .upcast_mut:: + 'r>() { // Allow the visitor to give a hint if it wants. object.visit(scope) } else { // If the visitor doesn't support request hint then we continue. E::value(VisitResult::Skipped(())).cast() } }