Diffstat (limited to 'src/protocol.rs')
-rw-r--r--src/protocol.rs132
1 files changed, 116 insertions, 16 deletions
diff --git a/src/protocol.rs b/src/protocol.rs
index c763730..fccb8ed 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -38,43 +38,143 @@ use core::{
pin::{pin, Pin},
ptr,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+ marker::PhantomData,
};
use crate::any::AnyTrait;
-pub mod visitor;
-pub mod walker;
+// pub mod visitor;
+// pub mod walker;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
-pub type Visitor<'a, 'ctx> = dyn AnyTrait<'ctx> + 'a;
-pub type Walker<'a, 'ctx> = dyn AnyTrait<'ctx> + 'a;
+pub type Visitor<'a, 'ctx, Effect> = <<Effect as self::Effect<'ctx>>::VisitorHkt as ForLtAnyTraitSendObj<'a, 'ctx, Bound<'a, 'ctx>>>::T;
+pub type Walker<'a, 'ctx, Effect> = <<Effect as self::Effect<'ctx>>::WalkerHkt as ForLtAnyTraitSendObj<'a, 'ctx, Bound<'a, 'ctx>>>::T;
-pub trait Effect: 'static {
- type ControlFlow<'a, C, B>;
+pub trait AnyTraitObj<'a, 'ctx: 'a>: AnyTraitSendObj<'a, 'ctx> {
+ fn from_obj(value: &'a mut (dyn AnyTrait<'ctx> + 'a)) -> Self;
}
-pub type ControlFlowFor<'a, E = SyncEffect, C = (), B = ()> = <E as Effect>::ControlFlow<'a, C, B>;
+// Lifetime bound to be used in `for<'lt>` blocks.
+pub type Bound<'lt, 'bound> = &'lt &'bound ();
+
+pub trait ForLtAnyTraitSendObj<'lt, 'ctx: 'lt, B> {
+ type T: AnyTraitSendObj<'lt, 'ctx>;
+}
+
+pub trait HktAnyTraitSendObj<'ctx>: for<'lt> ForLtAnyTraitSendObj<'lt, 'ctx, Bound<'lt, 'ctx>> {}
+impl<'ctx, T> HktAnyTraitSendObj<'ctx> for T where T: for<'lt> ForLtAnyTraitSendObj<'lt, 'ctx, Bound<'lt, 'ctx>> {}
+
+pub trait ForLt<'lt, 'ctx: 'lt, B> {
+ type T;
+}
+
+pub trait Hkt<'ctx>: for<'lt> ForLt<'lt, 'ctx, Bound<'lt, 'ctx>> {}
+impl<'ctx, T> Hkt<'ctx> for T where T: for<'lt> ForLt<'lt, 'ctx, Bound<'lt, 'ctx>> {}
+
+pub trait AnyTraitSendObj<'a, 'ctx: 'a> {
+ fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self;
+ fn as_obj(&self) -> &dyn AnyTrait<'ctx>;
+ fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx>;
+ fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx>;
+}
+
+impl<'a, 'ctx: 'a> AnyTraitSendObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) {
+ fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self {
+ value
+ }
+
+ fn as_obj(&self) -> &dyn AnyTrait<'ctx> {
+ *self
+ }
+
+ fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx> {
+ *self
+ }
+
+ fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx> {
+ self
+ }
+}
+
+impl<'a, 'ctx: 'a> AnyTraitSendObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + Send + 'a) {
+ fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self {
+ value
+ }
+
+ fn as_obj(&self) -> &dyn AnyTrait<'ctx> {
+ *self
+ }
+
+ fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx> {
+ *self
+ }
+
+ fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx> {
+ self
+ }
+}
+
+impl<'a, 'ctx: 'a> AnyTraitObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) {
+ fn from_obj(value: &'a mut (dyn AnyTrait<'ctx> + 'a)) -> Self {
+ value
+ }
+}
+
+pub trait Effect<'ctx, C = (), B = ()>: 'static {
+ type VisitorHkt: HktAnyTraitSendObj<'ctx>;
+ type WalkerHkt: HktAnyTraitSendObj<'ctx>;
+ type ControlFlowHkt: Hkt<'ctx>;
+}
+
+pub type ControlFlowFor<'a, 'ctx, E = SyncEffect, C = (), B = ()> =
+ <<E as Effect<'ctx, C, B>>::ControlFlowHkt as ForLt<'a, 'ctx, Bound<'a, 'ctx>>>::T;
pub enum SyncEffect {}
-impl Effect for SyncEffect {
- type ControlFlow<'a, C, B> = core::ops::ControlFlow<B, C>;
+pub struct AnyTraitSendObjHkt<'ctx>(PhantomData<fn() -> &'ctx ()>);
+
+impl<'a, 'ctx> ForLtAnyTraitSendObj<'a, 'ctx, Bound<'a, 'ctx>> for AnyTraitSendObjHkt<'ctx> {
+ type T = &'a mut (dyn AnyTrait<'ctx> + Send + 'a);
+}
+
+pub struct AnyTraitObjHkt<'ctx>(PhantomData<fn() -> &'ctx ()>);
+
+impl<'a, 'ctx> ForLtAnyTraitSendObj<'a, 'ctx, Bound<'a, 'ctx>> for AnyTraitObjHkt<'ctx> {
+ type T = &'a mut (dyn AnyTrait<'ctx> + 'a);
}
-fn noop() -> Waker {
- const VTABLE: RawWakerVTable = RawWakerVTable::new(|_| RAW, |_| {}, |_| {}, |_| {});
- const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE);
+pub struct SyncControlFlowHkt<'ctx, C, B>(PhantomData<fn() -> (&'ctx (), C, B)>);
- unsafe { Waker::from_raw(RAW) }
+impl<'a, 'ctx, C, B> ForLt<'a, 'ctx, Bound<'a, 'ctx>> for SyncControlFlowHkt<'ctx, C, B> {
+ type T = core::ops::ControlFlow<B, C>;
+}
+
+impl<'ctx, C, B> Effect<'ctx, C, B> for SyncEffect {
+ type ControlFlowHkt = SyncControlFlowHkt<'ctx, C, B>;
+
+ type VisitorHkt = AnyTraitSendObjHkt<'ctx>;
+
+ type WalkerHkt = AnyTraitSendObjHkt<'ctx>;
+}
+
+#[cfg(feature = "alloc")]
+pub struct AsyncControlFlowHkt<'ctx, C, B>(PhantomData<fn() -> (&'ctx (), C, B)>);
+
+#[cfg(feature = "alloc")]
+impl<'a, 'ctx, C, B> ForLt<'a, 'ctx, Bound<'a, 'ctx>> for AsyncControlFlowHkt<'ctx, C, B> {
+ type T = core::pin::Pin<
+ Box<dyn core::future::Future<Output = core::ops::ControlFlow<B, C>> + Send + 'a>,
+ >;
}
#[cfg(feature = "alloc")]
pub enum AsyncEffect {}
#[cfg(feature = "alloc")]
-impl Effect for AsyncEffect {
- type ControlFlow<'a, C, B> =
- core::pin::Pin<Box<dyn core::future::Future<Output = core::ops::ControlFlow<B, C>> + 'a>>;
+impl<'ctx, C, B> Effect<'ctx, C, B> for AsyncEffect {
+ type VisitorHkt = AnyTraitObjHkt<'ctx>;
+ type WalkerHkt = AnyTraitObjHkt<'ctx>;
+ type ControlFlowHkt = AsyncControlFlowHkt<'ctx, C, B>;
}