working with new effects
48 files changed, 1429 insertions, 917 deletions
@@ -9,7 +9,10 @@ mod type_name_id; use crate::hkt::{Invariant, Marker}; use core::marker::PhantomData; -use effectful::{bound::IsSync, environment::{DynBind, EnvConfig, Environment, InEnvironment}}; +use effectful::{ + bound::IsSync, + environment::{DynBind, EnvConfig, Environment, InEnvironment}, +}; pub use static_wrapper::*; pub use type_name_id::*; @@ -28,7 +31,10 @@ pub mod TypeName { type T: ?Sized + LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx (), Higher = Self>; } - pub trait MemberType<E: EnvConfig>: 'static + for<'a, 'ctx> MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> {} + pub trait MemberType<E: EnvConfig>: + 'static + for<'a, 'ctx> MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + { + } impl<T: ?Sized, E: EnvConfig> MemberType<E> for T where T: 'static + for<'a, 'ctx> MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> @@ -36,10 +42,13 @@ pub mod TypeName { } pub trait LowerTypeWithBound<'a, 'ctx: 'a, E: EnvConfig, B>: 'a + DynBind<E> { - type Higher: ?Sized + MemberTypeForLt<'a, 'ctx, E, &'a &'ctx (), T = Self> /* + MemberType<E>*/; + type Higher: ?Sized + MemberTypeForLt<'a, 'ctx, E, &'a &'ctx (), T = Self> + 'static; } - pub trait LowerType<'a, 'ctx: 'a, E: EnvConfig>: LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> {} + pub trait LowerType<'a, 'ctx: 'a, E: EnvConfig>: + LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> + { + } impl<'a, 'ctx: 'a, T: ?Sized, E: EnvConfig> LowerType<'a, 'ctx, E> for T where T: LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> @@ -53,7 +62,8 @@ pub mod TypeName { pub struct RefHrt<T: ?Sized>(Marker<T>); -impl<'a, 'lt, T: ?Sized, E: EnvConfig, B> TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B> for RefHrt<T> +impl<'a, 'lt, T: ?Sized, E: EnvConfig, B> TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B> + for RefHrt<T> where T: TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B>, <T as TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B>>::T: IsSync<E::NeedSend>, @@ -61,7 +71,8 @@ where type T = &'a <T as TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B>>::T; } -impl<'a, 'lt, T: ?Sized, E: EnvConfig, B> TypeName::LowerTypeWithBound<'a, 'lt, E, &'a &'lt B> for &'a T +impl<'a, 'lt, T: ?Sized, E: EnvConfig, B> TypeName::LowerTypeWithBound<'a, 'lt, E, &'a &'lt B> + for &'a T where T: TypeName::LowerTypeWithBound<'a, 'lt, E, &'a &'lt B>, T: IsSync<E::NeedSend>, @@ -71,14 +82,16 @@ where pub struct MutHrt<T: ?Sized>(Marker<T>); -impl<'a, 'lt, T: ?Sized, E: EnvConfig, B> TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B> for MutHrt<T> +impl<'a, 'lt, T: ?Sized, E: EnvConfig, B> TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B> + for MutHrt<T> where T: TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B>, { type T = &'a mut <T as TypeName::MemberTypeForLt<'a, 'lt, E, &'a &'lt B>>::T; } -impl<'a, 'lt, T: ?Sized, E: EnvConfig, B> TypeName::LowerTypeWithBound<'a, 'lt, E, &'a &'lt B> for &'a mut T +impl<'a, 'lt, T: ?Sized, E: EnvConfig, B> TypeName::LowerTypeWithBound<'a, 'lt, E, &'a &'lt B> + for &'a mut T where T: TypeName::LowerTypeWithBound<'a, 'lt, E, &'a &'lt B>, { @@ -86,7 +99,8 @@ where } #[cfg(feature = "alloc")] -impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> for Box<T> +impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + for Box<T> where T: TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()>, { @@ -94,7 +108,8 @@ where } #[cfg(feature = "alloc")] -impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> for Box<T> +impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> + for Box<T> where T: TypeName::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()>, { @@ -404,7 +419,9 @@ impl<'a, 'ctx, I: Indirect<'a>, E: EnvConfig> AnyTraitObject<'a, 'ctx, I, E> { /// /// If the type of the stored value is different, then `self` is /// returned as is. - pub fn downcast<T: ?Sized + TypeName::LowerType<'a, 'ctx, E>>(self) -> Result<I::ForT<T>, Self> { + pub fn downcast<T: ?Sized + TypeName::LowerType<'a, 'ctx, E>>( + self, + ) -> Result<I::ForT<T>, Self> { if self.id() == TypeNameId::of_lower::<T, E>() { // SAFETY: We know that the type name type is unique per T because it is bijective. // A self is only made in Self::new where the info is taken from T. @@ -485,20 +502,20 @@ mod test { // The following makes sure that a U could never become a T by the raise then lower process. // This proves that the bijective type names are really bijective. - fn _is_bijective_raise<'a, 'ctx: 'a, T>( - x: &TypeName::T<'a, 'ctx, TypeName::HigherRanked<'a, 'ctx, T>>, + fn _is_bijective_raise<'a, 'ctx: 'a, T, E: Environment>( + x: &TypeName::T<'a, 'ctx, TypeName::HigherRanked<'a, 'ctx, T, E>, E>, ) where - T: TypeName::LowerType<'a, 'ctx>, + T: TypeName::LowerType<'a, 'ctx, E>, { // If C -> B -> A -> B -> C (shown by this assignment), then C and A must be bijective. let _y: &T = x; } // This proves that the bijective type names are really bijective. - fn _is_bijective_lower<'a, 'ctx: 'a, U>( - x: &TypeName::HigherRanked<'a, 'ctx, TypeName::T<'a, 'ctx, U>>, + fn _is_bijective_lower<'a, 'ctx: 'a, U, E: Environment>( + x: &TypeName::HigherRanked<'a, 'ctx, TypeName::T<'a, 'ctx, U, E>, E>, ) where - U: TypeName::MemberType, + U: TypeName::MemberType<E>, { // If A -> B -> C -> B -> A (shown by this assignment), then A and C must be bijective. let _y: &U = x; diff --git a/src/any/static_wrapper.rs b/src/any/static_wrapper.rs index f27b34e..efc6839 100644 --- a/src/any/static_wrapper.rs +++ b/src/any/static_wrapper.rs @@ -13,14 +13,16 @@ pub struct OwnedStatic<T: ?Sized>(pub T); forward_send_sync!({T: (?Sized)} {} OwnedStatic<T>); -impl<'a, 'ctx, E: EnvConfig, T> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> for OwnedStatic<T> +impl<'a, 'ctx, E: EnvConfig, T> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + for OwnedStatic<T> where T: DynBind<E> + 'static, { type T = OwnedStatic<T>; } -impl<'a, 'ctx, E: EnvConfig, T> TypeName::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> for OwnedStatic<T> +impl<'a, 'ctx, E: EnvConfig, T> TypeName::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> + for OwnedStatic<T> where T: DynBind<E> + 'static, { @@ -36,7 +38,8 @@ forward_send_sync!({} {T: (?Sized + 'ctx)} {{'ctx}} BorrowedStatic<'ctx, T>); pub struct BorrowedStaticHrt<T: ?Sized>(Marker<T>); -impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> for BorrowedStaticHrt<T> +impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + for BorrowedStaticHrt<T> where T: DynBind<E> + IsSync<E::NeedSend> + 'static, { @@ -135,7 +138,8 @@ pub struct BoxedStatic<T: ?Sized>(pub Box<T>); forward_send_sync!({T: (?Sized)} {} BoxedStatic<T>); #[cfg(feature = "alloc")] -impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> for BoxedStatic<T> +impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + for BoxedStatic<T> where T: DynBind<E> + 'static, { @@ -143,7 +147,8 @@ where } #[cfg(feature = "alloc")] -impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> for BoxedStatic<T> +impl<'a, 'ctx, E: EnvConfig, T: ?Sized> TypeName::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> + for BoxedStatic<T> where T: DynBind<E> + 'static, { @@ -152,13 +157,17 @@ where #[cfg(test)] mod test { + use effectful::{block_on::Spin, bound::No, environment::Cfg, blocking::Blocking as Block}; + use super::*; + type Blocking = Block<Cfg<Spin, No, No>>; + #[test] fn owned_static_has_type_name() { - let a = TypeNameId::of_value(&OwnedStatic(42_i32)); - let b = TypeNameId::of_value(&OwnedStatic(123_i32)); - let c = TypeNameId::of_value(&OwnedStatic(true)); + let a = TypeNameId::of_value::<_, Blocking>(&OwnedStatic(42_i32)); + let b = TypeNameId::of_value::<_, Blocking>(&OwnedStatic(123_i32)); + let c = TypeNameId::of_value::<_, Blocking>(&OwnedStatic(true)); assert_eq!(a, b); assert_ne!(a, c); @@ -167,9 +176,9 @@ mod test { #[test] fn borrowed_static_has_type_name() { - let a = TypeNameId::of_value(&BorrowedStatic(&42_i32)); - let b = TypeNameId::of_value(&BorrowedStatic(&123_i32)); - let c = TypeNameId::of_value(&BorrowedStatic(&true)); + let a = TypeNameId::of_value::<_, Blocking>(&BorrowedStatic(&42_i32)); + let b = TypeNameId::of_value::<_, Blocking>(&BorrowedStatic(&123_i32)); + let c = TypeNameId::of_value::<_, Blocking>(&BorrowedStatic(&true)); assert_eq!(a, b); assert_ne!(a, c); @@ -178,9 +187,9 @@ mod test { #[test] fn temp_borrowed_static_has_type_name() { - let a = TypeNameId::of_value(&TempBorrowedStatic(&42_i32)); - let b = TypeNameId::of_value(&TempBorrowedStatic(&123_i32)); - let c = TypeNameId::of_value(&TempBorrowedStatic(&true)); + let a = TypeNameId::of_value::<_, Blocking>(&TempBorrowedStatic(&42_i32)); + let b = TypeNameId::of_value::<_, Blocking>(&TempBorrowedStatic(&123_i32)); + let c = TypeNameId::of_value::<_, Blocking>(&TempBorrowedStatic(&true)); assert_eq!(a, b); assert_ne!(a, c); @@ -193,9 +202,9 @@ mod test { let mut b = 123_i32; let mut c = true; - let a = TypeNameId::of_value(&BorrowedMutStatic(&mut a)); - let b = TypeNameId::of_value(&BorrowedMutStatic(&mut b)); - let c = TypeNameId::of_value(&BorrowedMutStatic(&mut c)); + let a = TypeNameId::of_value::<_, Blocking>(&BorrowedMutStatic(&mut a)); + let b = TypeNameId::of_value::<_, Blocking>(&BorrowedMutStatic(&mut b)); + let c = TypeNameId::of_value::<_, Blocking>(&BorrowedMutStatic(&mut c)); assert_eq!(a, b); assert_ne!(a, c); @@ -208,9 +217,9 @@ mod test { let mut b = 123_i32; let mut c = true; - let a = TypeNameId::of_value(&TempBorrowedMutStatic(&mut a)); - let b = TypeNameId::of_value(&TempBorrowedMutStatic(&mut b)); - let c = TypeNameId::of_value(&TempBorrowedMutStatic(&mut c)); + let a = TypeNameId::of_value::<_, Blocking>(&TempBorrowedMutStatic(&mut a)); + let b = TypeNameId::of_value::<_, Blocking>(&TempBorrowedMutStatic(&mut b)); + let c = TypeNameId::of_value::<_, Blocking>(&TempBorrowedMutStatic(&mut c)); assert_eq!(a, b); assert_ne!(a, c); @@ -220,9 +229,9 @@ mod test { #[test] #[cfg(feature = "alloc")] fn boxed_static_has_type_name() { - let a = TypeNameId::of_value(&BoxedStatic(Box::new(42_i32))); - let b = TypeNameId::of_value(&BoxedStatic(Box::new(123_i32))); - let c = TypeNameId::of_value(&BoxedStatic(Box::new(true))); + let a = TypeNameId::of_value::<_, Blocking>(&BoxedStatic(Box::new(42_i32))); + let b = TypeNameId::of_value::<_, Blocking>(&BoxedStatic(Box::new(123_i32))); + let c = TypeNameId::of_value::<_, Blocking>(&BoxedStatic(Box::new(true))); assert_eq!(a, b); assert_ne!(a, c); diff --git a/src/any/type_name_id.rs b/src/any/type_name_id.rs index d1b4acf..19c6a91 100644 --- a/src/any/type_name_id.rs +++ b/src/any/type_name_id.rs @@ -35,7 +35,8 @@ impl TypeNameId { /// Get the type ID from a lower type. #[inline(always)] - pub fn of_lower<'a, 'ctx: 'a, T: ?Sized + TypeName::LowerType<'a, 'ctx, E>, E: EnvConfig>() -> Self { + pub fn of_lower<'a, 'ctx: 'a, T: ?Sized + TypeName::LowerType<'a, 'ctx, E>, E: EnvConfig>( + ) -> Self { Self { name_id: TypeId::of::<TypeName::HigherRanked<'a, 'ctx, T, E>>(), @@ -46,7 +47,9 @@ impl TypeNameId { /// Get the type ID of a lower type's value. #[inline(always)] - pub fn of_value<'a, 'ctx: 'a, T: ?Sized + TypeName::LowerType<'a, 'ctx, E>, E: EnvConfig>(_: &T) -> Self { + pub fn of_value<'a, 'ctx: 'a, T: ?Sized + TypeName::LowerType<'a, 'ctx, E>, E: EnvConfig>( + _: &T, + ) -> Self { Self::of_lower::<'a, 'ctx, T, E>() } diff --git a/src/build.rs b/src/build.rs index a975b5c..eca91af 100644 --- a/src/build.rs +++ b/src/build.rs @@ -3,9 +3,7 @@ pub mod builders; use effectful::environment::{DynBind, EnvConfig, Environment, NativeForm}; -use crate::{ - protocol::{AsVisitor, DynVisitor}, -}; +use crate::protocol::{AsVisitor, DynVisitor}; /// A buildable type. pub trait Build<'ctx, M, E: Environment>: Sized + DynBind<E> { @@ -36,7 +34,9 @@ pub trait BuilderTypes<C: EnvConfig> { /// the builder with data from it's walk. /// - Call [`Self::build()`] to finish building the value and get any errors /// that happened during filling it with data. -pub trait Builder<'ctx, E: Environment>: DynBind<E> + AsVisitor<'ctx, E> + BuilderTypes<E> + Sized { +pub trait Builder<'ctx, E: Environment>: + DynBind<E> + AsVisitor<'ctx, E> + BuilderTypes<E> + Sized +{ fn from_seed<'a>(seed: Self::Seed) -> NativeForm<'a, Self, E> where Self: 'a; diff --git a/src/build/builders/core.rs b/src/build/builders/core.rs index 3f8b2a5..caff6eb 100644 --- a/src/build/builders/core.rs +++ b/src/build/builders/core.rs @@ -1,4 +1,9 @@ -use effectful::{environment::{Environment, NativeForm}, is_send_sync}; +use effectful::{ + effective::Effective, + environment::{Environment, NativeForm}, + higher_ranked::Mut, + is_send_sync, +}; use crate::{ any_trait, @@ -36,11 +41,14 @@ impl NoopVisitor { pub fn walk_dyn<'ctx: 'e, 'walker: 'e, 'e, E: Environment>( walker: DynWalkerObjSafe<'walker, 'ctx, E>, ) -> NativeForm<'e, VisitResult, E> { - E::value(NoopVisitor::new()).as_ctx_map(|noop| { - walker - .walk(DynVisitor(noop)) - .map(|x| x.to_continue().into()) - .cast() - }) + E::value(NoopVisitor::new()) + .update(walker, |walker, noop| { + walker + .walk(DynVisitor(noop)) + .map((), |_, x| x.to_continue().into()) + .cast() + }) + .map((), |_, (_, x)| x) + .cast() } } diff --git a/src/build/builders/core/enum.rs b/src/build/builders/core/enum.rs index 02fa9fe..aaa44ff 100644 --- a/src/build/builders/core/enum.rs +++ b/src/build/builders/core/enum.rs @@ -1,9 +1,8 @@ use core::fmt::{Debug, Display}; use effectful::bound::{Bool, IsSend, IsSync}; -use effectful::closure::Capture; -use effectful::environment::{DynBind, Environment, NativeForm}; use effectful::effective::Effective; +use effectful::environment::{DynBind, Environment, NativeForm}; use effectful::forward_send_sync; use effectful::higher_ranked::Mut; @@ -28,15 +27,19 @@ where inner: Inner<'ctx, Info, Mode, E>, } -unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> for EnumBuilder<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> + for EnumBuilder<'ctx, Info, Mode, E> where Info: EnumBuildInfo<'ctx, Mode, E>, -{} +{ +} -unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> for EnumBuilder<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> + for EnumBuilder<'ctx, Info, Mode, E> where Info: EnumBuildInfo<'ctx, Mode, E>, -{} +{ +} enum Inner<'ctx, Info, Mode, E: Environment> where @@ -48,22 +51,22 @@ where Value(Result<Info::T, Info::Error>), } -unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> for Inner<'ctx, Info, Mode, E> -where - Info: EnumBuildInfo<'ctx, Mode, E>, -{} +unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> for Inner<'ctx, Info, Mode, E> where + Info: EnumBuildInfo<'ctx, Mode, E> +{ +} -unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> for Inner<'ctx, Info, Mode, E> -where - Info: EnumBuildInfo<'ctx, Mode, E>, -{} +unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> for Inner<'ctx, Info, Mode, E> where + Info: EnumBuildInfo<'ctx, Mode, E> +{ +} pub trait EnumBuildInfo<'ctx, Mode, E: Environment> { type Builders: DynBind<E>; type Seed: DynBind<E>; - type Error: DynBind<E> + Debug + Display; + type Error: DynBind<E> + Debug + Display; type ValueT: TypeName::MemberType<E>; @@ -115,7 +118,8 @@ where { E::value(Self { inner: Inner::Seed(seed), - }).cast() + }) + .cast() } fn build<'a>(self) -> NativeForm<'a, Result<Self::Value, Self::Error>, E> @@ -183,10 +187,12 @@ where scope: DynRecoverableScope<'a, 'ctx, E>, ) -> NativeForm<'a, VisitResult, E> { match core::mem::replace(&mut self.inner, Inner::Temp) { - Inner::Seed(seed) => Info::guess_variant(seed, scope).map(Capture(self).fun_once(|this, result, _| { - this.inner = Inner::Value(result); - Flow::Done.into() - })).cast(), + Inner::Seed(seed) => Info::guess_variant(seed, scope) + .map(self, |this, result| { + this.inner = Inner::Value(result); + Flow::Done.into() + }) + .cast(), inner => { self.inner = inner; E::value(Flow::Continue.into()).cast() @@ -195,7 +201,8 @@ where } } -impl<'ctx, Info, Mode, E: Environment> Value<'ctx, Info::ValueT, E> for EnumBuilder<'ctx, Info, Mode, E> +impl<'ctx, Info, Mode, E: Environment> Value<'ctx, Info::ValueT, E> + for EnumBuilder<'ctx, Info, Mode, E> where Info: EnumBuildInfo<'ctx, Mode, E>, { @@ -212,7 +219,8 @@ where } } -impl<'ctx, Info, Mode, E: Environment> Tag<'ctx, tags::Variant, E> for EnumBuilder<'ctx, Info, Mode, E> +impl<'ctx, Info, Mode, E: Environment> Tag<'ctx, tags::Variant, E> + for EnumBuilder<'ctx, Info, Mode, E> where Info: EnumBuildInfo<'ctx, Mode, E>, { @@ -224,28 +232,30 @@ where let visitor = VariantVisitor::<Info, Mode, E> { marker: None }; E::value((visitor, walker)) - .update(Capture(()).fun_once_hrt::<Mut<_>, _>(|_, (visitor, walker), _| { - walker.walk(DynVisitor(visitor)).cast() - })) - .then(Capture(self).fun_once(|this, ((visitor, _), result), _| { - if let Some(variant) = visitor.marker { - match core::mem::replace(&mut this.inner, Inner::Temp) { - // A variant was given so we need to make the builder for - // it. - Inner::Seed(seed) => Info::new_builder(seed, variant).map(Capture((this, result)).fun_once(|(this, result), builder, _| { - this.inner = Inner::Builder { builder }; - result.to_done().into() - })).cast::<()>(), - inner => { - this.inner = inner; - E::value(result.to_done().into()).cast() + .update((), |_, (visitor, walker)| { + walker.walk(DynVisitor(visitor)).cast() + }) + .then(self, |this, ((visitor, _), result)| { + if let Some(variant) = visitor.marker { + match core::mem::replace(&mut this.inner, Inner::Temp) { + // A variant was given so we need to make the builder for + // it. + Inner::Seed(seed) => Info::new_builder(seed, variant) + .map((this, result), |(this, result), builder| { + this.inner = Inner::Builder { builder }; + result.to_done().into() + }) + .cast::<()>(), + inner => { + this.inner = inner; + E::value(result.to_done().into()).cast() + } } + } else { + E::value(result.to_done().into()).cast() } - } else { - E::value(result.to_done().into()).cast() - } - })) - .cast() + }) + .cast() } } @@ -256,15 +266,19 @@ where marker: Option<Info::VariantMarker>, } -unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> for VariantVisitor<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> + for VariantVisitor<'ctx, Info, Mode, E> where Info: EnumBuildInfo<'ctx, Mode, E>, -{} +{ +} -unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> for VariantVisitor<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> + for VariantVisitor<'ctx, Info, Mode, E> where Info: EnumBuildInfo<'ctx, Mode, E>, -{} +{ +} any_trait! { impl['ctx, Info, Mode][E] VariantVisitor<'ctx, Info, Mode, E> = [ diff --git a/src/build/builders/core/struct.rs b/src/build/builders/core/struct.rs index ef46628..6752acb 100644 --- a/src/build/builders/core/struct.rs +++ b/src/build/builders/core/struct.rs @@ -1,6 +1,12 @@ use core::fmt::{Debug, Display}; -use effectful::{bound::{IsSend, IsSync}, closure::Capture, effective::Effective, environment::{DynBind, Environment, NativeForm}, higher_ranked::Mut, tri}; +use effectful::{ + bound::{IsSend, IsSync}, + effective::Effective, + environment::{DynBind, Environment, NativeForm}, + higher_ranked::Mut, + tri, +}; use crate::{ any::{OwnedStatic, TempBorrowedStatic, TempBorrowedStaticHrt, TypeName}, @@ -28,15 +34,19 @@ where inner: Inner<'ctx, Info, Mode, E>, } -unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> for StructBuilder<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> + for StructBuilder<'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, -{} +{ +} -unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> for StructBuilder<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> + for StructBuilder<'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, -{} +{ +} enum Inner<'ctx, Info, Mode, E: Environment> where @@ -130,15 +140,19 @@ where error: Info::Error, } -unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> for StructError<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> + for StructError<'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, -{} +{ +} -unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> for StructError<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> + for StructError<'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, -{} +{ +} impl<'ctx, Info, Mode, E: Environment> StructError<'ctx, Info, Mode, E> where @@ -187,12 +201,14 @@ where 'ctx: 'e, { match core::mem::replace(&mut self.inner, Inner::Temp) { - Inner::Seed(seed) => Info::new_builders(seed).map(Capture(self).fun_once(|this, builders, _| { - this.inner = Inner::Builders { - builders, - kind: StructKind::Tuple, - }; - })).cast(), + Inner::Seed(seed) => Info::new_builders(seed) + .map(self, |this, builders| { + this.inner = Inner::Builders { + builders, + kind: StructKind::Tuple, + }; + }) + .cast(), inner => { self.inner = inner; @@ -213,7 +229,8 @@ where { E::value(Self { inner: Inner::Seed(seed), - }).cast() + }) + .cast() } fn build<'a>(self) -> NativeForm<'a, Result<Self::Value, Self::Error>, E> @@ -225,13 +242,14 @@ where Inner::Seed(seed) => { // We may be able to make a value from just the seed. Info::new_builders(seed) - .then(Capture(()).fun_once(|_, builders, _| Info::from_builders(builders))) - .map(Capture(()).fun_once(|_, result, _| result.map_err(StructError::from_field_err))).cast() + .then((), |_, builders| Info::from_builders(builders)) + .map((), |_, result| result.map_err(StructError::from_field_err)) + .cast() } Inner::Builders { builders, .. } => { // Create the value from the builders. Info::from_builders(builders) - .map(Capture(()).fun_once(|_, result, _| result.map_err(StructError::from_field_err))) + .map((), |_, result| result.map_err(StructError::from_field_err)) .cast() } // Use the value as is. @@ -240,7 +258,8 @@ where } } -impl<'ctx, Info, Mode: 'ctx, E: Environment> AsVisitor<'ctx, E> for StructBuilder<'ctx, Info, Mode, E> +impl<'ctx, Info, Mode: 'ctx, E: Environment> AsVisitor<'ctx, E> + for StructBuilder<'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, for<'b, 'c> TypeName::T<'b, 'c, Info::ValueT, E>: IsSync<E::NeedSend>, @@ -282,46 +301,50 @@ where 'ctx: 'this + 'walker, { E::value((self, walker)) - .update(Capture(()).fun_once_hrt::<Mut<_>, _>(|_, (this, walker), _| { - // Start with a hint to use the value protocol to directly transfer the - // struct value. - hint_protocol::<ValueProto<Info::ValueT, E>, _>(walker.cast(), *this, ()).cast() - })) - .if_not_finished(|(this, walker)| { - // Next hint that the struct protocol should be used to switch into - // map-like if the walker supports it. - hint_protocol::<TagProto<tags::Struct, E>, _>( - walker.cast(), - *this, - TagHint { kind: TagConst }, - ) - .cast() - }) - .if_skipped(|(this, walker)| { - // If the struct hint didn't work, - // then hint that the map protocol should be used to switch into - // map-like if the walker supports it. - hint_protocol::<TagProto<tags::Map, E>, _>( - walker.cast(), - *this, - TagHint { kind: TagConst }, - ) - .cast() - }) - .if_not_finished(|(this, walker)| { - // Lastly hint to use a sequence to get the field values. - // We hint with the exact number of fields we are expecting. - hint_protocol::<SequenceProto<E>, _>( - walker.cast(), - *this, - SequenceHint { - len: (Info::FIELD_COUNT, Some(Info::FIELD_COUNT)), - }, - ) + .update((), |_, (this, walker)| { + // Start with a hint to use the value protocol to directly transfer the + // struct value. + hint_protocol::<ValueProto<Info::ValueT, E>, _>(walker.cast(), *this, ()).cast() + }) + .cast::<()>() + .if_not_finished((), |_, (this, walker)| { + // Next hint that the struct protocol should be used to switch into + // map-like if the walker supports it. + hint_protocol::<TagProto<tags::Struct, E>, _>( + walker.cast(), + *this, + TagHint { kind: TagConst }, + ) + .cast() + }) + .cast::<()>() + .if_skipped((), |_, (this, walker)| { + // If the struct hint didn't work, + // then hint that the map protocol should be used to switch into + // map-like if the walker supports it. + hint_protocol::<TagProto<tags::Map, E>, _>( + walker.cast(), + *this, + TagHint { kind: TagConst }, + ) + .cast() + }) + .cast::<()>() + .if_not_finished((), |_, (this, walker)| { + // Lastly hint to use a sequence to get the field values. + // We hint with the exact number of fields we are expecting. + hint_protocol::<SequenceProto<E>, _>( + walker.cast(), + *this, + SequenceHint { + len: (Info::FIELD_COUNT, Some(Info::FIELD_COUNT)), + }, + ) + .cast() + }) + .cast::<()>() + .map((), |_, (_, x)| x) .cast() - }) - .map(Capture(()).fun_once(|_, (_, x), _| x)) - .cast() } } @@ -365,17 +388,17 @@ where ) -> NativeForm<'e, VisitResult, E> { // If this protocol is used then we need to create the builders. E::value(self) - .update(Capture(()).fun_once_hrt::<Mut<_>, _>(|_, this, _| this.make_builders().cast())) - .then(Capture(walker).fun_once(|walker, (this, _), _| { - if let Inner::Builders { kind, .. } = &mut this.inner { - // This signals to go into map mode for the sequence. - *kind = StructKind::Map; - } + .update((), |_, this| this.make_builders().cast()) + .then(walker, |walker, (this, _)| { + if let Inner::Builders { kind, .. } = &mut this.inner { + // This signals to go into map mode for the sequence. + *kind = StructKind::Map; + } - // Walk the walker so nothing complains. - NoopVisitor::walk_dyn(walker) - })) - .cast() + // Walk the walker so nothing complains. + NoopVisitor::walk_dyn(walker) + }) + .cast() } } @@ -393,16 +416,18 @@ where walker: DynWalkerObjSafe<'walker, 'ctx, E>, ) -> NativeForm<'e, VisitResult, E> { // If this protocol is used then we need to create the builders. - E::value(self).update(Capture(()).fun_once_hrt::<Mut<_>, _>(|_, this, _| this.make_builders().cast())).then(Capture(walker).fun_once(|walker, (this, _), _| { - if let Inner::Builders { kind, .. } = &mut this.inner { - // This signals to go into map mode for the sequence. - *kind = StructKind::Map; - } + E::value(self) + .update((), |_, this| this.make_builders().cast()) + .then(walker, |walker, (this, _)| { + if let Inner::Builders { kind, .. } = &mut this.inner { + // This signals to go into map mode for the sequence. + *kind = StructKind::Map; + } - // Walk the walker so nothing complains. - NoopVisitor::walk_dyn(walker) - })) - .cast() + // Walk the walker so nothing complains. + NoopVisitor::walk_dyn(walker) + }) + .cast() } } @@ -426,8 +451,8 @@ where { // If this protocol is used then we need to create the builders. E::value(self) - .update(Capture(()).fun_once_hrt::<Mut<_>, _>(|_, this, _| this.make_builders().cast())) - .update(Capture(()).fun_once_hrt::<Mut<_>, _>(|_, (this, _), _| { + .update((), |_, this| this.make_builders().cast()) + .update(scope, |scope, (this, _)| { match &mut this.inner { // We should treat the sequence as just values. Inner::Builders { @@ -435,22 +460,28 @@ where kind: StructKind::Tuple, } => { // Tuple-like is based on the index of the field. - let mut index = 0; + let index = 0; // Loop through all the fields getting a value for each one. - E::repeat_map((scope, builders), move |(scope, builders)| { - // Get the marker for the field at this index. - let marker = tri!(Info::marker_from_index(index)); - - // Move to the next field for the next iteration. - index += 1; - - // Select the visitor for this field. - let visitor = Info::as_visitor(marker, builders); - - // Visit the next item in the sequence. - scope.next(visitor).map(Flow::to_control_flow).cast() - }) + E::value((scope, builders)) + .repeat(index, |index, (scope, builders)| { + // Get the marker for the field at this index. + let marker = tri!(Info::marker_from_index(*index)); + + // Move to the next field for the next iteration. + *index += 1; + + // Select the visitor for this field. + let visitor = Info::as_visitor(marker, builders); + + // Visit the next item in the sequence. + scope + .next(visitor) + .map((), |_, x| Flow::to_control_flow(x)) + .cast() + }) + .map((), |_, (_, _, x)| x) + .cast::<()>() } // We should treat the sequence as key value pairs. Inner::Builders { @@ -466,24 +497,27 @@ where // Loop through all the elements in the sequence. // Each key value pair will be mapped to a field. - E::repeat_map((visitor, scope), |(visitor, scope)| { - // Visit the next element of the sequence. - // When there are no more items in the sequence then the loop ends. - scope - .next(DynVisitor(visitor)) - .map(Flow::to_control_flow) - .cast() - }) + E::value((visitor, scope)) + .repeat((), |_, (visitor, scope)| { + // Visit the next element of the sequence. + // When there are no more items in the sequence then the loop ends. + scope + .next(DynVisitor(visitor)) + .map((), |_, x| Flow::to_control_flow(x)) + .cast() + }) + .map((), |_, (_, _, x)| x) + .cast() } // If we don't have the builders ... we can't do anything. // This would only happen if the walker gives the value directly // then gives a sequence. _ => E::value(Flow::Done).cast(), } - .map(Into::into) + .map((), |_, x| Into::into(x)) .cast() - })) - .map(Capture(()).fun_once(|_, (_, x), _| x)) + }) + .map((), |_, (_, x)| x) .cast() } } @@ -494,15 +528,19 @@ struct FieldVisitor<'a, 'ctx, I: StructTypeInfo<'ctx, M, E>, M, E: Environment> _marker: Marker<E>, } -unsafe impl<'a, 'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> for FieldVisitor<'a, 'ctx, Info, Mode, E> +unsafe impl<'a, 'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> + for FieldVisitor<'a, 'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, -{} +{ +} -unsafe impl<'a, 'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> for FieldVisitor<'a, 'ctx, Info, Mode, E> +unsafe impl<'a, 'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> + for FieldVisitor<'a, 'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, -{} +{ +} any_trait! { impl['ctx, 'a, I, M][E] FieldVisitor<'a, 'ctx, I, M, E> = [ @@ -537,12 +575,15 @@ where _marker: Default::default(), }; - E::ready((self, visitor, walker)) - .as_ctx(|(_, visitor, walker)| walker.walk(DynVisitor(visitor)).cast()) - .map(|((this, visitor, _), flow)| { + E::value((self, visitor, walker)) + .update((), |_, (_, visitor, walker)| { + walker.walk(DynVisitor(visitor)).cast() + }) + .map((), |_, ((this, visitor, _), flow)| { this.marker = visitor.field_marker; flow.to_continue().into() }) + .cast() } } @@ -551,15 +592,19 @@ struct NameVisitor<'ctx, I: StructTypeInfo<'ctx, M, E>, M, E: Environment> { _marker: Marker<E>, } -unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> for NameVisitor<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSend<E::NeedSend> + for NameVisitor<'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, -{} +{ +} -unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> for NameVisitor<'ctx, Info, Mode, E> +unsafe impl<'ctx, Info, Mode, E: Environment> IsSync<E::NeedSync> + for NameVisitor<'ctx, Info, Mode, E> where Info: StructTypeInfo<'ctx, Mode, E>, -{} +{ +} any_trait! { impl['ctx, I, M][E] NameVisitor<'ctx, I, M, E> = [ @@ -586,7 +631,7 @@ where { self.field_marker = I::marker_from_index(index); - E::ready(VisitResult::Control(Flow::Done)) + E::value(VisitResult::Control(Flow::Done)).cast() } } @@ -605,7 +650,7 @@ where { self.field_marker = I::marker_from_name(name); - E::ready(VisitResult::Control(Flow::Done)) + E::value(VisitResult::Control(Flow::Done)).cast() } } @@ -624,6 +669,6 @@ where { self.field_marker = I::marker_from_name(name); - E::ready(VisitResult::Control(Flow::Done)) + E::value(VisitResult::Control(Flow::Done)).cast() } } diff --git a/src/build/builders/core/value.rs b/src/build/builders/core/value.rs index ccca07e..cd25bdc 100644 --- a/src/build/builders/core/value.rs +++ b/src/build/builders/core/value.rs @@ -1,6 +1,12 @@ use core::fmt::Display; -use effectful::{bound::IsSync, closure::Capture, effective::Effective, environment::{DynBind, Environment, NativeForm}, forward_send_sync, higher_ranked::Mut}; +use effectful::{ + bound::IsSync, + effective::Effective, + environment::{DynBind, Environment, NativeForm}, + forward_send_sync, + higher_ranked::Mut, +}; use crate::{ any::{ @@ -54,9 +60,9 @@ pub struct ValueBuilder<T, Clone, E> { forward_send_sync!({T} {} {Clone, E} ValueBuilder<T, Clone, E>); -impl<T, Clone, E: Environment> crate::BuilderTypes<E> for ValueBuilder<T, Clone, E> +impl<T, Clone, E: Environment> crate::BuilderTypes<E> for ValueBuilder<T, Clone, E> where - T: DynBind<E> + T: DynBind<E>, { type Error = ValueError<T>; @@ -68,7 +74,7 @@ where impl<'ctx, T: 'static, Clone, E: Environment> crate::Builder<'ctx, E> for ValueBuilder<T, Clone, E> where Self: AnyTrait<'ctx, E>, - T: DynBind<E> + T: DynBind<E>, { fn build<'a>(self) -> NativeForm<'a, Result<Self::Value, Self::Error>, E> where @@ -84,7 +90,8 @@ where E::value(Self { value: None, _marker: Default::default(), - }).cast() + }) + .cast() } } @@ -122,9 +129,9 @@ any_trait! { T: DynBind<E> + IsSync<E::NeedSend> + 'static + Clone, } -impl<'ctx, T: 'static, E: Environment> RequestHint<'ctx, E> for ValueBuilder<T, NotCloneable, E> +impl<'ctx, T: 'static, E: Environment> RequestHint<'ctx, E> for ValueBuilder<T, NotCloneable, E> where - T: DynBind<E> + IsSync<E::NeedSend> + T: DynBind<E> + IsSync<E::NeedSend>, { fn request_hint<'this: 'e, 'walker: 'e, 'e>( &'this mut self, @@ -133,9 +140,11 @@ where where 'ctx: 'this + 'walker, { - E::with(Capture((self, walker)).lending_fun_mut(|(this, walker), _| { + E::with((self, walker), |(this, walker)| { hint_protocol::<ValueProto<OwnedStatic<T>, E>, _>(walker.cast(), *this, ()).cast() - })).cast() + }) + .map((), |_, (_, x)| x) + .cast() } } @@ -151,33 +160,46 @@ where 'ctx: 'this + 'walker, { E::value((self, walker)) - .update(Capture(()).fun_once_hrt::<Mut<_>, _>(|_, (this, walker), _| { - hint_protocol::<ValueProto<OwnedStatic<T>, E>, _>(walker.cast(), *this, ()).cast() - })) - .if_not_finished(|(this, walker)| { - hint_protocol::<ValueProto<BorrowedStaticHrt<T>, E>, _>(walker.cast(), *this, ()).cast() - }) - .if_not_finished(|(this, walker)| { - hint_protocol::<ValueProto<TempBorrowedStaticHrt<T>, E>, _>(walker.cast(), *this, ()) - .cast() - }) - .if_not_finished(|(this, walker)| { - hint_protocol::<ValueProto<BorrowedMutStaticHrt<T>, E>, _>(walker.cast(), *this, ()) + .update((), |_, (this, walker)| { + hint_protocol::<ValueProto<OwnedStatic<T>, E>, _>(walker.cast(), *this, ()).cast() + }) + .cast::<()>() + .if_not_finished((), |_, (this, walker)| { + hint_protocol::<ValueProto<BorrowedStaticHrt<T>, E>, _>(walker.cast(), *this, ()) + .cast() + }) + .cast::<()>() + .if_not_finished((), |_, (this, walker)| { + hint_protocol::<ValueProto<TempBorrowedStaticHrt<T>, E>, _>( + walker.cast(), + *this, + (), + ) .cast() - }) - .if_not_finished(|(this, walker)| { - hint_protocol::<ValueProto<TempBorrowedMutStaticHrt<T>, E>, _>(walker.cast(), *this, ()) + }) + .cast::<()>() + .if_not_finished((), |_, (this, walker)| { + hint_protocol::<ValueProto<BorrowedMutStaticHrt<T>, E>, _>(walker.cast(), *this, ()) + .cast() + }) + .cast::<()>() + .if_not_finished((), |_, (this, walker)| { + hint_protocol::<ValueProto<TempBorrowedMutStaticHrt<T>, E>, _>( + walker.cast(), + *this, + (), + ) .cast() - }) - .map(Capture(()).fun_once(|_, (_, x), _| x)) - .cast() + }) + .map((), |_, (_, x)| x) + .cast() } } impl<'ctx, T: 'static, Clone, E: Environment> Value<'ctx, OwnedStatic<T>, E> for ValueBuilder<T, Clone, E> where - T: DynBind<E> + T: DynBind<E>, { fn visit<'a>( &'a mut self, diff --git a/src/effect/bound.rs b/src/effect/bound.rs new file mode 100644 index 0000000..3798823 --- /dev/null +++ b/src/effect/bound.rs @@ -0,0 +1,44 @@ +use crate::never::Never; + +pub trait Bool: Sized + sealed_bool::Sealed + 'static {} + +mod sealed_bool { + use super::*; + + pub trait Sealed {} + + impl Sealed for Yes {} + impl Sealed for No {} +} + +pub enum Yes {} +pub enum No {} + +impl Bool for Yes {} +impl Bool for No {} + +pub unsafe trait IsSend<B: Bool> {} +pub unsafe trait IsSync<B: Bool> {} + +pub struct DynamicShim<T>(pub T); + +unsafe impl<T: IsSend<Yes>> Send for DynamicShim<T> {} +unsafe impl<T: IsSync<Yes>> Sync for DynamicShim<T> {} + +pub struct Dynamic<T>(pub T); + +unsafe impl<T> IsSend<No> for Dynamic<T> {} +unsafe impl<T: Send> IsSend<Yes> for Dynamic<T> {} +unsafe impl<T> IsSync<No> for Dynamic<T> {} +unsafe impl<T: Sync> IsSync<Yes> for Dynamic<T> {} + +pub struct SendAndSync<T>(pub T); + +unsafe impl<T: Send, F: Bool> IsSend<F> for SendAndSync<T> {} +unsafe impl<T: Sync, F: Bool> IsSync<F> for SendAndSync<T> {} + +unsafe impl<F: Bool> IsSend<F> for Never {} +unsafe impl<F: Bool> IsSync<F> for Never {} + +unsafe impl<F: Bool> IsSend<F> for () {} +unsafe impl<F: Bool> IsSync<F> for () {} diff --git a/src/effect/closure.rs b/src/effect/closure.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/effect/closure.rs @@ -85,6 +85,15 @@ pub enum Flow { Done, } +impl ConvertShort<Flow> for Option<effectful::Never> { + fn convert_short(short: Self) -> Flow { + match short { + None => Flow::Done, + Some(_) => unreachable!(), + } + } +} + impl Flow { pub fn to_status(self) -> Status { match self { @@ -124,7 +133,7 @@ macro_rules! Walk { ),* $(,)?} } => { const _: () = { - impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Walk<'ctx, M, E> for &'ctx $name + impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Walk<'ctx, M, E> for &'ctx $name where $name: effectful::bound::IsSync<E::NeedSend> + effectful::environment::DynBind<E> { @@ -159,7 +168,7 @@ macro_rules! Walk { } } - impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::walkers::core::r#struct::StructTypeInfo<'ctx, M, E> for Info + impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::walkers::core::r#struct::StructTypeInfo<'ctx, M, E> for Info where $name: effectful::bound::IsSync<E::NeedSend> + effectful::environment::DynBind<E> { @@ -257,45 +266,45 @@ macro_rules! Walk { // } // } -pub mod demo { - use crate::{Build, BuildExt as _}; - use crate::{Walk, WalkExt as _}; - use macro_rules_attribute::derive; - - #[derive(Walk!)] - pub struct X { - pub a: bool, - pub b: bool, - } - - #[derive(Build!, PartialEq, Debug)] - pub struct Y { - pub b: bool, - pub a: bool, - } - - #[inline(never)] - pub fn ident(x: X) -> Y { - Y::build(x.as_walker()).unwrap() - // x.walk(Y::new_builder()).unwrap() - } - - #[test] - fn demo() { - assert_eq!(ident(X { a: true, b: false }), Y { a: true, b: false }); - - crate::effect::blocking::Spin::block_on(async { - let x = X { a: false, b: true }; - - let y = Y::build_async(x.as_async_walker().await).await.unwrap(); - - assert_eq!(y, Y { a: false, b: true }); - }); - - let x = X { a: false, b: true }; - - let y = Y::build(x.as_walker()).unwrap(); - - assert_eq!(y, Y { a: false, b: true }); - } -} +// pub mod demo { +// use crate::{Build, BuildExt as _}; +// use crate::{Walk, WalkExt as _}; +// use macro_rules_attribute::derive; +// +// #[derive(Walk!)] +// pub struct X { +// pub a: bool, +// pub b: bool, +// } +// +// #[derive(Build!, PartialEq, Debug)] +// pub struct Y { +// pub b: bool, +// pub a: bool, +// } +// +// #[inline(never)] +// pub fn ident(x: X) -> Y { +// Y::build(x.as_walker()).unwrap() +// // x.walk(Y::new_builder()).unwrap() +// } +// +// #[test] +// fn demo() { +// assert_eq!(ident(X { a: true, b: false }), Y { a: true, b: false }); +// +// crate::effect::blocking::Spin::block_on(async { +// let x = X { a: false, b: true }; +// +// let y = Y::build_async(x.as_async_walker().await).await.unwrap(); +// +// assert_eq!(y, Y { a: false, b: true }); +// }); +// +// let x = X { a: false, b: true }; +// +// let y = Y::build(x.as_walker()).unwrap(); +// +// assert_eq!(y, Y { a: false, b: true }); +// } +// } diff --git a/src/macros/build.rs b/src/macros/build.rs index 2f7e228..f56ece9 100644 --- a/src/macros/build.rs +++ b/src/macros/build.rs @@ -9,7 +9,7 @@ macro_rules! Build { #[allow(non_upper_case_globals, non_snake_case, non_camel_case_types)] const _: () = { // add a module here to seal fields. - impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Build<'ctx, M, E> for $name + impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Build<'ctx, M, E> for $name where $name: effectful::environment::DynBind<E> + effectful::bound::IsSync<E::NeedSend> { @@ -71,7 +71,7 @@ macro_rules! Build { $vis struct __Info; - impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::builders::core::r#struct::StructTypeInfo<'ctx, M, E> for __Info + impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::builders::core::r#struct::StructTypeInfo<'ctx, M, E> for __Info where $name: effectful::environment::DynBind<E> { @@ -158,21 +158,27 @@ macro_rules! Build { #[allow(non_upper_case_globals, non_snake_case, non_camel_case_types)] const _: () = { // add a module here to seal fields. - impl<'ctx, M: 'ctx, E: $crate::effect::Effect> $crate::Build<'ctx, M, E> for $name { + impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::Build<'ctx, M, E> for $name { type Builder = $crate::builders::core::r#enum::EnumBuilder<'ctx, __Info, M, E>; } $vis struct __Info; - $vis enum __Builders<'ctx, M, E: Effect> { + $vis enum __Builders<'ctx, M, E: effectful::environment::Environment> { $($variant(<$value as $crate::Build<'ctx, M, E>>::Builder)),* } + unsafe impl<'ctx, M: 'ctx, E: effectful::environment::Environment> effectful::bound::IsSend<E::NeedSend> for __Builders<'ctx, M, E> {} + unsafe impl<'ctx, M: 'ctx, E: effectful::environment::Environment> effectful::bound::IsSync<E::NeedSync> for __Builders<'ctx, M, E> {} + #[derive(Copy, Clone)] $vis enum __Marker { $($variant),* } + unsafe impl<'ctx, F: effectful::bound::Bool> effectful::bound::IsSend<F> for __Marker {} + unsafe impl<'ctx, F: effectful::bound::Bool> effectful::bound::IsSync<F> for __Marker {} + impl ::core::fmt::Display for __Marker { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { f.write_str(match self { @@ -189,18 +195,24 @@ macro_rules! Build { $(pub const $variant: u32 = __Variants::$variant as u32;)* } - $vis struct __ErrorBuilder<'ctx, M, E: Effect> { - $($variant: Option<<<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes>::Error>),* + $vis struct __ErrorBuilder<'ctx, M, E: Environment> { + $($variant: Option<<<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes<E>>::Error>),* } - $vis enum __Error<'ctx, M, E: Effect> { + unsafe impl<'ctx, M: 'ctx, E: effectful::environment::Environment> effectful::bound::IsSend<E::NeedSend> for __ErrorBuilder<'ctx, M, E> {} + unsafe impl<'ctx, M: 'ctx, E: effectful::environment::Environment> effectful::bound::IsSync<E::NeedSync> for __ErrorBuilder<'ctx, M, E> {} + + $vis enum __Error<'ctx, M, E: Environment> { __Guess { - $($variant: <<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes>::Error),* + $($variant: <<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes<E>>::Error),* }, - $($variant(<<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes>::Error)),* + $($variant(<<$value as $crate::Build<'ctx, M, E>>::Builder as BuilderTypes<E>>::Error)),* } - impl<'ctx, M, E: Effect> ::core::fmt::Display for __Error<'ctx, M, E> { + unsafe impl<'ctx, M: 'ctx, E: effectful::environment::Environment> effectful::bound::IsSend<E::NeedSend> for __Error<'ctx, M, E> {} + unsafe impl<'ctx, M: 'ctx, E: effectful::environment::Environment> effectful::bound::IsSync<E::NeedSync> for __Error<'ctx, M, E> {} + + impl<'ctx, M, E: Environment> ::core::fmt::Display for __Error<'ctx, M, E> { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { match self { Self::__Guess { @@ -215,7 +227,7 @@ macro_rules! Build { } } - impl<'ctx, M, E: Effect> ::core::fmt::Debug for __Error<'ctx, M, E> { + impl<'ctx, M, E: Environment> ::core::fmt::Debug for __Error<'ctx, M, E> { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { match self { Self::__Guess { @@ -230,7 +242,7 @@ macro_rules! Build { } } - impl<'ctx, M: 'ctx, E: $crate::effect::Effect> $crate::builders::core::r#enum::EnumBuildInfo<'ctx, M, E> for __Info { + impl<'ctx, M: 'ctx, E: effectful::environment::Environment> $crate::builders::core::r#enum::EnumBuildInfo<'ctx, M, E> for __Info { type Builders = __Builders<'ctx, M, E>; type Seed = (); @@ -246,27 +258,27 @@ macro_rules! Build { fn new_builder<'a>( seed: Self::Seed, variant: Self::VariantMarker, - ) -> ErasedEffective<'a, Self::Builders, E> { + ) -> NativeForm<'a, Self::Builders, E> { match variant { $(__Marker::$variant => { - Builder::<E>::from_seed(Default::default()).map(|builder| __Builders::$variant(builder)) + Builder::<E>::from_seed(Default::default()).map((), |_, builder| __Builders::$variant(builder)).cast() })* } } fn finish_builder<'a>( builder: Self::Builders, - ) -> ErasedEffective<'a, Result<Self::T, Self::Error>, E> { + ) -> NativeForm<'a, Result<Self::T, Self::Error>, E> { match builder { - $(__Builders::$variant(builder) => builder.build().map(|value| value.map($name::$variant).map_err(__Error::$variant))),* + $(__Builders::$variant(builder) => builder.build().map((), |_, value| value.map($name::$variant).map_err(__Error::$variant)).cast()),* } } - fn from_value<'a>(value: TypeName::T<'a, 'ctx, Self::ValueT>) -> Self::T { + fn from_value<'a>(value: TypeName::T<'a, 'ctx, Self::ValueT, E>) -> Self::T { value.0 } - fn as_visitor<'a>(builder: &'a mut Self::Builders) -> DynVisitor<'a, 'ctx> { + fn as_visitor<'a>(builder: &'a mut Self::Builders) -> DynVisitor<'a, 'ctx, E> { match builder { $(__Builders::$variant(builder) => builder.as_visitor()),* } @@ -289,16 +301,19 @@ macro_rules! Build { fn guess_variant<'a>( seed: Self::Seed, scope: DynRecoverableScope<'a, 'ctx, E>, - ) -> ErasedEffective<'a, Result<Self::T, Self::Error>, E> { - E::ready((scope, Err(__ErrorBuilder::<M, E> { A: None, B: None }))) - $(.or_else_update(|scope, result| { + ) -> NativeForm<'a, Result<Self::T, Self::Error>, E> { + use effectful::effective::EffectiveExt; + use effectful::short::ResultErrorExt; + + E::value((scope, Err(__ErrorBuilder::<M, E> { A: None, B: None }))) + $(.or_else_update((), |_, scope, result| { let mut error = result.into_error(); <<$value as Build<M, E>>::Builder as Builder<_>>::from_seed(Default::default()) - .map(|builder| (scope, builder)) - .as_ctx(|(scope, builder)| scope.new_walk(builder.as_visitor()).cast()) - .then(|((_, builder), _)| builder.build()) - .map(|result| { + .map(scope, |scope, builder| (scope, builder)) + .update((), |(), (scope, builder)| scope.new_walk(builder.as_visitor()).cast()) + .then((), |(), ((_, builder), _)| builder.build()) + .map(error, |mut error, result| { result.map(X::$variant).map_err(|err| { error.$variant = Some(err); error @@ -306,12 +321,12 @@ macro_rules! Build { }) .cast() }))* - .map(|(_, result)| match result { + .map((), |_, (_, result)| match result { Ok(value) => Ok(value), Err(err) => Err(__Error::__Guess { $($variant: err.$variant.unwrap()),* }), - }) + }).cast() } } }; diff --git a/src/protocol.rs b/src/protocol.rs index 5889605..6293e3d 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -57,12 +57,19 @@ pub mod walker; use core::ops::{Deref, DerefMut}; -use effectful::{bound::{IsSend, IsSync}, environment::Environment}; +use effectful::{ + bound::{IsSend, IsSync}, + environment::Environment, +}; use crate::any::AnyTrait; pub struct DynVisitor<'a, 'ctx, Env: Environment>(pub &'a mut (dyn AnyTrait<'ctx, Env> + 'a)); +unsafe impl<'a, 'ctx, E: Environment> IsSend<E::NeedSend> for DynVisitor<'a, 'ctx, E> {} + +unsafe impl<'a, 'ctx, E: Environment> IsSync<E::NeedSync> for DynVisitor<'a, 'ctx, E> {} + impl<'a, 'ctx, Env: Environment> DynVisitor<'a, 'ctx, Env> { pub fn cast<'b>(&'b mut self) -> DynVisitor<'b, 'ctx, Env> { DynVisitor(&mut *self.0) diff --git a/src/protocol/visitor.rs b/src/protocol/visitor.rs index 0189dc1..5916235 100644 --- a/src/protocol/visitor.rs +++ b/src/protocol/visitor.rs @@ -1,9 +1,6 @@ use core::ops::ControlFlow; -use crate::{ - never::Never, - Flow, Status, -}; +use crate::{never::Never, Flow, Status}; mod recoverable; mod request_hint; @@ -11,7 +8,13 @@ mod sequence; mod tag; mod value; -use effectful::{effective::Effective, environment::{DynBind, NativeForm}, forward_send_sync}; +use effectful::{ + bound::HasSendAndSync, + effective::{Effective, SplitUpdateEffective}, + environment::{DynBind, Environment, NativeForm}, + for_lt, forward_send_sync, + higher_ranked::Mut, +}; pub use recoverable::*; pub use request_hint::*; pub use sequence::*; @@ -94,71 +97,83 @@ impl<S> VisitResult<S> { } pub trait EffectiveVisitExt<'lt>: Effective<'lt> { - fn if_skipped<'ctx, 'wrap, Ctx, F>( + fn if_skipped<'ctx, 'wrap, Cap, Update>( self, - f: F, - ) -> NativeForm<'wrap, (Ctx, VisitResult<()>), Self::Env> + cap: Cap, + f: for<'a> fn(Cap, &'a mut Update) -> NativeForm<'a, VisitResult<()>, Self::Env, &'ctx ()>, + ) -> SplitUpdateEffective< + 'wrap, + 'lt, + (), + ( + Cap, + HasSendAndSync< + for<'a> fn( + Cap, + &'a mut Update, + ) -> NativeForm<'a, VisitResult<()>, Self::Env, &'ctx ()>, + >, + ), + Update, + VisitResult<()>, + VisitResult<()>, + Self, + > where - Ctx: DynBind<Self::Env>, - Self: Effective<'lt, Output = (Ctx, VisitResult<()>)>, - F: 'wrap - + for<'temp> FnOnce( - &'temp mut Ctx, - ) - -> NativeForm<'temp, VisitResult<()>, Self::Env, &'ctx ()>, + Cap: DynBind<Self::Env>, + Update: DynBind<Self::Env>, + Self: Effective<'lt, Output = (Update, VisitResult<()>)>, 'ctx: 'lt, 'lt: 'wrap, { - self.r#do( - |(ctx, v)| { - ( - ctx, - match v { - VisitResult::Skipped(()) => ControlFlow::Continue(()), - v => ControlFlow::Break(v), - }, - ) + self.split_update( + (), + |_, x| x, + (cap, HasSendAndSync(f)), + |(cap, HasSendAndSync(f)), update, value| match value { + VisitResult::Skipped(()) => f(cap, update), + _ => Self::Env::value(value).cast(), }, - |ctx, ()| f(ctx).cast(), - |_, v| ControlFlow::<_, Never>::Break(v), - |_, _| unreachable!(), - |_, _, _: Never| unreachable!(), - |ctx, _, v| (ctx, v), ) } - fn if_not_finished<'ctx, 'wrap, Ctx, F>( + fn if_not_finished<'ctx, 'wrap, Cap, Update>( self, - f: F, - ) -> NativeForm<'wrap, (Ctx, VisitResult<()>), Self::Env> + cap: Cap, + f: for<'a> fn(Cap, &'a mut Update) -> NativeForm<'a, VisitResult<()>, Self::Env, &'ctx ()>, + ) -> SplitUpdateEffective< + 'wrap, + 'lt, + (), + ( + Cap, + HasSendAndSync< + for<'a> fn( + Cap, + &'a mut Update, + ) -> NativeForm<'a, VisitResult<()>, Self::Env, &'ctx ()>, + >, + ), + Update, + VisitResult<()>, + VisitResult<()>, + Self, + > where - Ctx: DynBind<Self::Env>, - Self: Effective<'lt, Output = (Ctx, VisitResult<()>)>, - F: 'wrap - + for<'temp> FnOnce( - &'temp mut Ctx, - ) - -> NativeForm<'temp, VisitResult<()>, Self::Env, &'ctx ()>, + Cap: DynBind<Self::Env>, + Update: DynBind<Self::Env>, + Self: Effective<'lt, Output = (Update, VisitResult<()>)>, 'ctx: 'lt, 'lt: 'wrap, { - self.r#do( - |(ctx, v)| { - ( - ctx, - match v { - VisitResult::Skipped(()) | VisitResult::Control(Flow::Continue) => { - ControlFlow::Continue(()) - } - v => ControlFlow::Break(v), - }, - ) + self.split_update( + (), + |_, x| x, + (cap, HasSendAndSync(f)), + |(cap, HasSendAndSync(f)), update, value| match value { + VisitResult::Skipped(()) | VisitResult::Control(Flow::Continue) => f(cap, update), + _ => Self::Env::value(value).cast(), }, - |ctx, ()| f(ctx).cast(), - |_, v| ControlFlow::<_, Never>::Break(v), - |_, _| unreachable!(), - |_, _, _: Never| unreachable!(), - |ctx, _, v| (ctx, v), ) } } diff --git a/src/protocol/visitor/recoverable.rs b/src/protocol/visitor/recoverable.rs index fe8d82e..4f39e8a 100644 --- a/src/protocol/visitor/recoverable.rs +++ b/src/protocol/visitor/recoverable.rs @@ -1,4 +1,8 @@ -use effectful::{environment::{DynBind, EnvConfig, Environment, NativeForm}, is_send_sync}; +use effectful::{ + effective::Effective, + environment::{DynBind, EnvConfig, Environment, NativeForm}, + is_send_sync, +}; use crate::{ any::TypeName, @@ -43,8 +47,7 @@ pub trait RecoverableScope<'ctx, E: Environment>: DynBind<E> { ) -> NativeForm<'effect, Status, E>; } -pub type DynRecoverableScope<'a, 'ctx, E> = - &'a mut (dyn RecoverableScope<'ctx, E> + 'a); +pub type DynRecoverableScope<'a, 'ctx, E> = &'a mut (dyn RecoverableScope<'ctx, E> + 'a); pub struct RecoverableKnown; @@ -54,7 +57,9 @@ impl<'a, 'ctx, E: EnvConfig> Meta::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> fo type T = RecoverableKnown; } -impl<'a, 'ctx, E: EnvConfig> Meta::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> for RecoverableKnown { +impl<'a, 'ctx, E: EnvConfig> Meta::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> + for RecoverableKnown +{ type Higher = RecoverableKnown; } diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index 5adcf8c..2fd6255 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -1,4 +1,9 @@ -use effectful::{closure::Capture, environment::{DynBind, Environment, NativeForm}}; +use effectful::{ + effective::Effective, + environment::{DynBind, Environment, NativeForm}, + for_lt, + higher_ranked::Mut, +}; use crate::{ any::TypeName, @@ -50,17 +55,21 @@ pub fn request_hint<'ctx: 'visitor + 'walker, 'visitor: 'e, 'walker: 'e, 'e, E: visitor: DynVisitor<'visitor, 'ctx, E>, walker: DynWalker<'walker, 'ctx, E>, ) -> NativeForm<'e, VisitResult<DynWalker<'walker, 'ctx, E>>, E> { - E::value(walker).update(Capture(visitor).fun_once(|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::value(VisitResult::Skipped(())).cast() - } - })) - .map(|((_, walker), result)| result.map_skipped(|_| walker)) + E::value(walker) + .update(visitor, |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::<()>(); + + todo!() + } else { + // If the visitor doesn't support request hint then we continue. + E::value(VisitResult::Skipped(())).cast() + } + }) + .map((), |_, (walker, result)| result.map_skipped(|_| walker)) + .cast() } diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index 971532b..de9666d 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -1,4 +1,8 @@ -use effectful::{environment::{DynBind, EnvConfig, Environment, NativeForm}, is_send_sync}; +use effectful::{ + effective::Effective, + environment::{DynBind, EnvConfig, Environment, NativeForm}, + is_send_sync, +}; use crate::{ any::TypeName, @@ -100,7 +104,7 @@ pub fn visit_sequence<'a, 'ctx, E: Environment>( object.visit(scope) } else { // If the visitor doesn't support sequence then we continue. - E::value(VisitResult::Skipped(())) + E::value(VisitResult::Skipped(())).cast() } } diff --git a/src/protocol/visitor/tag.rs b/src/protocol/visitor/tag.rs index 7859f09..0473f5a 100644 --- a/src/protocol/visitor/tag.rs +++ b/src/protocol/visitor/tag.rs @@ -1,6 +1,13 @@ use core::any::TypeId; -use effectful::{bound::{Bool, IsSend, IsSync}, environment::{DynBind, EnvConfig, Environment, NativeForm}, forward_send_sync, is_send_sync, tri}; +use effectful::{ + bound::{Bool, IsSend, IsSync}, + effective::{Effective, EffectiveExt}, + environment::{DynBind, EnvConfig, Environment, NativeForm}, + for_lt, forward_send_sync, + higher_ranked::Mut, + is_send_sync, tri, +}; use crate::{ any::TypeName, @@ -69,7 +76,8 @@ pub trait Tag<'ctx, K: TagKind<E>, E: Environment>: DynBind<E> { pub struct TagProto<K: TagKind<E>, E: Environment>(Marker<(K, E)>); -impl<'a, 'ctx, K: TagKind<E>, E> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> for TagProto<K, E> +impl<'a, 'ctx, K: TagKind<E>, E> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + for TagProto<K, E> where E: Environment, { @@ -104,14 +112,14 @@ pub struct TagHint<K> { forward_send_sync!({K} {} {} TagHint<K>); -impl<'a, 'ctx, E: EnvConfig, K: DynBind<E> + 'static> Meta::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> - for TagHint<K> +impl<'a, 'ctx, E: EnvConfig, K: DynBind<E> + 'static> + Meta::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> for TagHint<K> { type T = TagHint<K>; } -impl<'a, 'ctx, E: EnvConfig, K: DynBind<E> + 'static> Meta::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> - for TagHint<K> +impl<'a, 'ctx, E: EnvConfig, K: DynBind<E> + 'static> + Meta::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> for TagHint<K> { type Higher = TagHint<K>; } @@ -193,27 +201,27 @@ pub fn visit_tag< let walker = DynWalkerAdapter::new(walker); // Give everything to the effective chain to be used as context. - E::ready((kind, visitor, walker)) - .as_ctx(|(kind, visitor, walker)| { + E::value((kind, visitor, walker)) + .update((), |_, (kind, visitor, walker)| { // Try to visit the tag kind as given. tri!(visitor.upcast_mut::<TagProto<K, E>>()) .visit(*kind, walker) - .map(VisitResult::to_flow) + .map((), |_, x| VisitResult::to_flow(x)) .cast() }) - .as_ctx_or_else(|(kind, visitor, walker)| { + .or_else_update((), |_, (kind, visitor, walker), _| { // If the tag type is already dynamic we don't need to try visiting again. if TypeId::of::<K>() == TypeId::of::<TagDyn>() { - return None.ready(); + return E::value(None).cast(); } // Visit using the dynamic tag, but with the same symbol. tri!(visitor.upcast_mut::<TagProto<TagDyn, E>>()) .visit(TagDyn(kind.symbol()), walker) - .map(VisitResult::to_flow) + .map((), |_, x| VisitResult::to_flow(x)) .cast() }) - .map(|((kind, _, walker), result)| match result { + .map((), |_, ((kind, _, walker), result)| match result { // The visit was performed so return the control flow. Some(flow) => Ok(VisitResult::Control(flow)), @@ -224,6 +232,7 @@ pub fn visit_tag< Err(err) => Err(map_walker_err(kind, err)), }, }) + .cast() } fn map_walker_err<'ctx, K: TagKind<E>, W: Walker<'ctx, E>, E: Environment>( @@ -238,4 +247,7 @@ fn map_walker_err<'ctx, K: TagKind<E>, W: Walker<'ctx, E>, E: Environment>( } } -impl<'ctx, T, K: TagKind<E>, E: Environment> HasProtocol<TagProto<K, E>> for T where T: Tag<'ctx, K, E> {} +impl<'ctx, T, K: TagKind<E>, E: Environment> HasProtocol<TagProto<K, E>> for T where + T: Tag<'ctx, K, E> +{ +} diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index f34cdcd..59bf907 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -2,7 +2,11 @@ //! //! In some sense, this is the most basic protocol. -use effectful::{bound::{Bool, IsSend, IsSync}, environment::{DynBind, EnvConfig, Environment, NativeForm}}; +use effectful::{ + bound::{Bool, IsSend, IsSync}, + effective::Effective, + environment::{DynBind, EnvConfig, Environment, NativeForm}, +}; use crate::{ any::TypeName, @@ -33,13 +37,14 @@ pub trait Value<'ctx, T: ?Sized + TypeName::MemberType<E>, E: Environment>: DynB value: TypeName::T<'a, 'ctx, T, E>, ) -> NativeForm<'a, VisitResult<TypeName::T<'a, 'ctx, T, E>>, E> where - TypeName::T<'a, 'ctx, T, E>: Send + Sync + Sized, + TypeName::T<'a, 'ctx, T, E>: Sized, 'ctx: 'a; } pub struct ValueProto<T: ?Sized + TypeName::MemberType<E>, E: Environment>(Marker<(*const T, E)>); -impl<'a, 'ctx, T: ?Sized, E> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> for ValueProto<T, E> +impl<'a, 'ctx, T: ?Sized, E> TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + for ValueProto<T, E> where E: Environment, T: TypeName::MemberType<E>, @@ -70,7 +75,8 @@ unsafe impl<'a, T: ?Sized + IsSync<F>, F: Bool> IsSync<F> for ValueKnown<'a, T> #[derive(Copy, Clone, Debug)] pub struct ValueKnownHrt<T: ?Sized>(Marker<T>); -impl<'a, 'ctx, E: EnvConfig, T> Meta::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> for ValueKnownHrt<T> +impl<'a, 'ctx, E: EnvConfig, T> Meta::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + for ValueKnownHrt<T> where T: ?Sized + TypeName::MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()>, TypeName::T<'a, 'ctx, T, E>: IsSync<E::NeedSend>, @@ -78,7 +84,8 @@ where type T = ValueKnown<'a, TypeName::T<'a, 'ctx, T, E>>; } -impl<'a, 'ctx, E: EnvConfig, T: ?Sized> Meta::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> for ValueKnown<'a, T> +impl<'a, 'ctx, E: EnvConfig, T: ?Sized> Meta::LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> + for ValueKnown<'a, T> where T: TypeName::LowerType<'a, 'ctx, E>, T: IsSync<E::NeedSend>, @@ -87,7 +94,7 @@ where } // This enrolls the Value protocol into the walker hint system. -impl<T: TypeName::MemberType<E>, E: Environment> HintMeta for ValueProto<T, E> +impl<T: TypeName::MemberType<E>, E: Environment> HintMeta for ValueProto<T, E> where for<'a, 'ctx> TypeName::T<'a, 'ctx, T, E>: IsSync<E::NeedSend>, { @@ -102,12 +109,15 @@ pub fn visit_value< 'ctx: 'visitor, 'visitor: 'e, 'e, - T: Send + Sync + TypeName::LowerType<'e, 'ctx, E>, + T: TypeName::LowerType<'e, 'ctx, E>, E: Environment, >( visitor: DynVisitor<'visitor, 'ctx, E>, value: T, -) -> NativeForm<'e, VisitResult<T>, E> { +) -> NativeForm<'e, VisitResult<T>, E> +where + TypeName::HigherRanked<'e, 'ctx, T, E>: TypeName::MemberType<E>, +{ if let Some(object) = visitor .0 .upcast_mut::<ValueProto<TypeName::HigherRanked<'e, 'ctx, T, E>, E>>() diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index 50cd71d..2084b5b 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -6,7 +6,12 @@ use core::ops::{Deref, DerefMut}; -use effectful::environment::{DynBind, EnvConfig, Environment, NativeForm}; +use effectful::{ + bound::{IsSend, IsSync}, + effective::Effective, + environment::{DynBind, EnvConfig, Environment, NativeForm}, + higher_ranked::Mut, +}; use crate::{ any::{AnyTrait, TypeName}, @@ -23,15 +28,24 @@ pub mod Meta { type T: ?Sized + LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx (), Higher = Self>; } - pub trait MemberType<E: EnvConfig>: for<'a, 'ctx> MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> {} + pub trait MemberType<E: EnvConfig>: + for<'a, 'ctx> MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + { + } - impl<T: ?Sized, E: EnvConfig> MemberType<E> for T where T: for<'a, 'ctx> MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> {} + impl<T: ?Sized, E: EnvConfig> MemberType<E> for T where + T: for<'a, 'ctx> MemberTypeForLt<'a, 'ctx, E, &'a &'ctx ()> + { + } pub trait LowerTypeWithBound<'a, 'ctx: 'a, E: EnvConfig, B>: 'a + DynBind<E> + Sized { type Higher: ?Sized + MemberTypeForLt<'a, 'ctx, E, &'a &'ctx (), T = Self>; } - pub trait LowerType<'a, 'ctx: 'a, E: EnvConfig>: LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> {} + pub trait LowerType<'a, 'ctx: 'a, E: EnvConfig>: + LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> + { + } impl<'a, 'ctx: 'a, E: EnvConfig, T: ?Sized> LowerType<'a, 'ctx, E> for T where T: LowerTypeWithBound<'a, 'ctx, E, &'a &'ctx ()> @@ -67,8 +81,10 @@ pub trait HintMeta: TypeName::MemberType<Self::Effect> + 'static { type Effect: Environment; } -pub type MetaKnown<'a, 'ctx, Protocol> = Meta::T<'a, 'ctx, <Protocol as HintMeta>::Known, <Protocol as HintMeta>::Effect>; -pub type MetaHint<'a, 'ctx, Protocol> = Meta::T<'a, 'ctx, <Protocol as HintMeta>::Hint, <Protocol as HintMeta>::Effect>; +pub type MetaKnown<'a, 'ctx, Protocol> = + Meta::T<'a, 'ctx, <Protocol as HintMeta>::Known, <Protocol as HintMeta>::Effect>; +pub type MetaHint<'a, 'ctx, Protocol> = + Meta::T<'a, 'ctx, <Protocol as HintMeta>::Hint, <Protocol as HintMeta>::Effect>; /// Object implementing the [`Hint`] protocol. pub trait Hint<'ctx, Protocol: ?Sized + HintMeta>: DynBind<Protocol::Effect> { @@ -95,6 +111,16 @@ pub struct DynVisitorWith<'temp, 'ctx, Protocol: ?Sized + HintMeta> { _marker: Marker<Protocol>, } +unsafe impl<'a, 'ctx, P: HintMeta> IsSend<<P::Effect as EnvConfig>::NeedSend> + for DynVisitorWith<'a, 'ctx, P> +{ +} + +unsafe impl<'a, 'ctx, P: HintMeta> IsSync<<P::Effect as EnvConfig>::NeedSync> + for DynVisitorWith<'a, 'ctx, P> +{ +} + pub trait HasProtocol<Protocol: ?Sized> {} impl<'temp, 'ctx: 'temp, Protocol: ?Sized + HintMeta> DynVisitorWith<'temp, 'ctx, Protocol> { @@ -141,7 +167,8 @@ where type T = dyn Hint<'ctx, Protocol> + 'a; } -impl<'a, 'ctx, Protocol: ?Sized> TypeName::LowerTypeWithBound<'a, 'ctx, Protocol::Effect, &'a &'ctx ()> +impl<'a, 'ctx, Protocol: ?Sized> + TypeName::LowerTypeWithBound<'a, 'ctx, Protocol::Effect, &'a &'ctx ()> for dyn Hint<'ctx, Protocol> + 'a where Protocol: HintMeta, @@ -168,8 +195,9 @@ where if let Some(object) = walker.0.upcast_mut::<HintProto<Protocol>>() { object .hint(DynVisitorWith::new(visitor), hint) - .map(Into::into) + .map((), |_, x| Into::into(x)) + .cast() } else { - VisitResult::Skipped(()).ready() + Protocol::Effect::value(VisitResult::Skipped(())).cast() } } diff --git a/src/transform.rs b/src/transform.rs index 8721845..6930ba1 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -1,24 +1,40 @@ -use effectful::{r#async::Async, block_on::Spin, blocking::Blocking, bound::{Ds, No, Ss, Yes, D}, effective::Effective, environment::{Cfg, Environment, NativeForm}}; +use effectful::{ + block_on::Spin, + blocking::Blocking, + bound::{Ds, No, Ss, Yes, D}, + effective::Effective, + environment::{Cfg, Environment, NativeForm}, + higher_ranked::Mut, + r#async::Async, +}; use futures::Future; -use crate::{ - build::Builder, - Build, BuilderTypes, DefaultMode, Walk, Walker, -}; +use crate::{build::Builder, Build, BuilderTypes, DefaultMode, Walk, Walker}; #[inline(always)] #[allow(clippy::type_complexity)] -pub fn transform<'a, 'ctx: 'a, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Environment>( +pub fn transform< + 'a, + 'ctx: 'a, + B: Builder<'ctx, E> + 'a, + W: Walker<'ctx, E> + 'a, + E: Environment, +>( seed: B::Seed, walker: W, ) -> NativeForm<'a, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> { B::from_seed(seed) - .update(|builder| walker.walk(builder.as_visitor()).cast()) - .then(|(builder, walker_result)| { + .update(walker, |walker, builder| { + walker.walk(builder.as_visitor()).cast() + }) + .then((), |_, (builder, walker_result)| { builder .build() - .map(|builder_result| (builder_result, walker_result)) + .map(walker_result, |walker_result, builder_result| { + (builder_result, walker_result) + }) }) + .cast() // B::from_seed(seed).map_with(walker, |builder, walker| walker.walk(builder.as_visitor())); // E::wrap(async { @@ -59,7 +75,10 @@ pub trait BuildExt { walker: W, ) -> Result< Self, - BuildError<<Self::Builder as BuilderTypes<Blocking<Cfg<Spin, No, No>>>>::Error, <W as Walker<'ctx, Blocking<Cfg<Spin, No, No>>>>::Error>, + BuildError< + <Self::Builder as BuilderTypes<Blocking<Cfg<Spin, No, No>>>>::Error, + <W as Walker<'ctx, Blocking<Cfg<Spin, No, No>>>>::Error, + >, > where Self: Build<'ctx, DefaultMode, Blocking<Cfg<Spin, No, No>>>, @@ -78,7 +97,10 @@ pub trait BuildExt { ) -> impl Future< Output = Result< Self, - BuildError<<Self::Builder as BuilderTypes<Async<Cfg<Spin, Yes, Yes>>>>::Error, <W as Walker<'ctx, Async<Cfg<Spin, Yes, Yes>>>>::Error>, + BuildError< + <Self::Builder as BuilderTypes<Async<Cfg<Spin, Yes, Yes>>>>::Error, + <W as Walker<'ctx, Async<Cfg<Spin, Yes, Yes>>>>::Error, + >, >, > + Send + Sync @@ -113,7 +135,9 @@ pub trait BuildExt { impl<T> BuildExt for T {} pub trait WalkExt { - fn as_walker<'ctx: 'a, 'a>(&'a self) -> <&'a Self as Walk<'ctx, DefaultMode, Blocking<Cfg<Spin, No, No>>>>::Walker + fn as_walker<'ctx: 'a, 'a>( + &'a self, + ) -> <&'a Self as Walk<'ctx, DefaultMode, Blocking<Cfg<Spin, No, No>>>>::Walker where &'a Self: Walk<'ctx, DefaultMode, Blocking<Cfg<Spin, No, No>>>, { @@ -136,7 +160,9 @@ pub trait WalkExt { B: Builder<'ctx, Blocking<Cfg<Spin, No, No>>>, { let mut builder = builder; - let _ = Walk::into_walker(self).into_value().walk(builder.as_visitor()); + let _ = Walk::into_walker(self) + .into_value() + .walk(builder.as_visitor()); match builder.build().into_value() { Ok(value) => Ok(value), _ => todo!(), diff --git a/src/walk.rs b/src/walk.rs index 10f96cd..fa7fcae 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -2,13 +2,15 @@ pub mod walkers; use core::fmt::Debug; -use effectful::{bound::{IsSend, IsSync}, environment::{DynBind, Environment, NativeForm}}; - -use crate::{ - protocol::DynVisitor, - Flow, +use effectful::{ + bound::{IsSend, IsSync}, + effective::Effective, + environment::{DynBind, Environment, NativeForm}, + higher_ranked::Mut, }; +use crate::{protocol::DynVisitor, Flow}; + /// A type that can be walked. pub trait Walk<'ctx, M, E: Environment>: Sized { /// The walker for the type. @@ -82,9 +84,15 @@ pub struct DynWalkerAdapter<'ctx, W: Walker<'ctx, E>, E: Environment> { state: DynWalkerState<'ctx, W, E>, } -unsafe impl<'ctx, W: Walker<'ctx, E>, E: Environment> IsSend<E::NeedSend> for DynWalkerAdapter<'ctx, W, E> {} +unsafe impl<'ctx, W: Walker<'ctx, E>, E: Environment> IsSend<E::NeedSend> + for DynWalkerAdapter<'ctx, W, E> +{ +} -unsafe impl<'ctx, W: Walker<'ctx, E>, E: Environment> IsSync<E::NeedSync> for DynWalkerAdapter<'ctx, W, E> {} +unsafe impl<'ctx, W: Walker<'ctx, E>, E: Environment> IsSync<E::NeedSync> + for DynWalkerAdapter<'ctx, W, E> +{ +} impl<'ctx, W: Walker<'ctx, E>, E: Environment> DynWalkerAdapter<'ctx, W, E> { #[inline(always)] @@ -115,7 +123,9 @@ impl<'ctx, W: Walker<'ctx, E>, E: Environment> DynWalkerAdapter<'ctx, W, E> { } } -impl<'ctx, W: Walker<'ctx, E>, E: Environment> WalkerObjSafe<'ctx, E> for DynWalkerAdapter<'ctx, W, E> { +impl<'ctx, W: Walker<'ctx, E>, E: Environment> WalkerObjSafe<'ctx, E> + for DynWalkerAdapter<'ctx, W, E> +{ #[inline(always)] fn walk<'a: 'c, 'b: 'c, 'c>( &'a mut self, @@ -128,11 +138,11 @@ impl<'ctx, W: Walker<'ctx, E>, E: Environment> WalkerObjSafe<'ctx, E> for DynWal core::mem::replace(&mut self.state, DynWalkerState::Walking) { E::value((self, visitor)) - .update(|(this, visitor)| { + .update(walker, |walker, (this, visitor)| { // Walk the walker. walker .walk(visitor.cast()) - .map(|value| match value { + .map(this, |this, value| match value { Ok(value) => { this.state = DynWalkerState::Done(value); Flow::Done @@ -147,7 +157,7 @@ impl<'ctx, W: Walker<'ctx, E>, E: Environment> WalkerObjSafe<'ctx, E> for DynWal }) .cast() }) - .map(|(_, value)| value) + .map((), |_, (_, value)| value) .cast() } else { // Can't do anything if the walker has already been walked. diff --git a/src/walk/walkers/core/bool.rs b/src/walk/walkers/core/bool.rs index 669978e..c6e7652 100644 --- a/src/walk/walkers/core/bool.rs +++ b/src/walk/walkers/core/bool.rs @@ -1,16 +1,17 @@ -use effectful::environment::{Environment, NativeForm}; - -use crate::{ - Walk, +use effectful::{ + effective::Effective, + environment::{Environment, NativeForm}, }; +use crate::Walk; + use super::value::ValueWalker; impl<'ctx, M, E: Environment> Walk<'ctx, M, E> for bool { type Walker = ValueWalker<bool>; fn into_walker<'e>(self) -> NativeForm<'e, Self::Walker, E> { - E::ready(ValueWalker::new(self)) + E::value(ValueWalker::new(self)).cast() } } @@ -18,6 +19,6 @@ impl<'ctx, M, E: Environment> Walk<'ctx, M, E> for &'ctx bool { type Walker = ValueWalker<bool>; fn into_walker<'e>(self) -> NativeForm<'e, Self::Walker, E> { - E::ready(ValueWalker::new(*self)) + E::value(ValueWalker::new(*self)).cast() } } diff --git a/src/walk/walkers/core/int.rs b/src/walk/walkers/core/int.rs index 2df49ea..bef10d8 100644 --- a/src/walk/walkers/core/int.rs +++ b/src/walk/walkers/core/int.rs @@ -1,5 +1,7 @@ +use effectful::effective::Effective; use effectful::environment::{DynBind, Environment, NativeForm}; use effectful::forward_send_sync; +use effectful::higher_ranked::Mut; use crate::{ any::OwnedStatic, @@ -78,9 +80,9 @@ impl<T: Integer> ::core::fmt::Display for IntegerWalkerError<T> { } } -impl<'ctx, T: Integer, E: Environment> Walker<'ctx, E> for IntegerWalker<T, E> +impl<'ctx, T: Integer, E: Environment> Walker<'ctx, E> for IntegerWalker<T, E> where - T: DynBind<E> + T: DynBind<E>, { type Error = IntegerWalkerError<T>; @@ -95,124 +97,138 @@ where { let value = self.value; - E::as_ctx((self, visitor), move |(this, visitor)| { - request_hint::<E>(visitor.cast(), DynWalker(this)) - .map(VisitResult::unit_skipped) - .cast() - }) - .map(|((_, visitor), result)| (visitor, result)) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, i8>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) + E::value((self, visitor)) + .update((), |_, (this, visitor)| { + request_hint::<E>(visitor.cast(), DynWalker(this)) + .map((), |_, x| VisitResult::unit_skipped(x)) .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, u8>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, i16>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, u16>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, i32>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, u32>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, i64>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, u64>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, i128>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, u128>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, isize>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .if_skipped(move |visitor| { - if let Some(value) = try_into::<_, usize>(value) { - visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) - .cast() - } else { - E::ready(VisitResult::Skipped(())).cast() - } - }) - .map(move |(_, result)| match result { - VisitResult::Skipped(()) => Err(IntegerWalkerError { value }), - VisitResult::Control(_) => Ok(value), - }) + }) + .map((), |_, ((_, visitor), result)| (visitor, result)) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, i8>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, u8>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, i16>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, u16>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, i32>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, u32>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, i64>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, u64>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, i128>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, u128>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, isize>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .cast::<()>() + .if_skipped(value, |value, visitor| { + if let Some(value) = try_into::<_, usize>(value) { + visit_value::<_, E>(visitor.cast(), OwnedStatic(value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + } else { + E::value(VisitResult::Skipped(())).cast() + } + }) + .map(value, |value, (_, result)| match result { + VisitResult::Skipped(()) => Err(IntegerWalkerError { value }), + VisitResult::Control(_) => Ok(value), + }) + .cast() } } @@ -270,9 +286,10 @@ macro_rules! impl_hints { { if let Some(value) = try_into::<_, $type>(self.value) { visit_value::<_, E>(visitor.into_inner(), OwnedStatic(value)) - .map(VisitResult::unit_skipped) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() } else { - E::ready(VisitResult::Skipped(())) + E::value(VisitResult::Skipped(())).cast() } } @@ -281,7 +298,7 @@ macro_rules! impl_hints { _hint: &'a MetaHint<'a, 'ctx, ValueProto<OwnedStatic<$type>, E>>, ) -> NativeForm<'a, Result<MetaKnown<'a, 'ctx, ValueProto<OwnedStatic<$type>, E>>, ()>, E> { - E::ready(Ok(ValueKnown { preview: None })) + E::value(Ok(ValueKnown { preview: None })).cast() } })* }; diff --git a/src/walk/walkers/core/key_value.rs b/src/walk/walkers/core/key_value.rs index 6469203..e1b38ac 100644 --- a/src/walk/walkers/core/key_value.rs +++ b/src/walk/walkers/core/key_value.rs @@ -1,4 +1,8 @@ -use effectful::{environment::{Environment, NativeForm}, forward_send_sync}; +use effectful::{ + effective::Effective, + environment::{Environment, NativeForm}, + forward_send_sync, +}; use crate::{ never::Never, @@ -63,32 +67,26 @@ where _tag, } = self; - E::as_ctx( - visitor, - #[inline(always)] - |visitor| { + E::value(visitor) + .update(key_walker, |key_walker, visitor| { visit_tag::<tags::Key, E, _>(TagConst, visitor.cast(), key_walker) - .map(|result| match result { + .map((), |_, result| match result { Ok(visit) => visit.unit_skipped(), Err(_) => Flow::Err.into(), }) .cast() - }, - ) - .if_not_finished( - #[inline(always)] - |visitor| { + }) + .if_not_finished(value_walker, |value_walker, visitor| { value_walker .walk(visitor.cast()) - .map(|result| match result { + .map((), |_, result| match result { Ok(_) => Flow::Done.into(), Err(_err) => Flow::Err.into(), }) .cast() - }, - ) - .remove_ctx() - .map(|_| Ok(())) + }) + .map((), |_, _| Ok(())) + .cast() // E::wrap(async move { // match visit_tag::<T, E, _>(self.tag, visitor.cast(), NoopWalker::new()).await { diff --git a/src/walk/walkers/core/noop.rs b/src/walk/walkers/core/noop.rs index 8f81626..0229048 100644 --- a/src/walk/walkers/core/noop.rs +++ b/src/walk/walkers/core/noop.rs @@ -1,10 +1,11 @@ -use effectful::{environment::{Environment, NativeForm}, is_send_sync, effective::Effective}; - -use crate::{ - never::Never, - protocol::DynVisitor, +use effectful::{ + effective::Effective, + environment::{Environment, NativeForm}, + is_send_sync, }; +use crate::{never::Never, protocol::DynVisitor}; + /// A walker that does nothing. /// /// This walker is useful for tags that don't need a value. diff --git a/src/walk/walkers/core/struct.rs b/src/walk/walkers/core/struct.rs index 899f99f..3150273 100644 --- a/src/walk/walkers/core/struct.rs +++ b/src/walk/walkers/core/struct.rs @@ -1,6 +1,11 @@ use core::any::TypeId; -use effectful::{bound::{IsSend, IsSync}, environment::{DynBind, Environment, NativeForm}, forward_send_sync}; +use effectful::{ + bound::{IsSend, IsSync}, + effective::Effective, + environment::{DynBind, Environment, NativeForm}, + forward_send_sync, +}; use crate::{ any::{AnyTrait, BorrowedStatic, BorrowedStaticHrt, StaticType}, @@ -41,8 +46,14 @@ pub struct StructWalker<'ctx, I: StructTypeInfo<'ctx, M, E, S = S>, S, M, E: Env _generics: Marker<E>, } -unsafe impl<'ctx, I: StructTypeInfo<'ctx, M, E, S = S>, S, M, E: Environment> IsSend<E::NeedSend> for StructWalker<'ctx, I, S, M, E> {} -unsafe impl<'ctx, I: StructTypeInfo<'ctx, M, E, S = S>, S, M, E: Environment> IsSync<E::NeedSync> for StructWalker<'ctx, I, S, M, E> {} +unsafe impl<'ctx, I: StructTypeInfo<'ctx, M, E, S = S>, S, M, E: Environment> IsSend<E::NeedSend> + for StructWalker<'ctx, I, S, M, E> +{ +} +unsafe impl<'ctx, I: StructTypeInfo<'ctx, M, E, S = S>, S, M, E: Environment> IsSync<E::NeedSync> + for StructWalker<'ctx, I, S, M, E> +{ +} /// Type info about a struct needed by [`StructWalker`]. pub trait StructTypeInfo<'ctx, M, E: Environment>: 'static { @@ -136,17 +147,15 @@ where where Self: 'c, { - E::ready((self, visitor)) - .as_ctx( - #[inline(always)] - |(this, visitor)| { - RecoverableScope::<'ctx, E>::new_walk::<'_, '_, '_>(this, visitor.cast()).cast() - }, - ) - .map(|((this, _), _)| match this.error { + E::value((self, visitor)) + .update((), |_, (this, visitor)| { + RecoverableScope::<'ctx, E>::new_walk::<'_, '_, '_>(this, visitor.cast()).cast() + }) + .map((), |_, ((this, _), _)| match this.error { Some(err) => Err(StructWalkError { kind: err }), None => Ok(()), }) + .cast() // E::ready(self).as_ctx_for::<'ctx, '_>(|this, _| { // (RecoverableScope::<'ctx, E>::new_walk::<'_, 'b, '_>(this, visitor), PhantomData) @@ -213,7 +222,7 @@ where &'a mut self, _hint: &'a <RecoverableProto<E> as HintMeta>::Hint, ) -> NativeForm<'a, Result<MetaKnown<'a, 'ctx, RecoverableProto<E>>, ()>, E> { - E::ready(Ok(RecoverableKnown)) + E::value(Ok(RecoverableKnown)).cast() } } @@ -263,9 +272,10 @@ where Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>>, ()>, E, > { - E::ready(Ok(TagKnown { + E::value(Ok(TagKnown { kind_available: Some(true), })) + .cast() } } @@ -311,9 +321,10 @@ where Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_TYPE_NAME.to_int() }>, E>>, ()>, E, > { - E::ready(Ok(TagKnown { + E::value(Ok(TagKnown { kind_available: Some(true), })) + .cast() } } @@ -355,9 +366,10 @@ where Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_MAP.to_int() }>, E>>, ()>, E, > { - E::ready(Ok(TagKnown { + E::value(Ok(TagKnown { kind_available: Some(true), })) + .cast() } } @@ -376,18 +388,20 @@ where where 'ctx: 'this + 'visitor + 'hint + 'e, { - E::as_ctx( + E::with( (visitor, DynWalkerAdapter::new(NoopWalker::new())), - #[inline(always)] |(visitor, noop_walker)| { visitor .as_known() .visit(TagConst, noop_walker) - .map(|status| VisitResult::Control(status.to_flow().unwrap_or(Flow::Continue))) + .map((), |_, status| { + VisitResult::Control(status.to_flow().unwrap_or(Flow::Continue)) + }) .cast() }, ) - .remove_ctx() + .map((), |_, (_, x)| x) + .cast() } #[inline(always)] @@ -399,9 +413,10 @@ where Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_STRUCT.to_int() }>, E>>, ()>, E, > { - E::ready(Ok(TagKnown { + E::value(Ok(TagKnown { kind_available: Some(true), })) + .cast() } } @@ -448,9 +463,10 @@ where Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_TYPE_ID.to_int() }>, E>>, ()>, E, > { - E::ready(Ok(TagKnown { + E::value(Ok(TagKnown { kind_available: Some(true), })) + .cast() } } @@ -510,7 +526,7 @@ where &'a mut self, hint: &'a <TagProto<TagDyn, E> as HintMeta>::Hint, ) -> NativeForm<'a, Result<MetaKnown<'a, 'ctx, TagProto<TagDyn, E>>, ()>, E> { - E::ready(match hint.kind { + E::value(match hint.kind { TagDyn(crate::TAG_TYPE_ID) | TagDyn(crate::TAG_STRUCT) => Ok(TagKnown { kind_available: Some(true), }), @@ -518,6 +534,7 @@ where kind_available: Some(false), }), }) + .cast() } } @@ -552,7 +569,7 @@ where &'a mut self, _hint: &'a (), ) -> NativeForm<'a, Result<ValueKnown<'a, BorrowedStatic<'ctx, I::T>>, ()>, E> { - E::ready(Ok(ValueKnown { preview: None })) + E::value(Ok(ValueKnown { preview: None })).cast() } } @@ -571,11 +588,11 @@ where where 'ctx: 'this + 'visitor + 'hint + 'e, { - E::as_ctx_map((self, visitor), |(this, visitor)| { + E::with((self, visitor), |(this, visitor)| { visitor .as_known() .visit(*this) - .map(|status| { + .map((), |_, status| { match status { VisitResult::Skipped(_) => Flow::Continue, VisitResult::Control(flow) => flow, @@ -584,6 +601,8 @@ where }) .cast() }) + .map((), |_, (_, x)| x) + .cast() } #[inline(always)] @@ -593,9 +612,10 @@ where ) -> NativeForm<'a, Result<MetaKnown<'a, 'ctx, SequenceProto<E>>, ()>, E> { let len = I::FIELDS.len(); - E::ready(Ok(SequenceKnown { + E::value(Ok(SequenceKnown { len: (len, Some(len)), })) + .cast() } } @@ -608,7 +628,7 @@ where fn size_hint(&mut self) -> NativeForm<'_, (usize, Option<usize>), E> { let len = I::FIELDS.len(); - E::ready((len, Some(len))) + E::value((len, Some(len))).cast() } #[inline(always)] @@ -617,20 +637,22 @@ where visitor: DynVisitor<'b, 'ctx, E>, ) -> NativeForm<'c, Flow, E> { if self.index >= I::FIELDS.len() { - return Flow::Done.ready(); + return E::value(Flow::Done).cast(); } let index = self.index; self.index += 1; - I::walk_field(index, self.value, visitor).map(|result| match result { - Ok(flow) => flow, - Err(err) => { - // Record the error and signal a break. - self.error = Some(StructWalkErrorKind::Field(err)); - Flow::Err - } - }) + I::walk_field(index, self.value, visitor) + .map(self, |this, result| match result { + Ok(flow) => flow, + Err(err) => { + // Record the error and signal a break. + this.error = Some(StructWalkErrorKind::Field(err)); + Flow::Err + } + }) + .cast() // E::map( // I::walk_field::<E>(index, self.value, visitor), @@ -650,7 +672,7 @@ impl<'ctx, I, M: 'ctx, E> RecoverableScope<'ctx, E> for StructWalker<'ctx, I, St where E: Environment, I: StructTypeInfo<'ctx, M, E, S = StaticType>, - I::T: 'static, + I::T: IsSync<E::NeedSend> + 'static, { #[inline(always)] fn new_walk<'a: 'c, 'b: 'c, 'c>( @@ -663,49 +685,61 @@ where // Reset the field index to the default. self.index = 0; - E::as_ctx((self, visitor), |(this, visitor)| { - request_hint::<E>(visitor.cast(), DynWalker(*this)) - .map(VisitResult::unit_skipped) + E::value((self, visitor)) + .update((), |_, (this, visitor)| { + request_hint::<E>(visitor.cast(), DynWalker(*this)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + }) + .cast::<()>() + .if_not_finished((), |_, (this, visitor)| { + visit_value::<_, E>(visitor.cast(), BorrowedStatic(this.value)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + }) + .cast::<()>() + .if_not_finished((), |_, (this, visitor)| { + visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>( + TagConst, + visitor.cast(), + ValueWalker::new(TypeId::of::<I::T>()), + ) + .map(this, |this, result| { + this.record_tag_error(result).unit_skipped() + }) .cast() - }) - .if_not_finished(|(this, visitor)| { - visit_value::<_, E>(visitor.cast(), BorrowedStatic(this.value)) - .map(VisitResult::unit_skipped) + }) + .cast::<()>() + .if_not_finished((), |_, (this, visitor)| { + visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>( + TagConst, + visitor.cast(), + NoopWalker::new(), + ) + .map(this, |this, result| { + this.record_tag_error(result).unit_skipped() + }) .cast() - }) - .if_not_finished(|(this, visitor)| { - visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>( - TagConst, - visitor.cast(), - ValueWalker::new(TypeId::of::<I::T>()), - ) - .map(|result| this.record_tag_error(result).unit_skipped()) - .cast() - }) - .if_not_finished(|(this, visitor)| { - visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>( - TagConst, - visitor.cast(), - NoopWalker::new(), - ) - .map(|result| this.record_tag_error(result).unit_skipped()) - .cast() - }) - .if_skipped(|(this, visitor)| { - visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>( - TagConst, - visitor.cast(), - NoopWalker::new(), - ) - .map(|result| this.record_tag_error(result).unit_skipped()) - .cast() - }) - .if_not_finished(|(this, visitor)| { - visit_sequence::<E>(visitor.cast(), *this) - .map(VisitResult::unit_skipped) + }) + .cast::<()>() + .if_skipped((), |_, (this, visitor)| { + visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>( + TagConst, + visitor.cast(), + NoopWalker::new(), + ) + .map(this, |this, result| { + this.record_tag_error(result).unit_skipped() + }) .cast() - }) - .remove_ctx() - .map(VisitResult::to_status) + }) + .cast::<()>() + .if_not_finished((), |_, (this, visitor)| { + visit_sequence::<E>(visitor.cast(), *this) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + }) + .map((), |_, (_, x)| VisitResult::to_status(x)) + .cast() } } diff --git a/src/walk/walkers/core/tag.rs b/src/walk/walkers/core/tag.rs index 931cfe4..378c063 100644 --- a/src/walk/walkers/core/tag.rs +++ b/src/walk/walkers/core/tag.rs @@ -1,6 +1,11 @@ use core::marker::PhantomData; -use effectful::{bound::IsSync, environment::{Environment, NativeForm}, forward_send_sync}; +use effectful::{ + bound::IsSync, + effective::Effective, + environment::{Environment, NativeForm}, + forward_send_sync, +}; use crate::{ any_trait, diff --git a/src/walk/walkers/core/value.rs b/src/walk/walkers/core/value.rs index 5ed43e0..d3f9159 100644 --- a/src/walk/walkers/core/value.rs +++ b/src/walk/walkers/core/value.rs @@ -1,4 +1,9 @@ -use effectful::{bound::IsSync, environment::{DynBind, Environment, NativeForm}, forward_send_sync}; +use effectful::{ + bound::IsSync, + effective::Effective, + environment::{DynBind, Environment, NativeForm}, + forward_send_sync, +}; use crate::{ any::{BorrowedStatic, OwnedStatic, TempBorrowedStatic}, @@ -40,9 +45,9 @@ impl<T: Copy> From<&T> for ValueWalker<T> { } } -impl<'ctx, T: 'static, E: Environment> crate::Walker<'ctx, E> for ValueWalker<T> +impl<'ctx, T: 'static, E: Environment> crate::Walker<'ctx, E> for ValueWalker<T> where - T: DynBind<E> + T: DynBind<E>, { type Error = Never; @@ -54,7 +59,9 @@ where visitor: DynVisitor<'b, 'ctx, E>, ) -> NativeForm<'c, Result<Self::Output, Self::Error>, E> { // Attempt to visit using the value protocol. - visit_value::<_, E>(visitor, OwnedStatic(self.0)).map(|_| Ok(())) + visit_value::<_, E>(visitor, OwnedStatic(self.0)) + .map((), |_, _| Ok(())) + .cast() } } @@ -76,7 +83,7 @@ impl<'ctx, T: ?Sized> BorrowWalker<'ctx, T> { impl<'ctx, T: ?Sized + DynBind<E> + 'static, E: Environment> crate::Walker<'ctx, E> for BorrowWalker<'ctx, T> where - T: IsSync<E::NeedSend> + T: IsSync<E::NeedSend>, { type Error = Never; @@ -88,16 +95,18 @@ where visitor: DynVisitor<'b, 'ctx, E>, ) -> NativeForm<'c, Result<Self::Output, Self::Error>, E> { // Attempt to visit using the value protocol. - E::as_ctx((self, visitor), |(this, visitor)| { - visit_value::<_, E>(visitor.cast(), BorrowedStatic(this.0)) - .map(VisitResult::unit_skipped) - .cast() - }) - .if_skipped(|(this, visitor)| { - visit_value::<_, E>(visitor.cast(), TempBorrowedStatic(this.0)) - .map(VisitResult::unit_skipped) - .cast() - }) - .map(|((this, _), _)| Ok(this.0)) + E::value((self, visitor)) + .update((), |_, (this, visitor)| { + visit_value::<_, E>(visitor.cast(), BorrowedStatic(this.0)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + }) + .if_skipped((), |_, (this, visitor)| { + visit_value::<_, E>(visitor.cast(), TempBorrowedStatic(this.0)) + .map((), |_, x| VisitResult::unit_skipped(x)) + .cast() + }) + .map((), |_, ((this, _), _)| Ok(this.0)) + .cast() } } diff --git a/tests/builder_enum.rs b/tests/builder_enum.rs index b589d6c..7eb4574 100644 --- a/tests/builder_enum.rs +++ b/tests/builder_enum.rs @@ -1,9 +1,5 @@ use treaty::{ any::{OwnedStatic, TypeName}, - effect::{ - blocking::Blocking, Effect, Effective as _, EffectiveExt as _, ErasedEffective, - ResultErrorExt as _, - }, protocol::{ visitor::{tags, DynRecoverableScope}, AsVisitor as _, DynVisitor, @@ -12,10 +8,19 @@ use treaty::{ Build, BuildExt as _, Builder, BuilderTypes, Status, }; -use crate::common::protocol::{ - recoverable::{MockRecoverableScopeVisitor, RecoverableVisitorExt as _}, - tag::TagVisitorExt as _, - value::ValueVisitorExt as _, +use crate::common::{ + protocol::{ + recoverable::{MockRecoverableScopeVisitor, RecoverableVisitorExt as _}, + tag::TagVisitorExt as _, + value::ValueVisitorExt as _, + }, + Blocking, +}; + +use effectful::{ + environment::{Environment, NativeForm}, + effective::Effective, + is_send_sync, }; use macro_rules_attribute::derive; @@ -28,6 +33,8 @@ enum X { B(bool), } +is_send_sync!(X); + #[test] fn enum_builder_takes_unsigned_integer_variant_tag() { let mut builder = X::new_builder(); @@ -41,7 +48,7 @@ fn enum_builder_takes_unsigned_integer_variant_tag() { builder.visit_value_and_done(OwnedStatic(1.23f32)); } - assert_eq!(builder.build().value().unwrap(), X::A(1.23)); + assert_eq!(builder.build().into_value().unwrap(), X::A(1.23)); } #[test] @@ -57,7 +64,7 @@ fn enum_builder_takes_string_variant_tag() { builder.visit_value_and_done(OwnedStatic(1.23f32)); } - assert_eq!(builder.build().value().unwrap(), X::A(1.23)); + assert_eq!(builder.build().into_value().unwrap(), X::A(1.23)); } #[test] @@ -90,5 +97,5 @@ fn enum_builder_can_guess_the_variant() { } // The enum should have a value now. - assert_eq!(builder.build().value().unwrap(), X::B(true)); + assert_eq!(builder.build().into_value().unwrap(), X::B(true)); } diff --git a/tests/builder_struct.rs b/tests/builder_struct.rs index b758379..f8eb0d6 100644 --- a/tests/builder_struct.rs +++ b/tests/builder_struct.rs @@ -1,7 +1,7 @@ +use effectful::is_send_sync; use macro_rules_attribute::derive; use treaty::{ any::{OwnedStatic, TempBorrowedStatic}, - effect::blocking::Blocking, protocol::{ visitor::{tags, visit_sequence, visit_tag, TagConst, VisitResult}, AsVisitor as _, @@ -13,6 +13,7 @@ use treaty::{ use crate::common::{ protocol::{sequence::MockSequenceScope, value::ValueVisitorExt as _}, walker::MockWalker, + Blocking, }; mod common; @@ -23,6 +24,8 @@ struct X { b: bool, } +is_send_sync!(X); + #[test] fn a_struct_builder_can_build_from_a_sequence_of_field_values() { let mut scope; @@ -55,12 +58,12 @@ fn a_struct_builder_can_build_from_a_sequence_of_field_values() { // Visit the sequence of field values. // The struct visitor should report as done. assert!(matches!( - visit_sequence(builder.as_visitor(), &mut scope).value(), + visit_sequence(builder.as_visitor(), &mut scope).into_value(), VisitResult::Control(Flow::Done) )); // The builder should be able to build a instance of the struct. - assert_eq!(builder.build().value().unwrap(), X { a: true, b: false }); + assert_eq!(builder.build().into_value().unwrap(), X { a: true, b: false }); } #[test] @@ -74,7 +77,7 @@ fn a_struct_builder_can_build_from_a_sequence_of_keyed_values() { scope.expect_next().once().returning(|mut visitor| { let mut walker; { - walker = MockWalker::<(), ()>::new(); + walker = MockWalker::<(), (), Blocking>::new(); // We need to give the b field name in the key tag. walker.expect_walk().once().returning(|mut visitor| { @@ -86,7 +89,7 @@ fn a_struct_builder_can_build_from_a_sequence_of_keyed_values() { // Tag the value with a key as the field name. assert_eq!( - visit_tag::<tags::Key, Blocking, _>(TagConst, visitor.cast(), walker).value(), + visit_tag::<tags::Key, Blocking, _>(TagConst, visitor.cast(), walker).into_value(), Ok(VisitResult::Control(Flow::Continue)), ); @@ -101,7 +104,7 @@ fn a_struct_builder_can_build_from_a_sequence_of_keyed_values() { scope.expect_next().once().returning(|mut visitor| { let mut walker; { - walker = MockWalker::<(), ()>::new(); + walker = MockWalker::<(), (), Blocking>::new(); // Here we do field a. walker.expect_walk().once().returning(|mut visitor| { @@ -113,7 +116,7 @@ fn a_struct_builder_can_build_from_a_sequence_of_keyed_values() { // Tag the value with a key. assert_eq!( - visit_tag::<tags::Key, Blocking, _>(TagConst, visitor.cast(), walker).value(), + visit_tag::<tags::Key, Blocking, _>(TagConst, visitor.cast(), walker).into_value(), Ok(VisitResult::Control(Flow::Continue)), ); @@ -134,16 +137,16 @@ fn a_struct_builder_can_build_from_a_sequence_of_keyed_values() { // This tag notifies the struct builder to expect the sequence as a map. assert_eq!( visit_tag::<tags::Map, Blocking, _>(TagConst, builder.as_visitor(), NoopWalker::new()) - .value(), + .into_value(), Ok(VisitResult::Control(Flow::Continue)) ); // Visit the sequence of fields. assert_eq!( - visit_sequence(builder.as_visitor(), &mut scope).value(), + visit_sequence(builder.as_visitor(), &mut scope).into_value(), VisitResult::Control(Flow::Done) ); // The struct is built as the mock walker above makes it. - assert_eq!(builder.build().value().unwrap(), X { a: false, b: true }); + assert_eq!(builder.build().into_value().unwrap(), X { a: false, b: true }); } diff --git a/tests/builder_value.rs b/tests/builder_value.rs index 7e59b76..3adabf4 100644 --- a/tests/builder_value.rs +++ b/tests/builder_value.rs @@ -3,7 +3,6 @@ mod common; use common::walker::MockWalker; use treaty::{ any::{BorrowedStatic, OwnedStatic, TempBorrowedStatic}, - effect::blocking::Blocking, protocol::{ visitor::{request_hint, ValueProto}, AsVisitor as _, DynWalker, @@ -11,7 +10,10 @@ use treaty::{ BuildExt as _, Builder as _, Flow, }; -use crate::common::protocol::{hint::MockHintWalker, value::ValueVisitorExt as _}; +use crate::common::{ + protocol::{hint::MockHintWalker, value::ValueVisitorExt as _}, + Blocking, +}; #[test] fn value_builder_gives_value_protocol_as_hint() { @@ -23,7 +25,7 @@ fn value_builder_gives_value_protocol_as_hint() { walker.expect_hint().once().returning(|mut visitor, ()| { // Fulfill the hint by visiting with a i32 value. assert_eq!( - visitor.as_known().visit(OwnedStatic(42)).value(), + visitor.as_known().visit(OwnedStatic(42)).into_value(), Flow::Done.into() ); @@ -33,19 +35,19 @@ fn value_builder_gives_value_protocol_as_hint() { // Request a hint from the i32 builder for what protocol to use. assert_eq!( - request_hint::<Blocking>(builder.as_visitor(), DynWalker(&mut walker)).value(), + request_hint::<Blocking>(builder.as_visitor(), DynWalker(&mut walker)).into_value(), Flow::Done.into() ); // The builder should have the value. - assert_eq!(builder.build().value().unwrap(), 42); + assert_eq!(builder.build().into_value().unwrap(), 42); } #[test] fn value_builder_can_use_an_owned_value_or_a_borrowed_value() { assert_eq!( i32::build({ - let mut walker = MockWalker::<(), ()>::new(); + let mut walker = MockWalker::<(), (), Blocking>::new(); walker.expect_walk().once().returning(|mut visitor| { visitor.visit_value_and_done(OwnedStatic(1)); Ok(()) @@ -58,7 +60,7 @@ fn value_builder_can_use_an_owned_value_or_a_borrowed_value() { assert_eq!( i32::build({ - let mut walker = MockWalker::<(), ()>::new(); + let mut walker = MockWalker::<(), (), Blocking>::new(); walker.expect_walk().once().returning(|mut visitor| { visitor.visit_value_and_done(BorrowedStatic(&2)); Ok(()) @@ -71,7 +73,7 @@ fn value_builder_can_use_an_owned_value_or_a_borrowed_value() { assert_eq!( i32::build({ - let mut walker = MockWalker::<(), ()>::new(); + let mut walker = MockWalker::<(), (), Blocking>::new(); walker.expect_walk().once().returning(|mut visitor| { visitor.visit_value_and_done(TempBorrowedStatic(&3)); Ok(()) diff --git a/tests/common/builder.rs b/tests/common/builder.rs index 74b78cd..64d77f9 100644 --- a/tests/common/builder.rs +++ b/tests/common/builder.rs @@ -1,8 +1,13 @@ use core::fmt::{Debug, Display}; +use effectful::{ + bound::{Bool, IsSend, IsSync}, + environment::{DynBind, Environment, NativeForm}, + effective::Effective, + forward_send_sync, +}; use mockall::mock; use treaty::{ any::{indirect, AnyTrait, AnyTraitObject, TypeNameId}, - effect::{Effect, Effective, ErasedEffective}, protocol::{AsVisitor, DynVisitor}, Builder, BuilderTypes, }; @@ -23,17 +28,32 @@ impl Display for EmptyError { } mock! { - pub Builder<Seed: 'static, Value: 'static, Error: 'static> { + pub Builder<Seed: 'static, Value: 'static, Error: 'static, E: Environment> { pub fn from_seed(seed: Seed) -> Self; pub fn build(self) -> Result<Value, Error>; - pub fn traits(&self, id: TypeNameId) -> &Option<Box<dyn for<'ctx> AnyTrait<'ctx> + Send + Sync>>; - pub fn traits_mut(&mut self, id: TypeNameId) -> &mut Option<Box<dyn for<'ctx> AnyTrait<'ctx> + Send + Sync>>; + pub fn traits(&self, id: TypeNameId) -> &Option<Box<dyn for<'ctx> AnyTrait<'ctx, E>>>; + pub fn traits_mut(&mut self, id: TypeNameId) -> &mut Option<Box<dyn for<'ctx> AnyTrait<'ctx, E>>>; } } -impl<Seed: Send + Sync, Value: Send + Sync, Error: Send + Sync + Display + Debug> BuilderTypes - for MockBuilder<Seed, Value, Error> +// forward_send_sync!({Seed: ('static), Value: ('static), Error: ('static)} {} {E: (Environment)} MockBuilder<Seed, Value, Error, E>); + +unsafe impl<Seed: 'static, Value: 'static, Error: 'static, E: Environment, F: Bool> IsSend<F> + for MockBuilder<Seed, Value, Error, E> +{ +} +unsafe impl<Seed: 'static, Value: 'static, Error: 'static, E: Environment, F: Bool> IsSync<F> + for MockBuilder<Seed, Value, Error, E> +{ +} + +impl<Seed, Value, Error: Display + Debug, E: Environment> BuilderTypes<E> + for MockBuilder<Seed, Value, Error, E> +where + Seed: DynBind<E>, + Value: DynBind<E>, + Error: DynBind<E>, { type Seed = Seed; @@ -42,8 +62,10 @@ impl<Seed: Send + Sync, Value: Send + Sync, Error: Send + Sync + Display + Debug type Value = Value; } -impl<Seed: 'static, Value: 'static, Error: 'static> MockBuilder<Seed, Value, Error> { - pub fn lock_from_seed_context<'a>() -> ContextGuard<'a, Context<Seed, Value, Error>> { +impl<Seed: 'static, Value: 'static, Error: 'static, E: Environment> + MockBuilder<Seed, Value, Error, E> +{ + pub fn lock_from_seed_context<'a>() -> ContextGuard<'a, Context<Seed, Value, Error, E>> { static LOCKS: StaticTypeMap = StaticTypeMap::new(); LOCKS @@ -58,31 +80,31 @@ impl<Seed: 'static, Value: 'static, Error: 'static> MockBuilder<Seed, Value, Err impl< 'ctx, - Seed: Send + Sync, - Value: Send + Sync, - Error: Send + Sync + Display + Debug, - E: Effect, - > Builder<'ctx, E> for MockBuilder<Seed, Value, Error> + Seed: DynBind<E>, + Value: DynBind<E>, + Error: DynBind<E> + Display + Debug, + E: Environment, + > Builder<'ctx, E> for MockBuilder<Seed, Value, Error, E> { - fn from_seed<'a>(seed: Self::Seed) -> ErasedEffective<'a, Self, E> + fn from_seed<'a>(seed: Self::Seed) -> NativeForm<'a, Self, E> where Self: 'a, { - E::ready(Self::from_seed(seed)) + E::value(Self::from_seed(seed)).cast() } - fn build<'a>(self) -> ErasedEffective<'a, Result<Self::Value, Self::Error>, E> + fn build<'a>(self) -> NativeForm<'a, Result<Self::Value, Self::Error>, E> where Self: 'a, { - E::ready(self.build()) + E::value(self.build()).cast() } } -impl<'ctx, Seed: Send + Sync, Value: Send + Sync, Error: Send + Sync + Display + Debug> - AsVisitor<'ctx> for MockBuilder<Seed, Value, Error> +impl<'ctx, Seed, Value, Error: Display + Debug, E: Environment> AsVisitor<'ctx, E> + for MockBuilder<Seed, Value, Error, E> { - fn as_visitor<'a>(&'a mut self) -> DynVisitor<'a, 'ctx> + fn as_visitor<'a>(&'a mut self) -> DynVisitor<'a, 'ctx, E> where 'ctx: 'a, { @@ -90,8 +112,13 @@ impl<'ctx, Seed: Send + Sync, Value: Send + Sync, Error: Send + Sync + Display + } } -impl<'ctx, Seed, Value, Error> AnyTrait<'ctx> for MockBuilder<Seed, Value, Error> { - fn upcast_to_id<'a>(&'a self, id: TypeNameId) -> Option<AnyTraitObject<'a, 'ctx, indirect::Ref>> +impl<'ctx, Seed, Value, Error, E: Environment> AnyTrait<'ctx, E> + for MockBuilder<Seed, Value, Error, E> +{ + fn upcast_to_id<'a>( + &'a self, + id: TypeNameId, + ) -> Option<AnyTraitObject<'a, 'ctx, indirect::Ref, E>> where 'ctx: 'a, { @@ -102,7 +129,7 @@ impl<'ctx, Seed, Value, Error> AnyTrait<'ctx> for MockBuilder<Seed, Value, Error fn upcast_to_id_mut<'a>( &'a mut self, id: TypeNameId, - ) -> Option<AnyTraitObject<'a, 'ctx, indirect::Mut>> + ) -> Option<AnyTraitObject<'a, 'ctx, indirect::Mut, E>> where 'ctx: 'a, { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 5c714e1..a856898 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -9,7 +9,9 @@ use std::{ sync::{Mutex, MutexGuard, OnceLock, RwLock}, }; -use treaty::effect::blocking::Spin; +use effectful::{block_on::Spin, blocking::Blocking as Block, bound::No, environment::Cfg}; + +pub type Blocking = Block<Cfg<Spin, No, No>>; pub mod builder; pub mod protocol; diff --git a/tests/common/protocol/hint.rs b/tests/common/protocol/hint.rs index 89f53a6..5884132 100644 --- a/tests/common/protocol/hint.rs +++ b/tests/common/protocol/hint.rs @@ -1,7 +1,11 @@ +use effectful::{ + bound::{Bool, IsSend, IsSync}, + effective::Effective, + environment::{Environment, NativeForm}, +}; use mockall::mock; use treaty::{ any::{any_trait, TypeName}, - effect::{Effect, Effective, ErasedEffective}, protocol::{ visitor::VisitResult, walker::hint::{DynVisitorWith, Hint, HintMeta, HintProto, MetaHint, MetaKnown}, @@ -21,11 +25,15 @@ mock! { } } +unsafe impl<P: HintMeta, F: Bool> IsSend<F> for MockHintWalker<P> {} +unsafe impl<P: HintMeta, F: Bool> IsSync<F> for MockHintWalker<P> {} + any_trait! { - impl['ctx, P] MockHintWalker<P> = [ + impl['ctx, P][E] MockHintWalker<P> = [ HintProto<P> ] where - P: HintMeta, + E: Environment, + P: HintMeta<Effect = E>, } impl<'ctx, P: HintMeta> Hint<'ctx, P> for MockHintWalker<P> { @@ -33,17 +41,17 @@ impl<'ctx, P: HintMeta> Hint<'ctx, P> for MockHintWalker<P> { &'this mut self, visitor: DynVisitorWith<'visitor, 'ctx, P>, hint: MetaHint<'hint, 'ctx, P>, - ) -> ErasedEffective<'e, VisitResult, P::Effect> + ) -> NativeForm<'e, VisitResult, P::Effect> where 'ctx: 'this + 'visitor + 'hint + 'e, { - P::Effect::ready(self.hint(visitor, hint)) + P::Effect::value(self.hint(visitor, hint)).cast() } fn known<'a>( &'a mut self, hint: &'a MetaHint<'a, 'ctx, P>, - ) -> ErasedEffective<'a, Result<MetaKnown<'a, 'ctx, P>, ()>, P::Effect> { - P::Effect::ready(Self::known(self)(&(), hint)) + ) -> NativeForm<'a, Result<MetaKnown<'a, 'ctx, P>, ()>, P::Effect> { + P::Effect::value(Self::known(self)(&(), hint)).cast() } } diff --git a/tests/common/protocol/recoverable.rs b/tests/common/protocol/recoverable.rs index 378e215..9f98afb 100644 --- a/tests/common/protocol/recoverable.rs +++ b/tests/common/protocol/recoverable.rs @@ -1,7 +1,12 @@ +use effectful::{ + blocking::Blocking as Block, + bound::{Bool, IsSend, IsSync}, + effective::Effective, + environment::{Environment, NativeForm}, +}; use mockall::mock; use treaty::{ any::{any_trait, TypeName}, - effect::{blocking::Blocking, Effect, Effective, ErasedEffective}, protocol::{ visitor::{ visit_recoverable, visit_sequence, DynRecoverableScope, DynSequenceScope, Recoverable, @@ -13,40 +18,48 @@ use treaty::{ Flow, Status, }; +use crate::common::Blocking; + mock! { pub RecoverableVisitor<E> { pub fn visit<'a, 'ctx>(&mut self, scope: DynRecoverableScope<'a, 'ctx, E>) -> VisitResult; } } +unsafe impl<E: Environment, F: Bool> IsSend<F> for MockRecoverableVisitor<E> {} +unsafe impl<E: Environment, F: Bool> IsSync<F> for MockRecoverableVisitor<E> {} + any_trait! { - impl['ctx, E] MockRecoverableVisitor<E> = [ + impl['ctx][E] MockRecoverableVisitor<E> = [ RecoverableProto<E> ] where - E: Effect, + E: Environment, } -impl<'ctx, E: Effect> Recoverable<'ctx, E> for MockRecoverableVisitor<E> { +impl<'ctx, E: Environment> Recoverable<'ctx, E> for MockRecoverableVisitor<E> { fn visit<'a>( &'a mut self, scope: DynRecoverableScope<'a, 'ctx, E>, - ) -> ErasedEffective<'a, VisitResult, E> { - E::ready(self.visit(scope)) + ) -> NativeForm<'a, VisitResult, E> { + E::value(self.visit(scope)).cast() } } mock! { - pub RecoverableScopeVisitor<E> { - pub fn new_walk<'a, 'b, 'ctx>(&'a mut self, visitor: DynVisitor<'b, 'ctx>) -> Status; + pub RecoverableScopeVisitor<E: Environment> { + pub fn new_walk<'a, 'b, 'ctx>(&'a mut self, visitor: DynVisitor<'b, 'ctx, E>) -> Status; } } -impl<'ctx, E: Effect> RecoverableScope<'ctx, E> for MockRecoverableScopeVisitor<E> { +unsafe impl<E: Environment, F: Bool> IsSend<F> for MockRecoverableScopeVisitor<E> {} +unsafe impl<E: Environment, F: Bool> IsSync<F> for MockRecoverableScopeVisitor<E> {} + +impl<'ctx, E: Environment> RecoverableScope<'ctx, E> for MockRecoverableScopeVisitor<E> { fn new_walk<'a: 'c, 'b: 'c, 'c>( &'a mut self, - visitor: DynVisitor<'b, 'ctx>, - ) -> ErasedEffective<'c, Status, E> { - E::ready(self.new_walk(visitor)) + visitor: DynVisitor<'b, 'ctx, E>, + ) -> NativeForm<'c, Status, E> { + E::value(self.new_walk(visitor)).cast() } } @@ -56,13 +69,13 @@ pub trait RecoverableVisitorExt<'ctx> { impl<'ctx, T> RecoverableVisitorExt<'ctx> for T where - T: AsVisitor<'ctx>, + T: AsVisitor<'ctx, Blocking>, { fn visit_recoverable_and_done<'a>( &'a mut self, scope: DynRecoverableScope<'a, 'ctx, Blocking>, ) { - let result = visit_recoverable(self.as_visitor(), scope).value(); + let result = visit_recoverable(self.as_visitor(), scope).into_value(); assert_eq!(result, VisitResult::Control(Flow::Done)); } diff --git a/tests/common/protocol/request_hint.rs b/tests/common/protocol/request_hint.rs index 63c423d..83de82b 100644 --- a/tests/common/protocol/request_hint.rs +++ b/tests/common/protocol/request_hint.rs @@ -1,33 +1,40 @@ +use effectful::{ + bound::{Bool, IsSend, IsSync}, + effective::Effective, + environment::{Environment, NativeForm}, +}; use mockall::mock; use treaty::{ any::{any_trait, TypeName}, - effect::{Effect, Effective, ErasedEffective}, protocol::visitor::{RequestHint, RequestHintProto, Value, ValueProto, VisitResult}, protocol::DynWalker, Flow, }; mock! { - pub RequestHintVisitor<E> { - pub fn request_hint<'a, 'ctx>(&mut self, walker: DynWalker<'a, 'ctx>) -> VisitResult; + pub RequestHintVisitor<E: Environment> { + pub fn request_hint<'a, 'ctx>(&mut self, walker: DynWalker<'a, 'ctx, E>) -> VisitResult; } } +unsafe impl<E: Environment, F: Bool> IsSend<F> for MockRequestHintVisitor<E> {} +unsafe impl<E: Environment, F: Bool> IsSync<F> for MockRequestHintVisitor<E> {} + any_trait! { - impl['ctx, E] MockRequestHintVisitor<E> = [ + impl['ctx][E] MockRequestHintVisitor<E> = [ RequestHintProto<E> ] where - E: Effect, + E: Environment, } -impl<'ctx, E: Effect> RequestHint<'ctx, E> for MockRequestHintVisitor<E> { +impl<'ctx, E: Environment> RequestHint<'ctx, E> for MockRequestHintVisitor<E> { fn request_hint<'this: 'e, 'walker: 'e, 'e>( &'this mut self, - walker: DynWalker<'walker, 'ctx>, - ) -> ErasedEffective<'e, VisitResult, E> + walker: DynWalker<'walker, 'ctx, E>, + ) -> NativeForm<'e, VisitResult, E> where 'ctx: 'this + 'walker, { - E::ready(self.request_hint(walker)) + E::value(self.request_hint(walker)).cast() } } diff --git a/tests/common/protocol/sequence.rs b/tests/common/protocol/sequence.rs index 43e71db..c580f05 100644 --- a/tests/common/protocol/sequence.rs +++ b/tests/common/protocol/sequence.rs @@ -1,7 +1,11 @@ +use effectful::{ + bound::{Bool, IsSend, IsSync}, + effective::Effective, + environment::{Environment, NativeForm}, +}; use mockall::mock; use treaty::{ any::{any_trait, TypeName}, - effect::{Effect, Effective, ErasedEffective}, protocol::DynWalker, protocol::{ visitor::{ @@ -19,38 +23,44 @@ mock! { } } +unsafe impl<E: Environment, F: Bool> IsSend<F> for MockSequenceVisitor<E> {} +unsafe impl<E: Environment, F: Bool> IsSync<F> for MockSequenceVisitor<E> {} + any_trait! { - impl['ctx, E] MockSequenceVisitor<E> = [ + impl['ctx][E] MockSequenceVisitor<E> = [ SequenceProto<E> ] where - E: Effect, + E: Environment, } -impl<'ctx, E: Effect> Sequence<'ctx, E> for MockSequenceVisitor<E> { +impl<'ctx, E: Environment> Sequence<'ctx, E> for MockSequenceVisitor<E> { fn visit<'a: 'c, 'b: 'c, 'c>( &'a mut self, scope: DynSequenceScope<'b, 'ctx, E>, - ) -> ErasedEffective<'c, VisitResult, E> { - E::ready(self.visit(scope)) + ) -> NativeForm<'c, VisitResult, E> { + E::value(self.visit(scope)).cast() } } mock! { - pub SequenceScope<E> { + pub SequenceScope<E: Environment> { pub fn size_hint(&mut self) -> (usize, Option<usize>); - pub fn next<'a, 'b, 'ctx>(&'a mut self, visitor: DynVisitor<'b, 'ctx>) -> Flow; + pub fn next<'a, 'b, 'ctx>(&'a mut self, visitor: DynVisitor<'b, 'ctx, E>) -> Flow; } } -impl<'ctx, E: Effect> SequenceScope<'ctx, E> for MockSequenceScope<E> { - fn size_hint(&mut self) -> ErasedEffective<'_, (usize, Option<usize>), E> { - E::ready(self.size_hint()) +unsafe impl<E: Environment, F: Bool> IsSend<F> for MockSequenceScope<E> {} +unsafe impl<E: Environment, F: Bool> IsSync<F> for MockSequenceScope<E> {} + +impl<'ctx, E: Environment> SequenceScope<'ctx, E> for MockSequenceScope<E> { + fn size_hint(&mut self) -> NativeForm<'_, (usize, Option<usize>), E> { + E::value(self.size_hint()).cast() } fn next<'a: 'c, 'b: 'c, 'c>( &'a mut self, - visitor: DynVisitor<'b, 'ctx>, - ) -> ErasedEffective<'c, Flow, E> { - E::ready(self.next(visitor)) + visitor: DynVisitor<'b, 'ctx, E>, + ) -> NativeForm<'c, Flow, E> { + E::value(self.next(visitor)).cast() } } diff --git a/tests/common/protocol/tag.rs b/tests/common/protocol/tag.rs index db11438..9ce76f3 100644 --- a/tests/common/protocol/tag.rs +++ b/tests/common/protocol/tag.rs @@ -1,7 +1,11 @@ +use effectful::{ + bound::{Bool, IsSend, IsSync}, + effective::Effective, + environment::{Environment, NativeForm}, +}; use mockall::mock; use treaty::{ any::any_trait, - effect::{blocking::Blocking, Effect, Effective, ErasedEffective}, protocol::{ visitor::{visit_tag, Tag, TagConst, TagKind, TagProto, VisitResult}, AsVisitor, DynVisitor, @@ -9,27 +13,32 @@ use treaty::{ DynWalkerObjSafe, Flow, Walker, }; +use crate::common::Blocking; + mock! { - pub TagVisitor<K: TagKind, E> { + pub TagVisitor<K: TagKind<E>, E: Environment> { pub fn visit<'a, 'ctx>(&'a mut self, kind: K, walker: DynWalkerObjSafe<'a, 'ctx, E>) -> VisitResult; } } any_trait! { - impl['ctx, K, E] MockTagVisitor<K, E> = [ + impl['ctx, K][E] MockTagVisitor<K, E> = [ TagProto<K, E>, ] where - K: TagKind, - E: Effect, + K: TagKind<E>, + E: Environment, } -impl<'ctx, K: TagKind, E: Effect> Tag<'ctx, K, E> for MockTagVisitor<K, E> { +unsafe impl<K: TagKind<E>, E: Environment, F: Bool> IsSend<F> for MockTagVisitor<K, E> {} +unsafe impl<K: TagKind<E>, E: Environment, F: Bool> IsSync<F> for MockTagVisitor<K, E> {} + +impl<'ctx, K: TagKind<E>, E: Environment> Tag<'ctx, K, E> for MockTagVisitor<K, E> { fn visit<'a: 'c, 'b: 'c, 'c>( &'a mut self, kind: K, walker: DynWalkerObjSafe<'b, 'ctx, E>, - ) -> ErasedEffective<'c, VisitResult, E> { - E::ready(self.visit(kind, walker)) + ) -> NativeForm<'c, VisitResult, E> { + E::value(self.visit(kind, walker)).cast() } } @@ -39,11 +48,11 @@ pub trait TagVisitorExt<'ctx> { impl<'ctx, T> TagVisitorExt<'ctx> for T where - T: AsVisitor<'ctx>, + T: AsVisitor<'ctx, Blocking>, { fn visit_tag_and_done<'a, const TAG: u64, W: Walker<'ctx, Blocking>>(&'a mut self, walker: W) { let result = - visit_tag::<TagConst<TAG>, Blocking, _>(TagConst, self.as_visitor(), walker).value(); + visit_tag::<TagConst<TAG>, Blocking, _>(TagConst, self.as_visitor(), walker).into_value(); assert_eq!(result.unwrap(), VisitResult::Control(Flow::Done)); } diff --git a/tests/common/protocol/value.rs b/tests/common/protocol/value.rs index 898b21d..fe470fa 100644 --- a/tests/common/protocol/value.rs +++ b/tests/common/protocol/value.rs @@ -1,7 +1,11 @@ +use effectful::{ + environment::{Environment, NativeForm}, + bound::{Bool, IsSend, IsSync}, + effective::Effective, +}; use mockall::mock; use treaty::{ any::{any_trait, OwnedStatic, TypeName}, - effect::{blocking::Blocking, Effect, Effective, ErasedEffective, Ss}, protocol::{ visitor::{visit_value, Value, ValueProto, VisitResult}, AsVisitor, DynVisitor, @@ -9,75 +13,89 @@ use treaty::{ Flow, }; +use crate::common::Blocking; + mock! { - pub ValueVisitor<T: TypeName::MemberType, E> + pub ValueVisitor<T: TypeName::MemberType<E>, E: Environment> where - for<'a, 'ctx> TypeName::T<'a, 'ctx, T>: Sized + for<'a, 'ctx> TypeName::T<'a, 'ctx, T, E>: Sized { - pub fn visit<'a, 'ctx>(&'a mut self, value: &TypeName::T<'a, 'ctx, T>) -> VisitResult<()>; + pub fn visit<'a, 'ctx>(&'a mut self, value: &TypeName::T<'a, 'ctx, T, E>) -> VisitResult<()>; } } +unsafe impl<T: TypeName::MemberType<E>, E: Environment, F: Bool> IsSend<F> for MockValueVisitor<T, E> +where + for<'a, 'ctx> TypeName::T<'a, 'ctx, T, E>: Sized + {} +unsafe impl<T: TypeName::MemberType<E>, E: Environment, F: Bool> IsSync<F> for MockValueVisitor<T, E> +where + for<'a, 'ctx> TypeName::T<'a, 'ctx, T, E>: Sized + {} + any_trait! { - impl['ctx, T, E] MockValueVisitor<T, E> = [ + impl['ctx, T][E] MockValueVisitor<T, E> = [ ValueProto<T, E> ] where - T: TypeName::MemberType + Ss, - for<'a, 'b> TypeName::T<'a, 'b, T>: Sized, - E: Effect, + T: TypeName::MemberType<E>, + for<'a, 'b> TypeName::T<'a, 'b, T, E>: Sized, + E: Environment, } -impl<'ctx, T: TypeName::MemberType, E: Effect> Value<'ctx, T, E> for MockValueVisitor<T, E> +impl<'ctx, T: TypeName::MemberType<E>, E: Environment> Value<'ctx, T, E> for MockValueVisitor<T, E> where - for<'a, 'lt> TypeName::T<'a, 'lt, T>: Sized, + for<'a, 'lt> TypeName::T<'a, 'lt, T, E>: Sized, { fn visit<'a>( &'a mut self, - value: TypeName::T<'a, 'ctx, T>, - ) -> ErasedEffective<'a, VisitResult<TypeName::T<'a, 'ctx, T>>, E> + value: TypeName::T<'a, 'ctx, T, E>, + ) -> NativeForm<'a, VisitResult<TypeName::T<'a, 'ctx, T, E>>, E> where - TypeName::T<'a, 'ctx, T>: Send, 'ctx: 'a, { - E::ready(match self.visit(&value) { + E::value(match self.visit(&value) { VisitResult::Skipped(_) => VisitResult::Skipped(value), VisitResult::Control(flow) => VisitResult::Control(flow), - }) + }).cast() } } pub trait ValueVisitorExt<'ctx> { fn visit_value_and_done<'a, T>(&'a mut self, value: T) where - T: TypeName::LowerType<'a, 'ctx>, + T: TypeName::LowerType<'a, 'ctx, Blocking>, + TypeName::HigherRanked<'a, 'ctx, T, Blocking>: TypeName::MemberType<Blocking>, 'ctx: 'a; fn visit_value_and_skipped<'a, T>(&'a mut self, value: T) where - T: TypeName::LowerType<'a, 'ctx>, + T: TypeName::LowerType<'a, 'ctx, Blocking>, + TypeName::HigherRanked<'a, 'ctx, T, Blocking>: TypeName::MemberType<Blocking>, 'ctx: 'a; } impl<'ctx, U> ValueVisitorExt<'ctx> for U where - U: AsVisitor<'ctx>, + U: AsVisitor<'ctx, Blocking>, { fn visit_value_and_done<'a, T>(&'a mut self, value: T) where - T: TypeName::LowerType<'a, 'ctx>, + T: TypeName::LowerType<'a, 'ctx, Blocking>, + TypeName::HigherRanked<'a, 'ctx, T, Blocking>: TypeName::MemberType<Blocking>, 'ctx: 'a, { - let result = visit_value::<_, Blocking>(self.as_visitor(), value).value(); + let result = visit_value::<_, Blocking>(self.as_visitor(), value).into_value(); assert_eq!(result, VisitResult::Control(Flow::Done)); } fn visit_value_and_skipped<'a, T>(&'a mut self, value: T) where - T: TypeName::LowerType<'a, 'ctx>, + T: TypeName::LowerType<'a, 'ctx, Blocking>, + TypeName::HigherRanked<'a, 'ctx, T, Blocking>: TypeName::MemberType<Blocking>, 'ctx: 'a, { - let result = visit_value::<_, Blocking>(self.as_visitor(), value).value(); + let result = visit_value::<_, Blocking>(self.as_visitor(), value).into_value(); assert_eq!(result.unit_skipped(), VisitResult::Skipped(())); } diff --git a/tests/common/walker.rs b/tests/common/walker.rs index 7956a98..7e90b7e 100644 --- a/tests/common/walker.rs +++ b/tests/common/walker.rs @@ -1,23 +1,36 @@ +use effectful::{ + effective::Effective, + bound::{Bool, IsSend, IsSync}, + environment::{Environment, NativeForm, DynBind}, +}; use mockall::mock; use treaty::{ any::{indirect, AnyTrait, AnyTraitObject, TypeNameId}, - effect::{Effect, Effective, ErasedEffective}, protocol::DynVisitor, Builder, BuilderTypes, Walker, }; mock! { - pub Walker<Output, Error> { - pub fn walk<'a, 'ctx>(self, visitor: DynVisitor<'a, 'ctx>) -> Result<Output, Error>; + pub Walker<Output, Error, E: Environment> { + pub fn walk<'a, 'ctx>(self, visitor: DynVisitor<'a, 'ctx, E>) -> Result<Output, Error>; - pub fn traits(&self, id: TypeNameId) -> &Option<Box<dyn for<'ctx> AnyTrait<'ctx> + Send + Sync>>; + pub fn traits(&self, id: TypeNameId) -> &Option<Box<dyn for<'ctx> AnyTrait<'ctx, E>>>; - pub fn traits_mut(&mut self, id: TypeNameId) -> &mut Option<Box<dyn for<'ctx> AnyTrait<'ctx> + Send + Sync>>; + pub fn traits_mut(&mut self, id: TypeNameId) -> &mut Option<Box<dyn for<'ctx> AnyTrait<'ctx, E>>>; } } -impl<'ctx, Output: Send + Sync, Error: Send + Sync + core::fmt::Debug, E: Effect> Walker<'ctx, E> - for MockWalker<Output, Error> +unsafe impl<Output, Error, E: Environment, F: Bool> IsSend<F> + for MockWalker<Output, Error, E> +{ +} +unsafe impl<Output, Error, E: Environment, F: Bool> IsSync<F> + for MockWalker<Output, Error, E> +{ +} + +impl<'ctx, Output: DynBind<E>, Error: DynBind<E> + core::fmt::Debug, E: Environment> + Walker<'ctx, E> for MockWalker<Output, Error, E> { type Error = Error; @@ -25,17 +38,20 @@ impl<'ctx, Output: Send + Sync, Error: Send + Sync + core::fmt::Debug, E: Effect fn walk<'a: 'c, 'c>( self, - visitor: DynVisitor<'a, 'ctx>, - ) -> ErasedEffective<'c, Result<Self::Output, Self::Error>, E> + visitor: DynVisitor<'a, 'ctx, E>, + ) -> NativeForm<'c, Result<Self::Output, Self::Error>, E> where Self: 'c, { - E::ready(self.walk(visitor)) + E::value(self.walk(visitor)).cast() } } -impl<'ctx, Output, Error> AnyTrait<'ctx> for MockWalker<Output, Error> { - fn upcast_to_id<'a>(&'a self, id: TypeNameId) -> Option<AnyTraitObject<'a, 'ctx, indirect::Ref>> +impl<'ctx, Output, Error, E: Environment> AnyTrait<'ctx, E> for MockWalker<Output, Error, E> { + fn upcast_to_id<'a>( + &'a self, + id: TypeNameId, + ) -> Option<AnyTraitObject<'a, 'ctx, indirect::Ref, E>> where 'ctx: 'a, { @@ -45,7 +61,7 @@ impl<'ctx, Output, Error> AnyTrait<'ctx> for MockWalker<Output, Error> { fn upcast_to_id_mut<'a>( &'a mut self, id: TypeNameId, - ) -> Option<AnyTraitObject<'a, 'ctx, indirect::Mut>> + ) -> Option<AnyTraitObject<'a, 'ctx, indirect::Mut, E>> where 'ctx: 'a, { diff --git a/tests/protocol_visitor_recoverable.rs b/tests/protocol_visitor_recoverable.rs index 2b8e6a1..3979110 100644 --- a/tests/protocol_visitor_recoverable.rs +++ b/tests/protocol_visitor_recoverable.rs @@ -1,7 +1,6 @@ use common::protocol::recoverable::MockRecoverableVisitor; use treaty::{ any::OwnedStatic, - effect::blocking::Blocking, protocol::{ visitor::{Recoverable, ValueProto, VisitResult}, DynVisitor, @@ -9,7 +8,9 @@ use treaty::{ Flow, Status, }; -use crate::common::{builder::MockBuilder, protocol::recoverable::MockRecoverableScopeVisitor}; +use crate::common::{ + builder::MockBuilder, protocol::recoverable::MockRecoverableScopeVisitor, Blocking, +}; mod common; @@ -20,16 +21,16 @@ fn recoverable_can_be_visited() { // Expect a visit using the rescoverable protocol. mock.expect_visit().once().returning(|scope| { - let mut visitor = MockBuilder::<(), (), ()>::new(); + let mut visitor = MockBuilder::<(), (), (), Blocking>::new(); // Expect that the visitor gets used. visitor.expect_traits().times(2).return_const(None); // Attempt to walk once. - assert_eq!(scope.new_walk(DynVisitor(&mut visitor)).value(), Status::Ok); + assert_eq!(scope.new_walk(DynVisitor(&mut visitor)).into_value(), Status::Ok); // Attempt to walk twice. - assert_eq!(scope.new_walk(DynVisitor(&mut visitor)).value(), Status::Ok); + assert_eq!(scope.new_walk(DynVisitor(&mut visitor)).into_value(), Status::Ok); // We are done. VisitResult::Control(Flow::Done) @@ -51,7 +52,7 @@ fn recoverable_can_be_visited() { // Visit using the recoverable protocol. assert!(matches!( - visitor.visit(&mut scope).value(), + visitor.visit(&mut scope).into_value(), VisitResult::Control(Flow::Done) )); } diff --git a/tests/protocol_visitor_request_hint.rs b/tests/protocol_visitor_request_hint.rs index 098e24d..40634ac 100644 --- a/tests/protocol_visitor_request_hint.rs +++ b/tests/protocol_visitor_request_hint.rs @@ -7,7 +7,6 @@ use common::{ use mockall::predicate::eq; use treaty::{ any::{OwnedStatic, TypeNameId}, - effect::blocking::Blocking, protocol::{ visitor::{RequestHint, RequestHintProto, ValueKnown, ValueProto, VisitResult}, walker::hint::HintProto, @@ -16,7 +15,7 @@ use treaty::{ Flow, }; -use crate::common::protocol::hint::KnownFactory; +use crate::common::{protocol::hint::KnownFactory, Blocking}; mod common; @@ -33,7 +32,7 @@ fn hints_can_be_requested() { // Get the known for the value protocol. assert_eq!( - obj.known(&()).value(), + obj.known(&()).into_value(), Ok(ValueKnown { preview: Some(&OwnedStatic(42)) }) @@ -46,13 +45,13 @@ fn hints_can_be_requested() { // This mock becomes the visitor. let visitor: &mut dyn RequestHint<Blocking> = &mut mock; - let mut mock = MockWalker::<(), ()>::new(); + let mut mock = MockWalker::<(), (), Blocking>::new(); // The visitor will lookup the value protocol on the walker. mock.expect_traits_mut() .once() .with(eq(TypeNameId::of::< - HintProto<ValueProto<OwnedStatic<i32>, Blocking>>, + HintProto<ValueProto<OwnedStatic<i32>, Blocking>>, Blocking >())) .returning(|_id| { let mut mock = MockHintWalker::<ValueProto<OwnedStatic<i32>, Blocking>>::new(); @@ -71,7 +70,7 @@ fn hints_can_be_requested() { // Request a hint from the visitor. assert!(matches!( - visitor.request_hint(DynWalker(&mut mock)).value(), + visitor.request_hint(DynWalker(&mut mock)).into_value(), VisitResult::Control(Flow::Done) )); } @@ -82,7 +81,7 @@ fn request_hint_proto() { let id = TypeId::of::<RequestHintProto<Blocking>>(); // The type id for the lifetime containing value protocol trait object. - let name_id = TypeNameId::of_lower::<dyn RequestHint<Blocking> + Send + Sync>(); + let name_id = TypeNameId::of_lower::<dyn RequestHint<Blocking>, Blocking>(); // They should be the same. assert_eq!(id, name_id.into_type_id()); diff --git a/tests/protocol_visitor_sequence.rs b/tests/protocol_visitor_sequence.rs index bc29ea4..4b3e7ca 100644 --- a/tests/protocol_visitor_sequence.rs +++ b/tests/protocol_visitor_sequence.rs @@ -3,7 +3,6 @@ use std::any::TypeId; use common::protocol::sequence::{MockSequenceScope, MockSequenceVisitor}; use treaty::{ any::{OwnedStatic, TypeNameId}, - effect::blocking::Blocking, protocol::{ visitor::{Sequence, SequenceProto, ValueProto, VisitResult}, DynVisitor, @@ -11,7 +10,7 @@ use treaty::{ Flow, }; -use crate::common::builder::MockBuilder; +use crate::common::{builder::MockBuilder, Blocking}; mod common; @@ -22,15 +21,15 @@ fn sequence_has_scope_with_size_hint_and_next() { // Expect a visit with the sequence protocol. mock.expect_visit().once().returning(|scope| { // Get the size hint from the sequence scope. - assert_eq!(scope.size_hint().value(), (1, Some(1))); + assert_eq!(scope.size_hint().into_value(), (1, Some(1))); - let mut visitor = MockBuilder::<(), (), ()>::new(); + let mut visitor = MockBuilder::<(), (), (), Blocking>::new(); // Expect the walker to lookup a trait. visitor.expect_traits().once().return_const(None); // Get the next item in the sequence from the walker. - assert_eq!(scope.next(DynVisitor(&mut visitor)).value(), Flow::Done); + assert_eq!(scope.next(DynVisitor(&mut visitor)).into_value(), Flow::Done); // We are done. VisitResult::Control(Flow::Done) @@ -57,7 +56,7 @@ fn sequence_has_scope_with_size_hint_and_next() { // Visit a sequence. assert!(matches!( - visitor.visit(&mut scope).value(), + visitor.visit(&mut scope).into_value(), VisitResult::Control(Flow::Done) )); } @@ -68,7 +67,7 @@ fn sequence_proto() { let id = TypeId::of::<SequenceProto<Blocking>>(); // The type id for the lifetime containing value protocol trait object. - let name_id = TypeNameId::of_lower::<dyn Sequence<Blocking> + Send + Sync>(); + let name_id = TypeNameId::of_lower::<dyn Sequence<Blocking>, Blocking>(); // They should be the same. assert_eq!(id, name_id.into_type_id()); diff --git a/tests/protocol_visitor_tag.rs b/tests/protocol_visitor_tag.rs index fa1cfd3..544f4c2 100644 --- a/tests/protocol_visitor_tag.rs +++ b/tests/protocol_visitor_tag.rs @@ -3,7 +3,6 @@ use std::any::TypeId; use common::protocol::tag::MockTagVisitor; use treaty::{ any::{OwnedStatic, TypeNameId}, - effect::blocking::Blocking, protocol::{ visitor::{Tag, TagConst, TagDyn, TagProto, ValueProto, VisitResult}, DynVisitor, @@ -12,7 +11,7 @@ use treaty::{ DynWalkerAdapter, Flow, }; -use crate::common::{builder::MockBuilder, walker::MockWalker}; +use crate::common::{builder::MockBuilder, walker::MockWalker, Blocking}; mod common; @@ -28,13 +27,13 @@ fn tag_can_be_visited() { // The kind should be test. assert_eq!(kind, Symbol::new("test")); - let mut builder = MockBuilder::<(), (), ()>::new(); + let mut builder = MockBuilder::<(), (), (), Blocking>::new(); // Expect that the builder is attempted to be used by the walker for the value. builder.expect_traits().once().return_const(None); // Walk the value of the tag. - assert_eq!(walker.walk(DynVisitor(&mut builder)).value(), Flow::Done); + assert_eq!(walker.walk(DynVisitor(&mut builder)).into_value(), Flow::Done); // We are done. VisitResult::Control(Flow::Done) @@ -43,7 +42,7 @@ fn tag_can_be_visited() { // Use the tag protocol trait. let visitor: &mut dyn Tag<TagDyn, Blocking> = &mut mock; - let mut walker = MockWalker::<(), ()>::new(); + let mut walker = MockWalker::<(), (), Blocking>::new(); // Expect the tag value to be walked. walker.expect_walk().once().returning(|visitor| { @@ -62,7 +61,7 @@ fn tag_can_be_visited() { assert!(matches!( visitor .visit(TagDyn(Symbol::new("test")), &mut walker) - .value(), + .into_value(), VisitResult::Control(Flow::Done) )); } @@ -76,13 +75,13 @@ fn const_tag_can_be_visited() { // Expect a visit with the tag protocol. mock.expect_visit().once().returning(|TagConst, walker| { - let mut builder = MockBuilder::<(), (), ()>::new(); + let mut builder = MockBuilder::<(), (), (), Blocking>::new(); // Expect that the builder is attempted to be used by the walker for the value. builder.expect_traits().once().return_const(None); // Walk the value of the tag. - assert_eq!(walker.walk(DynVisitor(&mut builder)).value(), Flow::Done); + assert_eq!(walker.walk(DynVisitor(&mut builder)).into_value(), Flow::Done); // We are done. VisitResult::Control(Flow::Done) @@ -91,7 +90,7 @@ fn const_tag_can_be_visited() { // Use the tag protocol trait. let visitor: &mut dyn Tag<TagConst<TEST>, Blocking> = &mut mock; - let mut walker = MockWalker::<(), ()>::new(); + let mut walker = MockWalker::<(), (), Blocking>::new(); // Expect the tag value to be walked. walker.expect_walk().once().returning(|visitor| { @@ -108,7 +107,7 @@ fn const_tag_can_be_visited() { // Visit the tag protocol for kind test with the value walker. assert!(matches!( - visitor.visit(TagConst, &mut walker).value(), + visitor.visit(TagConst, &mut walker).into_value(), VisitResult::Control(Flow::Done) )); } @@ -119,7 +118,7 @@ fn tag_proto() { let id = TypeId::of::<TagProto<TagDyn, Blocking>>(); // The type id for the lifetime containing value protocol trait object. - let name_id = TypeNameId::of_lower::<dyn Tag<TagDyn, Blocking> + Send + Sync>(); + let name_id = TypeNameId::of_lower::<dyn Tag<TagDyn, Blocking>, Blocking>(); // They should be the same. assert_eq!(id, name_id.into_type_id()); diff --git a/tests/protocol_visitor_value.rs b/tests/protocol_visitor_value.rs index 821b9f6..cd835ea 100644 --- a/tests/protocol_visitor_value.rs +++ b/tests/protocol_visitor_value.rs @@ -4,13 +4,13 @@ use common::protocol::{ hint::{KnownFactory, MockHintWalker}, value::MockValueVisitor, }; +use effectful::is_send_sync; use mockall::predicate::eq; use treaty::{ any::{ AnyTrait, BorrowedStatic, BorrowedStaticHrt, OwnedStatic, TempBorrowedMutStatic, TempBorrowedMutStaticHrt, TypeNameId, }, - effect::blocking::Blocking, protocol::{ visitor::{visit_value, Value, ValueKnown, ValueProto, VisitResult}, walker::hint::Hint, @@ -19,6 +19,8 @@ use treaty::{ Flow, }; +use crate::common::Blocking; + mod common; /// Tests support for custom type support in the value protocol. @@ -30,6 +32,8 @@ fn custom_value_type() { #[derive(PartialEq, Debug, Clone)] struct MyValue; + is_send_sync!(MyValue); + let mut mock = MockValueVisitor::<OwnedStatic<MyValue>, Blocking>::new(); // Expect the visit method to be called once with the custom type. @@ -43,14 +47,14 @@ fn custom_value_type() { let visitor: &mut dyn Value<OwnedStatic<MyValue>, Blocking> = &mut mock; // Visit the value. - let result = visitor.visit(OwnedStatic(MyValue)).value(); + let result = visitor.visit(OwnedStatic(MyValue)).into_value(); // The mock returns that it is done. assert_eq!(result, VisitResult::Control(Flow::Done)); - let visitor: &mut (dyn AnyTrait + Send + Sync) = &mut mock; + let visitor: &mut dyn AnyTrait<Blocking> = &mut mock; assert_eq!( - visit_value::<_, Blocking>(DynVisitor(visitor), OwnedStatic(MyValue)).value(), + visit_value::<_, Blocking>(DynVisitor(visitor), OwnedStatic(MyValue)).into_value(), VisitResult::Control(Flow::Done) ); } @@ -83,13 +87,13 @@ fn borrowed_value() { // Visit the borrowed value. assert_eq!( - visitor.visit(BorrowedStatic(value)).value(), + visitor.visit(BorrowedStatic(value)).into_value(), Flow::Done.into() ); - let visitor: &mut (dyn AnyTrait + Send + Sync) = &mut mock; + let visitor: &mut dyn AnyTrait<Blocking> = &mut mock; assert_eq!( - visit_value::<_, Blocking>(DynVisitor(visitor), BorrowedStatic(value)).value(), + visit_value::<_, Blocking>(DynVisitor(visitor), BorrowedStatic(value)).into_value(), VisitResult::Control(Flow::Done) ); } @@ -130,7 +134,7 @@ fn temp_borrowed_value() { // Visit the context to show we can shorten the lifetime. // This would also force the lifetime to be to long if this wasn't the Temp form. assert_eq!( - visitor.visit(TempBorrowedMutStatic(value)).value(), + visitor.visit(TempBorrowedMutStatic(value)).into_value(), Flow::Done.into() ); @@ -141,7 +145,7 @@ fn temp_borrowed_value() { // Visit the temp value. assert_eq!( - visitor.visit(TempBorrowedMutStatic(&mut value)).value(), + visitor.visit(TempBorrowedMutStatic(&mut value)).into_value(), Flow::Done.into() ); } @@ -183,19 +187,19 @@ fn all_visit_results() { // Visit can return a done. assert_eq!( - visitor.visit(OwnedStatic(0)).value(), + visitor.visit(OwnedStatic(0)).into_value(), VisitResult::Control(Flow::Done) ); // Visit can return an error signal. assert_eq!( - visitor.visit(OwnedStatic(1)).value(), + visitor.visit(OwnedStatic(1)).into_value(), VisitResult::Control(Flow::Err) ); // Visit can return a continue. assert_eq!( - visitor.visit(OwnedStatic(2)).value(), + visitor.visit(OwnedStatic(2)).into_value(), VisitResult::Control(Flow::Continue) ); @@ -203,7 +207,7 @@ fn all_visit_results() { // This is for runtime visit support checking. // The value should be given back, but that's not forced. assert_eq!( - visitor.visit(OwnedStatic(3)).value(), + visitor.visit(OwnedStatic(3)).into_value(), VisitResult::Skipped(OwnedStatic(3)) ); } @@ -215,7 +219,7 @@ fn value_proto() { let id = TypeId::of::<ValueProto<OwnedStatic<i32>, Blocking>>(); // The type id for the lifetime containing value protocol trait object. - let name_id = TypeNameId::of_lower::<dyn Value<OwnedStatic<i32>, Blocking> + Send + Sync>(); + let name_id = TypeNameId::of_lower::<dyn Value<OwnedStatic<i32>, Blocking>, Blocking>(); // They should be the same. assert_eq!(id, name_id.into_type_id()); @@ -241,7 +245,7 @@ fn as_hint() { // The value protocol has no hint data, and it has no known data. assert_eq!( - walker.known(&()).value(), + walker.known(&()).into_value(), Ok(ValueKnown { preview: Some(&OwnedStatic(42)) }) @@ -263,7 +267,7 @@ fn as_hint() { // The value protocol has no hint data, and it has no known data. assert_eq!( - walker.known(&()).value(), + walker.known(&()).into_value(), Ok(ValueKnown { preview: Some(&BorrowedStatic(&42)) }) @@ -281,6 +285,6 @@ fn as_hint() { let walker: &mut dyn Hint<ValueProto<TempBorrowedMutStaticHrt<i32>, Blocking>> = &mut mock; // The value protocol has no hint data, and it has no known data. - assert_eq!(walker.known(&()).value(), Ok(ValueKnown { preview: None })); + assert_eq!(walker.known(&()).into_value(), Ok(ValueKnown { preview: None })); } } diff --git a/tests/protocol_walker_hint.rs b/tests/protocol_walker_hint.rs index 40c48e5..0751a11 100644 --- a/tests/protocol_walker_hint.rs +++ b/tests/protocol_walker_hint.rs @@ -1,11 +1,13 @@ use std::any::TypeId; +use effectful::is_send_sync; use treaty::{ any::{TypeName, TypeNameId}, - effect::blocking::Blocking, protocol::walker::hint::{self, HintMeta, HintProto}, }; +use crate::common::Blocking; + mod common; // /// This tests for the hint protocol being able to give the known info and being able to hint. @@ -302,11 +304,13 @@ mod common; fn hint_proto() { struct MyProtocol; - impl<'a, 'ctx> TypeName::MemberTypeForLt<'a, 'ctx, &'a &'ctx ()> for MyProtocol { + is_send_sync!(MyProtocol); + + impl<'a, 'ctx> TypeName::MemberTypeForLt<'a, 'ctx, Blocking, &'a &'ctx ()> for MyProtocol { type T = MyProtocol; } - impl<'a, 'ctx> TypeName::LowerTypeWithBound<'a, 'ctx, &'a &'ctx ()> for MyProtocol { + impl<'a, 'ctx> TypeName::LowerTypeWithBound<'a, 'ctx, Blocking, &'a &'ctx ()> for MyProtocol { type Higher = MyProtocol; } @@ -320,7 +324,7 @@ fn hint_proto() { let id = TypeId::of::<HintProto<MyProtocol>>(); // The type id for the lifetime containing value protocol trait object. - let name_id = TypeNameId::of_lower::<dyn hint::Hint<MyProtocol> + Send + Sync>(); + let name_id = TypeNameId::of_lower::<dyn hint::Hint<MyProtocol>, Blocking>(); // They should be the same. assert_eq!(id, name_id.into_type_id()); diff --git a/tests/walker_struct.rs b/tests/walker_struct.rs index cf09be1..160e9b0 100644 --- a/tests/walker_struct.rs +++ b/tests/walker_struct.rs @@ -1,7 +1,9 @@ +use effectful::{ + bound::ForceDynamic, effective::Effective, environment::{Environment, NativeForm}, is_send_sync +}; use mockall::predicate::eq; use treaty::{ any::{BorrowedStatic, BorrowedStaticHrt, OwnedStatic, StaticType, TypeNameId}, - effect::{blocking::Blocking, Effect, Effective, ErasedEffective}, protocol::{ visitor::{tags, SequenceProto, TagConst, TagProto, ValueProto, VisitResult}, AsVisitor, DynVisitor, @@ -13,6 +15,7 @@ use treaty::{ use crate::common::{ builder::{EmptyError, MockBuilder}, protocol::{sequence::MockSequenceVisitor, tag::MockTagVisitor, value::MockValueVisitor}, + Blocking, }; mod common; @@ -22,10 +25,12 @@ struct X { b: i32, } +is_send_sync!(X); + struct Info; // This gives the struct walker enough information to walk the X struct. -impl<'ctx, M, E: Effect> StructTypeInfo<'ctx, M, E> for Info { +impl<'ctx, M, E: Environment> StructTypeInfo<'ctx, M, E> for Info { const NAME: &'static str = "X"; const FIELDS: &'static [&'static str] = &["a", "b"]; @@ -39,9 +44,9 @@ impl<'ctx, M, E: Effect> StructTypeInfo<'ctx, M, E> for Info { fn walk_field<'a>( index: usize, value: &'ctx Self::T, - mut visitor: DynVisitor<'a, 'ctx>, - ) -> ErasedEffective<'a, Result<Flow, Self::FieldError>, E> { - E::from_future(async move { + mut visitor: DynVisitor<'a, 'ctx, E>, + ) -> NativeForm<'a, Result<Flow, Self::FieldError>, E> { + E::future(unsafe { ForceDynamic::new(async move { match index { // A real impl would be expected to tag these values with the field name. 0 => { @@ -76,7 +81,8 @@ impl<'ctx, M, E: Effect> StructTypeInfo<'ctx, M, E> for Info { } _ => Ok(Flow::Done), } - }) + })}) + .cast() } } @@ -92,32 +98,33 @@ fn sequence_of_field_values() { // The struct walker using the info we provided about the struct. let walker = StructWalker::<Info, _, DefaultMode, Blocking>::new(&value); - let mut builder = MockBuilder::<(), (), EmptyError>::new(); + let mut builder = MockBuilder::<(), (), EmptyError, Blocking>::new(); // Expect a visit on the sequence protocol for the struct fields. builder .expect_traits_mut() .once() - .with(eq(TypeNameId::of::<SequenceProto<Blocking>>())) + .with(eq(TypeNameId::of::<SequenceProto<Blocking>, Blocking>())) .returning(|_| { let mut visitor = MockSequenceVisitor::<Blocking>::new(); // Expect the sequence visitor to be used. visitor.expect_visit().once().returning(|scope| { // The struct should have exactly 2 fields. - assert_eq!(scope.size_hint().value(), (2, Some(2))); + assert_eq!(scope.size_hint().into_value(), (2, Some(2))); // Get the first field value. { - let mut visitor = MockBuilder::<(), (), EmptyError>::new(); + let mut visitor = MockBuilder::<(), (), EmptyError, Blocking>::new(); // Expect a bool value for the field. visitor .expect_traits_mut() .once() - .with(eq( - TypeNameId::of::<ValueProto<OwnedStatic<bool>, Blocking>>(), - )) + .with(eq(TypeNameId::of::< + ValueProto<OwnedStatic<bool>, Blocking>, + Blocking, + >())) .returning(|_| { let mut visitor = MockValueVisitor::<OwnedStatic<bool>, Blocking>::new(); @@ -133,21 +140,21 @@ fn sequence_of_field_values() { }); assert_eq!( - scope.next(AsVisitor::as_visitor(&mut visitor)).value(), + scope.next(AsVisitor::as_visitor(&mut visitor)).into_value(), Flow::Continue ); } // Get the second field value. { - let mut visitor = MockBuilder::<(), (), EmptyError>::new(); + let mut visitor = MockBuilder::<(), (), EmptyError, Blocking>::new(); // Expect a i32 value. visitor .expect_traits_mut() .once() .with(eq( - TypeNameId::of::<ValueProto<OwnedStatic<i32>, Blocking>>(), + TypeNameId::of::<ValueProto<OwnedStatic<i32>, Blocking>, Blocking>(), )) .returning(|_| { let mut visitor = MockValueVisitor::<OwnedStatic<i32>, Blocking>::new(); @@ -163,7 +170,7 @@ fn sequence_of_field_values() { }); assert_eq!( - scope.next(AsVisitor::as_visitor(&mut visitor)).value(), + scope.next(AsVisitor::as_visitor(&mut visitor)).into_value(), Flow::Done ); } @@ -180,7 +187,7 @@ fn sequence_of_field_values() { // Walk the struct. assert_eq!( - walker.walk(AsVisitor::as_visitor(&mut builder)).value(), + walker.walk(AsVisitor::as_visitor(&mut builder)).into_value(), Ok(()) ); } @@ -193,7 +200,7 @@ fn has_struct_tag() { // The struct walker using the info we provided about the struct. let walker = StructWalker::<Info, _, DefaultMode, Blocking>::new(&value); - let mut builder = MockBuilder::<(), (), EmptyError>::new(); + let mut builder = MockBuilder::<(), (), EmptyError, Blocking>::new(); let mut seq = mockall::Sequence::new(); @@ -209,15 +216,15 @@ fn has_struct_tag() { .expect_traits_mut() .once() .in_sequence(&mut seq) - .with(eq(TypeNameId::of::<TagProto<tags::Struct, Blocking>>())) + .with(eq(TypeNameId::of::<TagProto<tags::Struct, Blocking>, Blocking>())) .returning(|_| { let mut visitor = MockTagVisitor::<tags::Struct, Blocking>::new(); visitor.expect_visit().once().returning(|TagConst, walker| { - let mut visitor = MockBuilder::<(), (), ()>::new(); + let mut visitor = MockBuilder::<(), (), (), Blocking>::new(); // Walk the noop walker so there isn't an error. - assert_eq!(walker.walk(DynVisitor(&mut visitor)).value(), Flow::Done); + assert_eq!(walker.walk(DynVisitor(&mut visitor)).into_value(), Flow::Done); // We are done, the walker should now stop early. VisitResult::Control(Flow::Done) @@ -228,7 +235,7 @@ fn has_struct_tag() { // Walk the struct. assert_eq!( - walker.walk(AsVisitor::as_visitor(&mut builder)).value(), + walker.walk(AsVisitor::as_visitor(&mut builder)).into_value(), Ok(()) ); } @@ -241,7 +248,7 @@ fn has_map_backup_tag() { // The struct walker using the info we provided about the struct. let walker = StructWalker::<Info, _, DefaultMode, Blocking>::new(&value); - let mut builder = MockBuilder::<(), (), EmptyError>::new(); + let mut builder = MockBuilder::<(), (), EmptyError, Blocking>::new(); let mut seq = mockall::Sequence::new(); @@ -259,15 +266,15 @@ fn has_map_backup_tag() { .expect_traits_mut() .once() .in_sequence(&mut seq) - .with(eq(TypeNameId::of::<TagProto<tags::Map, Blocking>>())) + .with(eq(TypeNameId::of::<TagProto<tags::Map, Blocking>, Blocking>())) .returning(|_| { let mut visitor = MockTagVisitor::<tags::Map, Blocking>::new(); visitor.expect_visit().once().returning(|TagConst, walker| { - let mut visitor = MockBuilder::<(), (), ()>::new(); + let mut visitor = MockBuilder::<(), (), (), Blocking>::new(); // Walk the noop walker so there isn't an error. - assert_eq!(walker.walk(DynVisitor(&mut visitor)).value(), Flow::Done); + assert_eq!(walker.walk(DynVisitor(&mut visitor)).into_value(), Flow::Done); // We are done, the walker should now stop early. VisitResult::Control(Flow::Done) @@ -278,7 +285,7 @@ fn has_map_backup_tag() { // Walk the struct. assert_eq!( - walker.walk(AsVisitor::as_visitor(&mut builder)).value(), + walker.walk(AsVisitor::as_visitor(&mut builder)).into_value(), Ok(()) ); } @@ -291,7 +298,7 @@ fn borrowed_value_directly() { // The struct walker using the info we provided about the struct. let walker = StructWalker::<Info, _, DefaultMode, Blocking>::new(&value); - let mut builder = MockBuilder::<(), (), EmptyError>::new(); + let mut builder = MockBuilder::<(), (), EmptyError, Blocking>::new(); let mut seq = mockall::Sequence::new(); @@ -308,7 +315,7 @@ fn borrowed_value_directly() { .once() .in_sequence(&mut seq) .with(eq(TypeNameId::of::< - ValueProto<BorrowedStaticHrt<X>, Blocking>, + ValueProto<BorrowedStaticHrt<X>, Blocking>, Blocking >())) .returning(|_| { let mut visitor = MockValueVisitor::<BorrowedStaticHrt<X>, Blocking>::new(); @@ -331,7 +338,7 @@ fn borrowed_value_directly() { // Walk the struct. assert_eq!( - walker.walk(AsVisitor::as_visitor(&mut builder)).value(), + walker.walk(AsVisitor::as_visitor(&mut builder)).into_value(), Ok(()) ); } |