working on async effective
Konnor Andrews 2024-05-19
parent 8382bca · commit 167a1ec
-rw-r--r--src/any.rs70
-rw-r--r--src/effect.rs234
-rw-r--r--src/effect/async.rs492
-rw-r--r--src/effect/blocking.rs269
-rw-r--r--src/effect/blocking/spin.rs46
-rw-r--r--src/hkt.rs27
6 files changed, 933 insertions, 205 deletions
diff --git a/src/any.rs b/src/any.rs
index e007f80..78190df 100644
--- a/src/any.rs
+++ b/src/any.rs
@@ -3,7 +3,7 @@
//! The `AnyTrait` trait provides dynamic upcasting to trait objects.
pub mod indirect;
-mod static_wrapper;
+// mod static_wrapper;
mod type_name_id;
use crate::{
@@ -12,7 +12,7 @@ use crate::{
};
use core::marker::PhantomData;
-pub use static_wrapper::*;
+// pub use static_wrapper::*;
pub use type_name_id::*;
#[cfg(all(feature = "alloc", not(feature = "std")))]
@@ -46,44 +46,50 @@ higher_ranked_type! {
where {
T: ?Sized + TypeName::LowerType<'a, 'ctx>
};
- }
-}
-
-pub struct MutHrt<T: ?Sized>(Marker<T>);
-
-higher_ranked_type! {
- impl TypeName {
- impl['a, 'ctx, T] type T['a, 'ctx] for MutHrt<T> =
- &'a mut TypeName::T<'a, 'ctx, T>
- where {
- T: ?Sized + TypeName::LowerForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>,
- TypeName::T<'a, 'ctx, T>: 'a
- };
- impl['a, 'ctx, T] type HigherRanked['a, 'ctx] for &'a mut T =
- MutHrt<TypeName::HigherRanked<'a, 'ctx, T>>
+ impl['a, 'ctx, T] type HigherRankedAll['a, 'ctx] for &'a T =
+ RefHrt<TypeName::HigherRankedAll<'a, 'ctx, T>>
where {
T: ?Sized + TypeName::LowerType<'a, 'ctx>
};
}
}
-#[cfg(feature = "alloc")]
-higher_ranked_type! {
- impl TypeName {
- impl['a, 'ctx, T] type T['a, 'ctx] for Box<T> =
- Box<TypeName::T<'a, 'ctx, T>>
- where {
- T: ?Sized + TypeName::LowerForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>,
- };
+pub struct MutHrt<T: ?Sized>(Marker<T>);
- impl['a, 'ctx, T] type HigherRanked['a, 'ctx] for Box<T> =
- Box<TypeName::HigherRanked<'a, 'ctx, T>>
- where {
- T: ?Sized + TypeName::LowerType<'a, 'ctx>
- };
- }
-}
+// higher_ranked_type! {
+// impl TypeName {
+// impl['a, 'ctx, T] type T['a, 'ctx] for MutHrt<T> =
+// &'a mut TypeName::T<'a, 'ctx, T>
+// where {
+// T: ?Sized + TypeName::LowerForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>,
+// TypeName::T<'a, 'ctx, T>: 'a
+// };
+//
+// impl['a, 'ctx, T] type HigherRanked['a, 'ctx] for &'a mut T =
+// MutHrt<TypeName::HigherRanked<'a, 'ctx, T>>
+// where {
+// T: ?Sized + TypeName::RaiseForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>
+// };
+// }
+// }
+
+// #[cfg(feature = "alloc")]
+// higher_ranked_type! {
+// impl TypeName {
+// impl['a, 'ctx, T] type T['a, 'ctx] for Box<T> =
+// Box<TypeName::T<'a, 'ctx, T>>
+// where {
+// T: ?Sized + TypeName::LowerForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>,
+// };
+//
+// impl['a, 'ctx, T] type HigherRanked['a, 'ctx] for Box<T> =
+// Box<TypeName::HigherRanked<'a, 'ctx, T>>
+// where {
+// T: ?Sized + TypeName::RaiseForLt<'a, 'ctx, TypeName::Bound<'a, 'ctx>>
+// };
+// }
+// }
/// Dynamic trait lookup.
///
diff --git a/src/effect.rs b/src/effect.rs
index 84b275b..e8891ad 100644
--- a/src/effect.rs
+++ b/src/effect.rs
@@ -1,7 +1,10 @@
+pub mod r#async;
pub mod blocking;
use core::{future::Future, ops::ControlFlow};
+use crate::{higher_ranked_trait, higher_ranked_type};
+
// Goal: code using the module shouldn't care if the underlying environment is async or not.
// That is the API should allow yielding without forcing it.
//
@@ -38,115 +41,163 @@ use core::{future::Future, ops::ControlFlow};
pub trait Effect:
Join<Effect = Self> + TryJoin<Effect = Self> + Send + Sync + Sized + 'static
{
- type Erased<T>: Effective<Output = T, Effect = Self>;
+ type Erased<T: Send + Sync>: ErasedHrt<T, Self>;
- type Ready<T>: Effective<Output = T, Effect = Self>;
+ type Ready<'a, T: Send + Sync + 'a>: Effective<'a, Output = T, Effect = Self>;
- fn ready<T>(value: T) -> Self::Ready<T>;
+ fn ready<'a, T: Send + Sync + 'a>(value: T) -> Self::Ready<'a, T>;
- type FromFuture<F>: Effective<Output = F::Output, Effect = Self>
+ type FromFuture<'a, F: Send + Sync + 'a>: Effective<'a, Output = F::Output, Effect = Self>
where
- F: Future;
+ F: Future,
+ F::Output: Send + Sync + 'a;
- fn from_future<F>() -> Self::FromFuture<F>
+ fn from_future<'a, F: Send + Sync + 'a>(future: F) -> Self::FromFuture<'a, F>
where
- F: Future;
+ F: Future,
+ F::Output: Send + Sync + 'a;
}
-pub trait EffectiveForLt<'a, Output: 'a, E: Effect, Bound> {
- type T: Effective<Output = Output, Effect = E>;
+pub trait ErasedForLt<'a, T: Send + Sync + 'a, E: Effect, Bound: 'a> {
+ type T: Effective<'a, Output = T, Effect = E>;
}
-pub trait EffectiveHrt<Output, E: Effect>: for<'a> EffectiveForLt<'a, Output, E, &'a Output> {}
+pub trait ErasedHrt<T: Send + Sync, E: Effect>: for<'a> ErasedForLt<'a, T, E, &'a T> {}
+
+impl<T: Send + Sync, E: Effect, U> ErasedHrt<T, E> for U where
+ U: for<'a> ErasedForLt<'a, T, E, &'a T>
+{
+}
-pub type EffectiveT<'a, V, Output, E> = <V as EffectiveForLt<'a, Output, E, &'a Output>>::T;
+pub type ErasedEffective<'lt, Output, E> =
+ <<E as Effect>::Erased<Output> as ErasedForLt<'lt, Output, E, &'lt Output>>::T;
+
+pub trait Effective<'lt>: Send + Sync + 'lt {
+ fn into_erased(self) -> ErasedEffective<'lt, Self::Output, Self::Effect>;
-pub trait Effective: Into<<Self::Effect as Effect>::Erased<Self::Output>> {
/// The effect the effective belongs to.
type Effect: Effect;
/// The type of the effective's output value.
- type Output;
+ type Output: Send + Sync + 'lt;
/// Future that resolves to the same value as the effective.
- type IntoFuture: Future<Output = Self::Output>;
+ type IntoFuture: Send + Sync + Future<Output = Self::Output>;
/// Convert the effective into a general future for use in async.
fn into_future(self) -> Self::IntoFuture;
- /// Effective performing a loop.
- type Loop<T, V, F>: Effective<Output = (Self::Output, T), Effect = Self::Effect>
- where
- F: for<'a> FnMut(&'a mut Self::Output) -> EffectiveT<'a, V, ControlFlow<T>, Self::Effect>,
- V: EffectiveHrt<ControlFlow<T>, Self::Effect>;
-
- /// Perform a loop with the effective value as context.
- ///
- /// When the callback returns break then the loop will end and the effective
- /// will resolve to the break value and the context.
- fn r#loop<T, V, F>(self, cb: F) -> Self::Loop<T, V, F>
- where
- F: for<'a> FnMut(&'a mut Self::Output) -> EffectiveT<'a, V, ControlFlow<T>, Self::Effect>,
- V: EffectiveHrt<ControlFlow<T>, Self::Effect>;
-
- type Map<T, F>: Effective<Output = T, Effect = Self::Effect>
+ // /// Effective performing a loop.
+ // type Loop<T, V, F>: Effective<Output = (Self::Output, T), Effect = Self::Effect>
+ // where
+ // F: MutFnOnceHrt<Self::Output, T, Self::Effect>;
+ //
+ // /// Perform a loop with the effective value as context.
+ // ///
+ // /// When the callback returns break then the loop will end and the effective
+ // /// will resolve to the break value and the context.
+ // fn r#loop<T, V, F>(self, cb: F) -> Self::Loop<T, V, F>
+ // where
+ // F: MutFnOnceHrt<Self::Output, T, Self::Effect>;
+
+ type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
+ 'a,
+ Output = T,
+ Effect = Self::Effect,
+ >
where
- F: FnOnce(Self::Output) -> T;
+ F: FnOnce(Self::Output) -> T,
+ 'lt: 'a;
- fn map<T, F>(self, cb: F) -> Self::Map<T, F>
+ fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
where
- F: FnOnce(Self::Output) -> T;
+ F: FnOnce(Self::Output) -> T,
+ 'lt: 'a;
- type Then<T, V, F>: Effective<Output = T, Effect = Self::Effect>
+ type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
+ 'a,
+ Output = T,
+ Effect = Self::Effect,
+ >
where
F: FnOnce(Self::Output) -> V,
- V: Effective<Output = T, Effect = Self::Effect>;
+ V: Effective<'a, Output = T, Effect = Self::Effect>;
- fn then<T, V, F>(self, cb: F) -> Self::Then<T, V, F>
+ fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
+ self,
+ cb: F,
+ ) -> Self::Then<'a, T, V, F>
where
F: FnOnce(Self::Output) -> V,
- V: Effective<Output = T, Effect = Self::Effect>;
+ V: Effective<'a, Output = T, Effect = Self::Effect>;
- type AsCtx<T, V, F>: Effective<Output = (Self::Output, T), Effect = Self::Effect>
+ type AsCtx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>: Effective<
+ 'a,
+ Output = (Self::Output, T),
+ Effect = Self::Effect,
+ >
where
- F: for<'a> FnOnce(&'a mut Self::Output) -> EffectiveT<'a, V, T, Self::Effect>,
- V: EffectiveHrt<T, Self::Effect>;
+ F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a;
- fn as_ctx<T, V, F>(self, cb: F) -> Self::AsCtx<T, V, F>
+ fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
where
- F: for<'a> FnOnce(&'a mut Self::Output) -> EffectiveT<'a, V, T, Self::Effect>,
- V: EffectiveHrt<T, Self::Effect>;
+ F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a;
}
pub trait Join {
type Effect: Effect;
- type Two<T0, T1>: Effective<Output = (T0::Output, T1::Output), Effect = Self::Effect>
+ type Two<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a>: Effective<
+ 'a,
+ Output = (T0::Output, T1::Output),
+ Effect = Self::Effect,
+ >
where
- T0: Effective<Effect = Self::Effect>,
- T1: Effective<Effect = Self::Effect>;
+ T0: Effective<'a, Effect = Self::Effect>,
+ T1: Effective<'a, Effect = Self::Effect>;
- type Three<T0, T1, T2>: Effective<
+ type Three<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a>: Effective<
+ 'a,
Output = (T0::Output, T1::Output, T2::Output),
Effect = Self::Effect,
>
where
- T0: Effective<Effect = Self::Effect>,
- T1: Effective<Effect = Self::Effect>,
- T2: Effective<Effect = Self::Effect>;
-
- fn two<T0, T1, F0, F1>(cb: (F0, F1)) -> Self::Two<T0, T1>
+ T0: Effective<'a, Effect = Self::Effect>,
+ T1: Effective<'a, Effect = Self::Effect>,
+ T2: Effective<'a, Effect = Self::Effect>;
+
+ fn two<
+ 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ >(
+ cb: (F0, F1),
+ ) -> Self::Two<'a, T0, T1>
where
- T0: Effective<Effect = Self::Effect>,
- T1: Effective<Effect = Self::Effect>,
+ T0: Effective<'a, Effect = Self::Effect>,
+ T1: Effective<'a, Effect = Self::Effect>,
F0: FnOnce() -> T0,
F1: FnOnce() -> T1;
- fn three<T0, T1, T2, F0, F1, F2>(effectives: (F0, F1, F2)) -> Self::Three<T0, T1, T2>
+ fn three<
+ 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ T2: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ F2: Send + Sync + 'a,
+ >(
+ effectives: (F0, F1, F2),
+ ) -> Self::Three<'a, T0, T1, T2>
where
- T0: Effective<Effect = Self::Effect>,
- T1: Effective<Effect = Self::Effect>,
- T2: Effective<Effect = Self::Effect>,
+ T0: Effective<'a, Effect = Self::Effect>,
+ T1: Effective<'a, Effect = Self::Effect>,
+ T2: Effective<'a, Effect = Self::Effect>,
F0: FnOnce() -> T0,
F1: FnOnce() -> T1,
F2: FnOnce() -> T2;
@@ -155,35 +206,58 @@ pub trait Join {
pub trait TryJoin {
type Effect: Effect;
- type Two<Err, V0, V1, T0, T1>: Effective<Output = Result<(T0, T1), Err>, Effect = Self::Effect>
+ type Two<'a, Err: Send + Sync + 'a, V0: Send + Sync + 'a, V1: Send + Sync + 'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a>: Effective<'a, Output = Result<(T0, T1), Err>, Effect = Self::Effect>
where
- V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>;
+ V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>;
- type Three<Err, V0, V1, V2, T0, T1, T2>: Effective<
+ type Three<'a, Err: Send + Sync + 'a, V0: Send + Sync + 'a, V1: Send + Sync + 'a, V2: Send + Sync + 'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a>: Effective<'a,
Output = Result<(T0, T1, T2), Err>,
Effect = Self::Effect,
>
where
- V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>,
- V2: Effective<Output = Result<T2, Err>, Effect = Self::Effect>;
-
- fn two<Err, T0, T1, V0, V1, F0, F1>(cb: (F0, F1)) -> Self::Two<Err, V0, V1, T0, T1>
+ V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ V2: Effective<'a, Output = Result<T2, Err>, Effect = Self::Effect>;
+
+ fn two<
+ 'a,
+ Err: Send + Sync + 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ V0: Send + Sync + 'a,
+ V1: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ >(
+ cb: (F0, F1),
+ ) -> Self::Two<'a, Err, V0, V1, T0, T1>
where
- V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>,
- F0: FnOnce() -> T0,
- F1: FnOnce() -> T1;
-
- fn three<Err, T0, T1, T2, V0, V1, V2, F0, F1, F2>(
+ V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ F0: FnOnce() -> V0,
+ F1: FnOnce() -> V1;
+
+ fn three<
+ 'a,
+ Err: Send + Sync + 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ T2: Send + Sync + 'a,
+ V0: Send + Sync + 'a,
+ V1: Send + Sync + 'a,
+ V2: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ F2: Send + Sync + 'a,
+ >(
cb: (F0, F1, F2),
- ) -> Self::Three<Err, V0, V1, V2, T0, T1, T2>
+ ) -> Self::Three<'a, Err, V0, V1, V2, T0, T1, T2>
where
- V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>,
- V2: Effective<Output = Result<T2, Err>, Effect = Self::Effect>,
- F0: FnOnce() -> T0,
- F1: FnOnce() -> T1,
- F2: FnOnce() -> T2;
+ V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ V2: Effective<'a, Output = Result<T2, Err>, Effect = Self::Effect>,
+ F0: FnOnce() -> V0,
+ F1: FnOnce() -> V1,
+ F2: FnOnce() -> V2;
}
diff --git a/src/effect/async.rs b/src/effect/async.rs
new file mode 100644
index 0000000..84aacee
--- /dev/null
+++ b/src/effect/async.rs
@@ -0,0 +1,492 @@
+use core::pin::Pin;
+
+use core::future::Future;
+
+use futures::FutureExt as _;
+use pin_project::pin_project;
+
+use crate::hkt::Marker;
+
+use super::{Effect, Effective, ErasedForLt, Join, TryJoin};
+
+pub enum Async {}
+
+pub struct ErasedHrt<T>(Marker<T>);
+
+#[pin_project(project = ErasedFutureProj)]
+pub enum ErasedFuture<'a, T> {
+ Boxed(Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>),
+ Ready(#[pin] core::future::Ready<T>),
+}
+
+pub enum BoxOrReady<'a, T> {
+ Boxed(Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>),
+ Ready(T),
+}
+
+pub type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>;
+
+impl<'a, T: Send + Sync> ErasedForLt<'a, T, Async, &'a T> for ErasedHrt<T> {
+ type T = BoxOrReady<'a, T>;
+}
+
+pub struct Value<T>(pub T);
+
+pub struct Wrapped<F>(pub F);
+
+impl Effect for Async {
+ type Erased<T: Send + Sync> = ErasedHrt<T>;
+
+ type Ready<'a, T: Send + Sync + 'a> = Value<T>;
+
+ fn ready<'a, T: Send + Sync + 'a>(value: T) -> Self::Ready<'a, T> {
+ todo!()
+ }
+
+ type FromFuture<'a, F: Send + Sync + 'a> = Wrapped<F>
+ where
+ F: futures::prelude::Future,
+ F::Output: Send + Sync + 'a;
+
+ fn from_future<'a, F: Send + Sync + 'a>(future: F) -> Self::FromFuture<'a, F>
+ where
+ F: futures::prelude::Future,
+ F::Output: Send + Sync + 'a,
+ {
+ todo!()
+ }
+}
+
+impl<'lt, U: Send + Sync + 'lt> Effective<'lt> for BoxOrReady<'lt, U> {
+ fn into_erased(self) -> super::ErasedEffective<'lt, Self::Output, Self::Effect> {
+ self
+ }
+
+ type Effect = Async;
+
+ type Output = U;
+
+ type IntoFuture = ErasedFuture<'lt, U>;
+
+ fn into_future(self) -> Self::IntoFuture {
+ match self {
+ BoxOrReady::Boxed(fut) => ErasedFuture::Boxed(fut),
+ BoxOrReady::Ready(value) => ErasedFuture::Ready(core::future::ready(value)),
+ }
+ }
+
+ type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a> = futures::future::Map<ErasedFuture<'lt, U>, F>
+ where
+ F: FnOnce(Self::Output) -> T,
+ 'lt: 'a;
+
+ fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
+ where
+ F: FnOnce(Self::Output) -> T,
+ 'lt: 'a
+ {
+ todo!()
+ }
+
+ type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>
+ = futures::future::Then<ErasedFuture<'lt, U>, V::IntoFuture, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect>;
+
+ fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
+ self,
+ cb: F,
+ ) -> Self::Then<'a, T, V, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect> {
+ todo!()
+ }
+
+ type AsCtx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = BoxedFuture<'a, T>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a;
+
+ fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a {
+ todo!()
+ }
+}
+
+impl<'lt, U: Send + Sync + 'lt> Effective<'lt> for Value<U> {
+ fn into_erased(self) -> super::ErasedEffective<'lt, Self::Output, Self::Effect> {
+ todo!()
+ }
+
+ type Effect = Async;
+
+ type Output = U;
+
+ type IntoFuture = core::future::Ready<U>;
+
+ fn into_future(self) -> Self::IntoFuture {
+ core::future::ready(self.0)
+ }
+
+ type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = core::future::Ready<T>
+ where
+ F: FnOnce(Self::Output) -> T;
+
+ fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
+ where
+ F: FnOnce(Self::Output) -> T {
+ todo!()
+ }
+
+ type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>
+ = V
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect>;
+
+ fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
+ self,
+ cb: F,
+ ) -> Self::Then<'a, T, V, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect> {
+ todo!()
+ }
+
+ type AsCtx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = BoxedFuture<'a, T>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a;
+
+ fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a {
+ todo!()
+ }
+}
+
+impl<'lt, U: Send + Sync + 'lt> Effective<'lt> for Wrapped<U>
+where
+ U: Future,
+ U::Output: Send + Sync + 'lt
+{
+ fn into_erased(self) -> super::ErasedEffective<'lt, Self::Output, Self::Effect> {
+ todo!()
+ }
+
+ type Effect = Async;
+
+ type Output = U::Output;
+
+ type IntoFuture = U;
+
+ fn into_future(self) -> Self::IntoFuture {
+ todo!()
+ }
+
+ type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = futures::future::Map<U, F>
+ where
+ F: FnOnce(Self::Output) -> T;
+
+ fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
+ where
+ F: FnOnce(Self::Output) -> T {
+ todo!()
+ }
+
+ type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>
+ = futures::future::Then<U, V::IntoFuture, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect>;
+
+ fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
+ self,
+ cb: F,
+ ) -> Self::Then<'a, T, V, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect> {
+ todo!()
+ }
+
+ type AsCtx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = BoxedFuture<'a, T>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a;
+
+ fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a {
+ todo!()
+ }
+}
+
+impl Join for Async {
+ type Effect = Self;
+
+ type Two<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a>
+ = futures::future::Join<ErasedFuture<'a, T0>, ErasedFuture<'a, T1>>
+ where
+ T0: super::Effective<'a, Effect = Self::Effect>,
+ T1: super::Effective<'a, Effect = Self::Effect>;
+
+ type Three<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a> = futures::future::Join3<ErasedFuture<'a, T0>, ErasedFuture<'a, T1>, ErasedFuture<'a, T2>, >
+ where
+ T0: super::Effective<'a, Effect = Self::Effect>,
+ T1: super::Effective<'a, Effect = Self::Effect>,
+ T2: super::Effective<'a, Effect = Self::Effect>;
+
+ fn two<
+ 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ >(
+ cb: (F0, F1),
+ ) -> Self::Two<'a, T0, T1>
+ where
+ T0: super::Effective<'a, Effect = Self::Effect>,
+ T1: super::Effective<'a, Effect = Self::Effect>,
+ F0: FnOnce() -> T0,
+ F1: FnOnce() -> T1 {
+ todo!()
+ }
+
+ fn three<
+ 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ T2: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ F2: Send + Sync + 'a,
+ >(
+ effectives: (F0, F1, F2),
+ ) -> Self::Three<'a, T0, T1, T2>
+ where
+ T0: super::Effective<'a, Effect = Self::Effect>,
+ T1: super::Effective<'a, Effect = Self::Effect>,
+ T2: super::Effective<'a, Effect = Self::Effect>,
+ F0: FnOnce() -> T0,
+ F1: FnOnce() -> T1,
+ F2: FnOnce() -> T2 {
+ todo!()
+ }
+}
+
+impl TryJoin for Async {
+ type Effect = Self;
+
+ type Two<'a, Err: Send + Sync + 'a, V0: Send + Sync + 'a, V1: Send + Sync + 'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a>
+ = futures::future::TryJoin<ErasedFuture<'a, Result<T0, Err>>, ErasedFuture<'a, Result<T1, Err>>>
+ where
+ V0: super::Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: super::Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>;
+
+ type Three<'a, Err: Send + Sync + 'a, V0: Send + Sync + 'a, V1: Send + Sync + 'a, V2: Send + Sync + 'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a>
+ = futures::future::TryJoin3<ErasedFuture<'a, Result<T0, Err>>, ErasedFuture<'a, Result<T1, Err>>, ErasedFuture<'a, Result<T1, Err>>>
+ where
+ V0: super::Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: super::Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ V2: super::Effective<'a, Output = Result<T2, Err>, Effect = Self::Effect>;
+
+ fn two<
+ 'a,
+ Err: Send + Sync + 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ V0: Send + Sync + 'a,
+ V1: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ >(
+ cb: (F0, F1),
+ ) -> Self::Two<'a, Err, V0, V1, T0, T1>
+ where
+ V0: super::Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: super::Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ F0: FnOnce() -> V0,
+ F1: FnOnce() -> V1 {
+ todo!()
+ }
+
+ fn three<
+ 'a,
+ Err: Send + Sync + 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ T2: Send + Sync + 'a,
+ V0: Send + Sync + 'a,
+ V1: Send + Sync + 'a,
+ V2: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ F2: Send + Sync + 'a,
+ >(
+ cb: (F0, F1, F2),
+ ) -> Self::Three<'a, Err, V0, V1, V2, T0, T1, T2>
+ where
+ V0: super::Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: super::Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ V2: super::Effective<'a, Output = Result<T2, Err>, Effect = Self::Effect>,
+ F0: FnOnce() -> V0,
+ F1: FnOnce() -> V1,
+ F2: FnOnce() -> V2 {
+ todo!()
+ }
+}
+
+impl<'lt, T> Future for ErasedFuture<'lt, T> {
+ type Output = T;
+
+ fn poll(self: Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> {
+ match self.project() {
+ ErasedFutureProj::Boxed(fut) => fut.poll_unpin(cx),
+ ErasedFutureProj::Ready(fut) => fut.poll(cx),
+ }
+ }
+}
+
+impl<'c, 'lt: 'c, Fut0: Send + Sync + 'lt, F0: Send + Sync + 'c, R0: Send + Sync + 'c> Effective<'c> for futures::future::Map<Fut0, F0>
+where
+ F0: FnOnce(Fut0::Output) -> R0,
+ Fut0: Future,
+ Fut0::Output: 'lt,
+{
+ fn into_erased(self) -> super::ErasedEffective<'c, Self::Output, Self::Effect> {
+ todo!()
+ }
+
+ type Effect = Async;
+
+ type Output = R0;
+
+ type IntoFuture = Self;
+
+ fn into_future(self) -> Self::IntoFuture {
+ self
+ }
+
+ type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a> =
+ futures::future::Map<Self, F>
+ where
+ F: FnOnce(Self::Output) -> T,
+ 'c: 'a;
+
+ fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
+ where
+ F: FnOnce(Self::Output) -> T,
+ 'c: 'a
+ {
+ todo!()
+ }
+
+ type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>
+ = futures::future::Then<Self, V, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect>;
+
+ fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
+ self,
+ cb: F,
+ ) -> Self::Then<'a, T, V, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect> {
+ todo!()
+ }
+
+ type AsCtx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = BoxOrReady<'a, T>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'a: 'a;
+
+ fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'a: 'a {
+ todo!()
+ }
+}
+
+impl<'c, 'lt: 'c, Fut0: Send + Sync + 'lt, V0: Send + Sync + 'lt, Fut1: Send + Sync + 'lt, F0: Send + Sync + 'c> Effective<'c> for futures::future::Then<Fut0, Fut1, F0>
+where
+ F0: FnOnce(Fut0::Output) -> V0,
+ V0: Effective<'lt, Effect = Async, IntoFuture = Fut1>,
+ Fut1: Future,
+ Fut1::Output: Send + Sync + 'lt,
+ Fut0: Future,
+ Fut0::Output: Send + Sync + 'lt,
+{
+ fn into_erased(self) -> super::ErasedEffective<'c, Self::Output, Self::Effect> {
+ todo!()
+ }
+
+ type Effect = Async;
+
+ type Output = Fut1::Output;
+
+ type IntoFuture = Self;
+
+ fn into_future(self) -> Self::IntoFuture {
+ todo!()
+ }
+
+ type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = futures::future::Map<Self, F>
+ where
+ F: FnOnce(Self::Output) -> T,
+ 'c: 'a;
+
+ fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
+ where
+ F: FnOnce(Self::Output) -> T,
+ 'c: 'a {
+ todo!()
+ }
+
+ type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>
+ = futures::future::Then<Self, V, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect>;
+
+ fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
+ self,
+ cb: F,
+ ) -> Self::Then<'a, T, V, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect> {
+ todo!()
+ }
+
+ type AsCtx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = BoxOrReady<'a, T>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'c: 'a;
+
+ fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>,
+ 'c: 'a {
+ todo!()
+ }
+}
diff --git a/src/effect/blocking.rs b/src/effect/blocking.rs
index ea97477..abadfb2 100644
--- a/src/effect/blocking.rs
+++ b/src/effect/blocking.rs
@@ -1,164 +1,253 @@
+mod spin;
+
+pub use spin::*;
+
+use crate::hkt::Marker;
+
use super::*;
-pub enum Blocking {}
+pub trait BlockOn: 'static {
+ fn block_on<F>(future: F) -> F::Output
+ where
+ F: core::future::Future + Send,
+ <F as core::future::Future>::Output: Send;
+}
+
+pub struct Blocking<B>(Marker<B>);
-pub struct Value<T>(pub T);
+#[repr(transparent)]
+pub struct Value<T, B>(pub T, Marker<B>);
+
+impl<'lt, T: Send + Sync, B: BlockOn> ErasedForLt<'lt, T, Blocking<B>, &'lt T> for Value<T, B> {
+ type T = Value<T, B>;
+}
-impl Effect for Blocking {
- type Erased<T> = Value<T>;
+impl<B: BlockOn> Effect for Blocking<B> {
+ type Erased<T: Send + Sync> = Value<T, B>;
- type Ready<T> = Value<T>;
+ type Ready<'a, T: Send + Sync + 'a> = Value<T, B>;
- fn ready<T>(value: T) -> Self::Ready<T> {
- todo!()
+ fn ready<'a, T: Send + Sync + 'a>(value: T) -> Self::Ready<'a, T> {
+ Value(value, Default::default())
}
- type FromFuture<F> = Value<F::Output>
+ type FromFuture<'a, F: Send + Sync + 'a> = Value<F::Output, B>
where
- F: Future;
+ F: Future,
+ F::Output: Send + Sync + 'a;
- fn from_future<F>() -> Self::FromFuture<F>
+ fn from_future<'a, F: Send + Sync + 'a>(future: F) -> Self::FromFuture<'a, F>
where
F: Future,
+ F::Output: Send + Sync + 'a,
{
- todo!()
+ Value(B::block_on(future), Default::default())
}
}
-impl<U> Effective for Value<U> {
- type Effect = Blocking;
+impl<'lt, U: Send + Sync + 'lt, B: BlockOn> Effective<'lt> for Value<U, B> {
+ fn into_erased(self) -> ErasedEffective<'lt, Self::Output, Self::Effect> {
+ self
+ }
+
+ type Effect = Blocking<B>;
type Output = U;
type IntoFuture = core::future::Ready<U>;
fn into_future(self) -> Self::IntoFuture {
- todo!()
- }
-
- type Loop<T, V, F> = Value<T>
- where
- F: for<'a> FnMut(&'a mut Self::Output) -> EffectiveT<'a, V, ControlFlow<T>, Self::Effect>,
- V: EffectiveHrt<ControlFlow<T>, Self::Effect>;
-
- fn r#loop<T, V, F>(self, cb: F) -> Self::Loop<T, V, F>
- where
- F: for<'a> FnMut(&'a mut Self::Output) -> EffectiveT<'a, V, ControlFlow<T>, Self::Effect>,
- V: EffectiveHrt<ControlFlow<T>, Self::Effect>,
- {
- todo!()
+ core::future::ready(self.0)
}
- type Map<T, F> = Value<T>
+ type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a> = Value<T, B>
where
F: FnOnce(Self::Output) -> T;
- fn map<T, F>(self, cb: F) -> Self::Map<T, F>
+ fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
where
F: FnOnce(Self::Output) -> T,
{
- todo!()
+ Value(cb(self.0), Default::default())
}
- type Then<T, V, F> = Value<T>
+ type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a> = Value<T, B>
where
F: FnOnce(Self::Output) -> V,
- V: Effective<Output = T, Effect = Self::Effect>;
+ V: Effective<'a, Output = T, Effect = Self::Effect>;
- fn then<T, V, F>(self, cb: F) -> Self::Then<T, V, F>
+ fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
+ self,
+ cb: F,
+ ) -> Self::Then<'a, T, V, F>
where
F: FnOnce(Self::Output) -> V,
- V: Effective<Output = T, Effect = Self::Effect>,
+ V: Effective<'a, Output = T, Effect = Self::Effect>,
{
- todo!()
+ cb(self.0).into_erased()
}
- type AsCtx<T, V, F> = Value<T>
+ type AsCtx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a> = Value<(U, T), B>
where
- F: for<'a> FnOnce(&'a mut Self::Output) -> EffectiveT<'a, V, T, Self::Effect>,
- V: EffectiveHrt<T, Self::Effect>;
+ F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a;
- fn as_ctx<T, V, F>(self, cb: F) -> Self::AsCtx<T, V, F>
+ fn as_ctx<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'a, T, F>
where
- F: for<'a> FnOnce(&'a mut Self::Output) -> EffectiveT<'a, V, T, Self::Effect>,
- V: EffectiveHrt<T, Self::Effect>,
+ F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>,
+ 'lt: 'a,
{
- todo!()
+ let mut this = self.0;
+ let result = cb(&mut this).0;
+ Value((this, result), Default::default())
}
}
-impl Join for Blocking {
- type Effect = Self;
+impl<B: BlockOn> Join for Blocking<B> {
+ type Effect = Blocking<B>;
- type Two<T0, T1> = Value<(T0::Output, T1::Output)>
+ type Two<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a> = Value<(T0::Output, T1::Output), B>
where
- T0: Effective<Effect = Self::Effect>,
- T1: Effective<Effect = Self::Effect>;
+ T0: Effective<'a, Effect = Self::Effect>,
+ T1: Effective<'a, Effect = Self::Effect>;
- type Three<T0, T1, T2> = Value<(T0::Output, T1::Output, T2::Output)>
+ type Three<'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a> = Value<(T0::Output, T1::Output, T2::Output), B>
where
- T0: Effective<Effect = Self::Effect>,
- T1: Effective<Effect = Self::Effect>,
- T2: Effective<Effect = Self::Effect>;
+ T0: Effective<'a, Effect = Self::Effect>,
+ T1: Effective<'a, Effect = Self::Effect>,
+ T2: Effective<'a, Effect = Self::Effect>;
- fn two<T0, T1, F0, F1>(cb: (F0, F1)) -> Self::Two<T0, T1>
+ fn two<
+ 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ >(
+ cb: (F0, F1),
+ ) -> Self::Two<'a, T0, T1>
where
- T0: Effective<Effect = Self::Effect>,
- T1: Effective<Effect = Self::Effect>,
+ T0: Effective<'a, Effect = Self::Effect>,
+ T1: Effective<'a, Effect = Self::Effect>,
F0: FnOnce() -> T0,
F1: FnOnce() -> T1,
{
- todo!()
+ let v0 = (cb.0)().into_erased().0;
+ let v1 = (cb.1)().into_erased().0;
+
+ Value((v0, v1), Default::default())
}
- fn three<T0, T1, T2, F0, F1, F2>(effectives: (F0, F1, F2)) -> Self::Three<T0, T1, T2>
+ fn three<
+ 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ T2: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ F2: Send + Sync + 'a,
+ >(
+ cb: (F0, F1, F2),
+ ) -> Self::Three<'a, T0, T1, T2>
where
- T0: Effective<Effect = Self::Effect>,
- T1: Effective<Effect = Self::Effect>,
- T2: Effective<Effect = Self::Effect>,
+ T0: Effective<'a, Effect = Self::Effect>,
+ T1: Effective<'a, Effect = Self::Effect>,
+ T2: Effective<'a, Effect = Self::Effect>,
F0: FnOnce() -> T0,
F1: FnOnce() -> T1,
F2: FnOnce() -> T2,
{
- todo!()
+ let v0 = (cb.0)().into_erased().0;
+ let v1 = (cb.1)().into_erased().0;
+ let v2 = (cb.2)().into_erased().0;
+
+ Value((v0, v1, v2), Default::default())
}
}
-impl TryJoin for Blocking {
- type Effect = Self;
-
- type Two<Err, V0, V1, T0, T1> = Value<Result<(T0, T1), Err>>
- where
- V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>;
+impl<B: BlockOn> TryJoin for Blocking<B> {
+ type Effect = Blocking<B>;
+
+ type Two<'a, Err: Send + Sync + 'a, V0: Send + Sync + 'a, V1: Send + Sync + 'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a> = Value<Result<(T0, T1), Err>, B>
+ where
+ V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>;
+
+ type Three<'a, Err: Send + Sync + 'a, V0: Send + Sync + 'a, V1: Send + Sync + 'a, V2: Send + Sync + 'a, T0: Send + Sync + 'a, T1: Send + Sync + 'a, T2: Send + Sync + 'a> = Value<Result<(T0, T1, T2), Err>, B>
+ where
+ V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ V2: Effective<'a, Output = Result<T2, Err>, Effect = Self::Effect>;
+
+ fn two<
+ 'a,
+ Err: Send + Sync + 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ V0: Send + Sync + 'a,
+ V1: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ >(
+ cb: (F0, F1),
+ ) -> Self::Two<'a, Err, V0, V1, T0, T1>
+ where
+ V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ F0: FnOnce() -> V0,
+ F1: FnOnce() -> V1,
+ {
+ let v0 = match (cb.0)().into_erased().0 {
+ Ok(v) => v,
+ Err(err) => return Value(Err(err), Default::default()),
+ };
- type Three<Err, V0, V1, V2, T0, T1, T2> = Value<Result<(T0, T1, T2), Err>>
- where
- V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>,
- V2: Effective<Output = Result<T2, Err>, Effect = Self::Effect>;
+ let v1 = match (cb.1)().into_erased().0 {
+ Ok(v) => v,
+ Err(err) => return Value(Err(err), Default::default()),
+ };
- fn two<Err, T0, T1, V0, V1, F0, F1>(cb: (F0, F1)) -> Self::Two<Err, V0, V1, T0, T1>
- where
- V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>,
- F0: FnOnce() -> T0,
- F1: FnOnce() -> T1,
- {
- todo!()
+ Value(Ok((v0, v1)), Default::default())
}
- fn three<Err, T0, T1, T2, V0, V1, V2, F0, F1, F2>(
+ fn three<
+ 'a,
+ Err: Send + Sync + 'a,
+ T0: Send + Sync + 'a,
+ T1: Send + Sync + 'a,
+ T2: Send + Sync + 'a,
+ V0: Send + Sync + 'a,
+ V1: Send + Sync + 'a,
+ V2: Send + Sync + 'a,
+ F0: Send + Sync + 'a,
+ F1: Send + Sync + 'a,
+ F2: Send + Sync + 'a,
+ >(
cb: (F0, F1, F2),
- ) -> Self::Three<Err, V0, V1, V2, T0, T1, T2>
- where
- V0: Effective<Output = Result<T0, Err>, Effect = Self::Effect>,
- V1: Effective<Output = Result<T1, Err>, Effect = Self::Effect>,
- V2: Effective<Output = Result<T2, Err>, Effect = Self::Effect>,
- F0: FnOnce() -> T0,
- F1: FnOnce() -> T1,
- F2: FnOnce() -> T2,
+ ) -> Self::Three<'a, Err, V0, V1, V2, T0, T1, T2>
+ where
+ V0: Effective<'a, Output = Result<T0, Err>, Effect = Self::Effect>,
+ V1: Effective<'a, Output = Result<T1, Err>, Effect = Self::Effect>,
+ V2: Effective<'a, Output = Result<T2, Err>, Effect = Self::Effect>,
+ F0: FnOnce() -> V0,
+ F1: FnOnce() -> V1,
+ F2: FnOnce() -> V2,
{
- todo!()
+ let v0 = match (cb.0)().into_erased().0 {
+ Ok(v) => v,
+ Err(err) => return Value(Err(err), Default::default()),
+ };
+
+ let v1 = match (cb.1)().into_erased().0 {
+ Ok(v) => v,
+ Err(err) => return Value(Err(err), Default::default()),
+ };
+
+ let v2 = match (cb.2)().into_erased().0 {
+ Ok(v) => v,
+ Err(err) => return Value(Err(err), Default::default()),
+ };
+
+ Value(Ok((v0, v1, v2)), Default::default())
}
}
diff --git a/src/effect/blocking/spin.rs b/src/effect/blocking/spin.rs
new file mode 100644
index 0000000..2193a3d
--- /dev/null
+++ b/src/effect/blocking/spin.rs
@@ -0,0 +1,46 @@
+use core::{
+ pin::pin,
+ ptr,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+};
+
+use super::BlockOn;
+
+/// [`BlockOn`] implementer that just spins on the future.
+///
+/// This is useful for futures that are alwayd ready.
+pub enum Spin {}
+
+impl BlockOn for Spin {
+ #[inline(always)]
+ fn block_on<F>(future: F) -> F::Output
+ where
+ F: core::future::Future + Send,
+ {
+ let waker = noop();
+ let mut context = Context::from_waker(&waker);
+
+ let mut future = pin!(future);
+ loop {
+ if let Poll::Ready(value) = future.as_mut().poll(&mut context) {
+ return value;
+ }
+ }
+ }
+}
+
+#[inline]
+pub fn noop() -> Waker {
+ const VTABLE: &RawWakerVTable = &RawWakerVTable::new(
+ // Cloning just returns a new no-op raw waker
+ |_| RAW,
+ // `wake` does nothing
+ |_| {},
+ // `wake_by_ref` does nothing
+ |_| {},
+ // Dropping does nothing as we don't allocate anything
+ |_| {},
+ );
+ const RAW: RawWaker = RawWaker::new(ptr::null(), VTABLE);
+ unsafe { Waker::from_raw(RAW) }
+}
diff --git a/src/hkt.rs b/src/hkt.rs
index 50602c1..faac1af 100644
--- a/src/hkt.rs
+++ b/src/hkt.rs
@@ -70,10 +70,11 @@ macro_rules! higher_ranked_trait {
$($($lower_where)*)?
$($($higher_where)*)?
{
- type T: RaiseForLt<$($lt,)+ $($($generic)*,)? B, HigherRanked = Self> + ?Sized + $($lower)*;
+ type T: RaiseForLt<$($lt,)+ $($($generic)*,)? B, HigherRanked = Self, HigherRankedAll = Self> + ?Sized + $($lower)*;
}
pub trait RaiseForLt<$($lt,)+ $($($generic)*,)? B>
+ : RaiseForLtAll<$($($generic)*,)? B>
where
$($($lower_where)*)?
$($($higher_where)*)?
@@ -81,6 +82,13 @@ macro_rules! higher_ranked_trait {
type HigherRanked: LowerForLt<$($lt,)+ $($($generic)*,)? B, T = Self> + ?Sized + $($higher)*;
}
+ pub trait RaiseForLtAll<$($($generic)*,)? B>
+ where
+ $($($higher_where)*)?
+ {
+ type HigherRankedAll: for<$($lt,)+> LowerForLt<$($lt,)+ $($($generic)*,)? $bound> + ?Sized + $($higher)*;
+ }
+
pub type Bound<$($lt,)+ $($($generic)*)?> = $bound;
pub trait MemberType$(<$($generic)*>)?:
@@ -113,6 +121,9 @@ macro_rules! higher_ranked_trait {
pub type HigherRanked<$($lt,)+ $($($generic)*,)? __> =
<__ as RaiseForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>>>::HigherRanked;
+
+ pub type HigherRankedAll<$($lt,)+ $($($generic)*,)? __> =
+ <__ as RaiseForLtAll<$($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>>>::HigherRankedAll;
}
}
}
@@ -127,9 +138,13 @@ macro_rules! higher_ranked_type {
$lower:ty
$(where {$($lower_where:tt)*})?;
- impl$([$($higher_generic:tt)*])? type HigherRanked[$($higher_forward:tt)*] for $higher_lower:ty =
+ impl$([$($higher_generic:tt)*])? type HigherRanked[$($higher_lt:lifetime),+]$([$($higher_forward:tt)*])? for $higher_lower:ty =
$higher:ty
$(where {$($higher_where:tt)*})?;
+
+ impl$([$($higher_all_generic:tt)*])? type HigherRankedAll[$($higher_all_lt:lifetime),+]$([$($higher_all_forward:tt)*])? for $higher_all_lower:ty =
+ $higher_all:ty
+ $(where {$($higher_all_where:tt)*})?;
}
} => {
impl$(<$($lower_generic)*>)* $higher_trait::LowerForLt<$($lower_forward)*, $higher_trait::Bound<$($lower_forward)*>> for $lower_higher
@@ -138,11 +153,17 @@ macro_rules! higher_ranked_type {
type T = $lower;
}
- impl$(<$($higher_generic)*>)* $higher_trait::RaiseForLt<$($higher_forward)*, $higher_trait::Bound<$($higher_forward)*>> for $higher_lower
+ impl$(<$($higher_generic)*>)* $higher_trait::RaiseForLt<$($higher_lt,)+ $($($higher_forward)*,)? $higher_trait::Bound<$($higher_lt,)+ $($($higher_forward)*)?>> for $higher_lower
$(where $($higher_where)*)?
{
type HigherRanked = $higher;
}
+
+ impl$(<$($higher_all_generic)*>)* $higher_trait::RaiseForLtAll<$($($higher_all_forward)*,)? $higher_trait::Bound<$($higher_all_lt,)+ $($($higher_all_forward)*)?>> for $higher_all_lower
+ $(where $($higher_all_where)*)?
+ {
+ type HigherRankedAll = $higher_all;
+ }
}
}
pub use higher_ranked_type;