Diffstat (limited to 'src/protocol/visitor/value.rs')
| -rw-r--r-- | src/protocol/visitor/value.rs | 161 |
1 files changed, 96 insertions, 65 deletions
diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index 20c55d9..5628eac 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -6,16 +6,17 @@ use core::ops::ControlFlow; use crate::{ any::{TypeName, TypeNameable}, - effect::{any_t, Effect, SyncEffect, Yield}, - hkt::hkt, + effect::{Effect, Future}, + higher_ranked_type, + hkt::AnySend, nameable, - protocol::walker::HintMeta, + protocol::walker::hint::HintMeta, }; /// Trait object for the [`Value`] protocol. /// /// Types implementing the [`Value`] protocol will implement this trait. -pub trait Value<'a, 'ctx: 'a, T, E: Effect<'ctx, ControlFlow<(), ()>>> { +pub trait Value<'a, 'ctx: 'a, T, E: Effect<'ctx>> { /// Visit a value of type `T`. /// /// Use this to give a value to a visitor. Its expected that a walker @@ -25,7 +26,7 @@ pub trait Value<'a, 'ctx: 'a, T, E: Effect<'ctx, ControlFlow<(), ()>>> { /// If a [`ControlFlow::Break`] is returned then the walker /// should stop walking as soon as possible as there has likely been /// and error. - fn visit(&'a mut self, value: T) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E>; + fn visit(&'a mut self, value: T) -> Future<'a, 'ctx, ControlFlow<(), ()>, E>; } nameable! { @@ -33,31 +34,31 @@ nameable! { impl [T::Name, E] for dyn Value<'a, 'ctx, T, E> + 'a where { T: TypeNameable<'a, 'ctx> + ?Sized, - E: Effect<'ctx, ControlFlow<(), ()>>, + E: Effect<'ctx>, 'ctx: 'a, } impl [T, E] where dyn Value<'a, 'ctx, T::Nameable, E> + 'a { T: TypeName<'a, 'ctx> + ?Sized, - E: Effect<'ctx, ControlFlow<(), ()>>, + E: Effect<'ctx>, 'ctx: 'a, } } -hkt!((any_t): for<'a, 'ctx> pub KnownHkt => ()); +higher_ranked_type! { + pub type Known['ctx]: (AnySend) = for<'lt> () +} // This enrolls the Value protocol into the walker hint system. -impl<'a, 'ctx: 'a, T, E: Effect<'ctx, ControlFlow<(), ()>>> HintMeta<'ctx> - for dyn Value<'a, 'ctx, T, E> + 'a -{ - type Known = KnownHkt<'ctx>; +impl<'a, 'ctx: 'a, T, E: Effect<'ctx>> HintMeta<'ctx> for dyn Value<'a, 'ctx, T, E> + 'a { + type Known = Known<'ctx>; type Hint = (); } #[cfg(test)] mod test { - use core::ops::ControlFlow; + use core::{marker::PhantomData, ops::ControlFlow}; use crate::{ any::{ @@ -65,87 +66,110 @@ mod test { AnyTrait, }, any_trait, + effect::{BlockOn, Blocking, Spin}, }; use super::*; #[test] fn visit() { - struct Visitor(Option<i32>); + struct Visitor<E>(Option<i32>, PhantomData<fn() -> E>); - impl<'a, 'ctx: 'a> Value<'a, 'ctx, OwnedStatic<i32>, SyncEffect> for Visitor { + impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, OwnedStatic<i32>, E> for Visitor<E> + where + E: Effect<'ctx>, + { fn visit( &'a mut self, OwnedStatic(value): OwnedStatic<i32>, - ) -> core::ops::ControlFlow<()> { - self.0 = Some(value); - ControlFlow::Continue(()) + ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { + E::wrap(async move { + self.0 = Some(value); + ControlFlow::Continue(()) + }) } } - impl<'a, 'ctx: 'a> Value<'a, 'ctx, BorrowedStatic<'ctx, i32>, SyncEffect> for Visitor { + impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, i32>, E> for Visitor<E> + where + E: Effect<'ctx>, + { fn visit( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, i32>, - ) -> core::ops::ControlFlow<()> { - self.0 = Some(*value); - ControlFlow::Continue(()) + ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { + E::wrap(async { + self.0 = Some(*value); + ControlFlow::Continue(()) + }) } } any_trait! { - impl['a, 'ctx] Visitor = [ - dyn Value<'ctx, OwnedStatic<i32>> + 'a, - dyn Value<'ctx, BorrowedStatic<'ctx, i32>> + 'a, - ] + impl['a, 'ctx, E] Visitor<E> = [ + dyn Value<'a, 'ctx, OwnedStatic<i32>, E> + 'a, + dyn Value<'a, 'ctx, BorrowedStatic<'ctx, i32>, E> + 'a, + ] where E: Effect<'ctx>, } - let mut v = Visitor(None); - let object: &mut dyn AnyTrait<'_> = &mut v; - object - .upcast_mut::<dyn Value<'_, OwnedStatic<i32>>>() - .unwrap() - .visit(OwnedStatic(42)); + let mut v = Visitor::<Blocking>(None, PhantomData); + let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; + Spin::block_on( + object + .upcast_mut::<dyn Value<'_, '_, OwnedStatic<i32>, Blocking>>() + .unwrap() + .visit(OwnedStatic(42)), + ); assert_eq!(v.0, Some(42)); - let object: &mut dyn AnyTrait<'_> = &mut v; - object - .upcast_mut::<dyn Value<'_, BorrowedStatic<'_, i32>>>() - .unwrap() - .visit(BorrowedStatic(&101)); + let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; + Spin::block_on( + object + .upcast_mut::<dyn Value<'_, '_, BorrowedStatic<'_, i32>, Blocking>>() + .unwrap() + .visit(BorrowedStatic(&101)), + ); assert_eq!(v.0, Some(101)); } #[test] fn visit_borrowed() { - struct Visitor<'ctx>(Option<&'ctx mut String>); + struct Visitor<'ctx, E>(Option<&'ctx mut String>, PhantomData<fn() -> E>); - impl<'a, 'ctx> Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>, SyncEffect> for Visitor<'ctx> { + impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>, E> for Visitor<'ctx, E> + where + E: Effect<'ctx>, + { fn visit( &'a mut self, BorrowedMutStatic(value): BorrowedMutStatic<'ctx, String>, - ) -> ControlFlow<()> { - self.0 = Some(value); - ControlFlow::Continue(()) + ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { + E::wrap(async { + self.0 = Some(value); + + ControlFlow::Continue(()) + }) } } any_trait! { - impl['a, 'ctx] Visitor<'ctx> = [ - dyn Value<'ctx, BorrowedMutStatic<'ctx, String>> + 'a, - ] + impl['a, 'ctx, E] Visitor<'ctx, E> = [ + dyn Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>, E> + 'a, + ] where E: Effect<'ctx> } - let mut v = Visitor(None); + let mut v = Visitor::<Blocking>(None, PhantomData); let mut y = String::from("abc"); - let object: &mut dyn AnyTrait<'_> = &mut v; - object - .upcast_mut::<dyn Value<'_, _>>() - .unwrap() - .visit(BorrowedMutStatic(&mut y)); + let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; + Spin::block_on( + object + .upcast_mut::<dyn Value<'_, '_, _, Blocking>>() + .unwrap() + .visit(BorrowedMutStatic(&mut y)), + ); v.0.unwrap().push_str("def"); assert_eq!(y, "abcdef"); @@ -153,32 +177,39 @@ mod test { #[test] fn visit_borrowed_unsized() { - struct Visitor<'ctx>(Option<&'ctx str>); + struct Visitor<'ctx, E>(Option<&'ctx str>, PhantomData<fn() -> E>); - impl<'a, 'ctx: 'a> Value<'a, 'ctx, BorrowedStatic<'ctx, str>, SyncEffect> for Visitor<'ctx> { + impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, str>, E> for Visitor<'ctx, E> + where + E: Effect<'ctx>, + { fn visit( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, str>, - ) -> ControlFlow<()> { - self.0 = Some(value); - ControlFlow::Continue(()) + ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { + E::wrap(async { + self.0 = Some(value); + ControlFlow::Continue(()) + }) } } any_trait! { - impl['a, 'ctx] Visitor<'ctx> = [ - dyn Value<'ctx, BorrowedStatic<'ctx, str>> + 'a, - ] + impl['a, 'ctx, E] Visitor<'ctx, E> = [ + dyn Value<'a, 'ctx, BorrowedStatic<'ctx, str>, E> + 'a, + ] where E: Effect<'ctx> } - let mut v = Visitor(None); + let mut v = Visitor::<Blocking>(None, PhantomData); let y = String::from("abc"); - let object: &mut dyn AnyTrait<'_> = &mut v; - object - .upcast_mut::<dyn Value<'_, BorrowedStatic<'_, str>> + '_>() - .unwrap() - .visit(BorrowedStatic(&y)); + let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; + Spin::block_on( + object + .upcast_mut::<dyn Value<'_, '_, BorrowedStatic<'_, str>, Blocking> + '_>() + .unwrap() + .visit(BorrowedStatic(&y)), + ); assert_eq!(v.0, Some("abc")); } |