Diffstat (limited to 'src/protocol/visitor/request_hint.rs')
| -rw-r--r-- | src/protocol/visitor/request_hint.rs | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index 0c11fcd..a110adb 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -1,6 +1,8 @@ use crate::{ any::TypeName, - effect::{Effect, ErasedEffective, ReadyExt as _}, + effect::{ + Effect, EffectExt as _, Effective as _, EffectiveExt as _, ErasedEffective, ReadyExt as _, + }, hkt::Marker, protocol::{DynVisitor, DynWalker}, }; @@ -13,10 +15,12 @@ pub trait RequestHint<'ctx, E: Effect> { /// /// `walker` is what the visitor (`self`) will call to give a hint using the /// [`Hint`][crate::builtins::walker::Hint] protocol. - fn request_hint<'a>( - &'a mut self, - walker: DynWalker<'a, 'ctx>, - ) -> ErasedEffective<'a, VisitResult<DynWalker<'a, 'ctx>>, E>; + fn request_hint<'this: 'e, 'walker: 'e, 'e>( + &'this mut self, + walker: DynWalker<'walker, 'ctx>, + ) -> ErasedEffective<'e, VisitResult, E> + where + 'ctx: 'this + 'walker; } pub struct RequestHintProto<E: Effect>(Marker<E>); @@ -43,15 +47,21 @@ where /// If [`Flow::Done`] is returned then the visitor doesn't need any more information and the walker /// should stop walking. /// If [`Flow::Break`] is returned then there was an error and the walker should stop walking. -pub fn request_hint<'a, 'ctx, E: Effect>( - visitor: DynVisitor<'a, 'ctx>, - walker: DynWalker<'a, 'ctx>, -) -> ErasedEffective<'a, VisitResult<DynWalker<'a, 'ctx>>, E> { - if let Some(object) = visitor.0.upcast_mut::<RequestHintProto<E>>() { - // Allow the visitor to give a hint if it wants. - object.request_hint(walker) - } else { - // If the visitor doesn't support request hint then we continue. - VisitResult::Skipped(walker).ready() - } +pub fn request_hint<'ctx: 'visitor + 'walker, 'visitor: 'e, 'walker: 'e, 'e, E: Effect>( + visitor: DynVisitor<'visitor, 'ctx>, + walker: DynWalker<'walker, 'ctx>, +) -> ErasedEffective<'e, VisitResult<DynWalker<'walker, 'ctx>>, E> { + E::as_ctx((visitor, walker), |(visitor, walker)| { + if let Some(object) = visitor.0.upcast_mut::<RequestHintProto<E>>() { + // Allow the visitor to give a hint if it wants. + object + .request_hint(walker.cast()) + .map(|x| x.unit_skipped()) + .cast() + } else { + // If the visitor doesn't support request hint then we continue. + E::ready(VisitResult::Skipped(())).cast() + } + }) + .map(|((_, walker), result)| result.map_skipped(|_| walker)) } |