Diffstat (limited to 'src/protocol/visitor/request_hint.rs')
-rw-r--r--src/protocol/visitor/request_hint.rs42
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))
}