moved tests to integration tests and cleaned up effects some
41 files changed, 760 insertions, 1351 deletions
@@ -11,14 +11,12 @@ include = ["LICENSE-APACHE", "LICENSE-MIT", "README.md", "empty.rs"] [dependencies] serde = { version = "1.0", default-features = false, optional = true } -mockall = { version = "0.12.1", optional = true } [features] -default = ["std", "serde", "mock"] +default = ["std", "serde", "better_errors"] std = ["alloc", "serde?/std"] alloc = ["serde?/alloc"] serde = ["dep:serde"] -mock = ["std", "dep:mockall"] better_errors = [] [dev-dependencies] @@ -6,7 +6,7 @@ pub mod indirect; pub mod static_wrapper; mod type_name_id; -use crate::{bijective_higher_ranked_trait, bijective_higher_ranked_type}; +use crate::{bijective_higher_ranked_trait, bijective_higher_ranked_type, hkt::Invariant}; use core::marker::PhantomData; pub use type_name_id::*; @@ -118,17 +118,18 @@ bijective_higher_ranked_type! { /// by `id` if [`AnyTrait`] had every trait as a super bound. /// /// ``` -/// use treaty::any::{AnyTrait, any_trait, nameable}; +/// use treaty::any::{AnyTrait, any_trait, WithContextLt, TypeName}; +/// use treaty::hkt::bijective_higher_ranked_type; /// /// // Create a test value. /// let my_num = MyNum(42); /// /// // Cast to be a AnyTrait trait object. /// // Now we don't know the type. -/// let anything: &dyn AnyTrait<'_> = &my_num; +/// let anything: &(dyn AnyTrait<'_> + Send) = &my_num; /// /// // We can still upcast to an impl of ToNum. -/// let to_num_object: &dyn ToNum = anything.upcast().unwrap(); +/// let to_num_object: &dyn ToNum = anything.upcast::<DynToNum>().unwrap(); /// /// assert_eq!(to_num_object.num(), 42); /// @@ -139,10 +140,15 @@ bijective_higher_ranked_type! { /// fn num(&self) -> i32; /// } /// +/// bijective_higher_ranked_type! { +/// for['ctx] type DynToNum[][]: WithContextLt['ctx][] +/// for<'a> (dyn ToNum + 'a) +/// } +/// /// // Make the trait object nameable. -/// nameable! { -/// struct Name['a, 'ctx]; -/// impl for dyn ToNum + 'a where { } +/// bijective_higher_ranked_type! { +/// type [][]: TypeName[][] +/// for<'ctx> (DynToNum) /// } /// /// // An example struct. @@ -159,7 +165,7 @@ bijective_higher_ranked_type! { /// // Here the only trait that can be looked up is ToNum as its the only /// // one in the list. /// any_trait! { -/// impl['a, 'ctx] MyNum = [dyn ToNum + 'a]; +/// impl['ctx] MyNum = [DynToNum] /// } /// ``` pub trait AnyTrait<'ctx> { @@ -346,15 +352,8 @@ pub struct AnyTraitObject<'a, 'ctx: 'a, I: Indirect<'a>> { /// This is some form of &T where T may be sized or not. indirect: RawIndirect<'a, I>, - /// Extra type information for the type system. - _marker: PhantomData<( - // Invariant over 'a and 'ctx, the TypeNameId doesn't track lifetimes so we have to do it - // here. - // https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns - fn(&'ctx ()) -> &'ctx (), - // Not Send or Sync. - *const (), - )>, + _lifetime: Invariant<'ctx>, + _not_send_sync: PhantomData<*const ()>, } impl<'a, 'ctx, I: Indirect<'a>> AnyTraitObject<'a, 'ctx, I> { @@ -368,7 +367,8 @@ impl<'a, 'ctx, I: Indirect<'a>> AnyTraitObject<'a, 'ctx, I> { Self { info: TypeNameId::of_lower::<T>, indirect: RawIndirect::new(indirect), - _marker: PhantomData, + _lifetime: Default::default(), + _not_send_sync: PhantomData, } } diff --git a/src/any/indirect.rs b/src/any/indirect.rs index eef24f0..ae70ef3 100644 --- a/src/any/indirect.rs +++ b/src/any/indirect.rs @@ -16,7 +16,7 @@ pub trait HigherKinded<'a> { pub trait Indirect<'a>: HigherKinded<'a> + sealed::Sealed<'a> {} pub(super) mod sealed { - use core::marker::PhantomData; + use crate::hkt::{Invariant, Marker}; use super::*; @@ -41,14 +41,16 @@ pub(super) mod sealed { #[repr(transparent)] pub struct RawIndirect<'a, I> { indirect: MaybeUninit<[u8; INDIRECT_SIZE]>, - _marker: PhantomData<fn(&'a ()) -> (&'a (), I)>, + _lifetime: Invariant<'a>, + _generic: Marker<I> } impl<'a, I: Indirect<'a>> RawIndirect<'a, I> { pub fn new<T: ?Sized>(indirect: I::ForT<T>) -> Self { Self { indirect: I::into_raw(indirect), - _marker: PhantomData, + _lifetime: Default::default(), + _generic: Default::default() } } diff --git a/src/any/static_wrapper.rs b/src/any/static_wrapper.rs index 4b238b9..c99b037 100644 --- a/src/any/static_wrapper.rs +++ b/src/any/static_wrapper.rs @@ -7,19 +7,14 @@ use super::*; #[repr(transparent)] pub struct OwnedStatic<T: ?Sized>(pub T); -/// Higher ranked type for [`OwnedStatic`]. -pub struct DynOwnedStatic<T: ?Sized>(PhantomData<fn() -> *const T>); - -impl<'a, 'ctx, T: ?Sized + 'ctx> WithContextLt::LowerForLt<'a, 'ctx, &'a (&'ctx (),)> - for DynOwnedStatic<T> -{ - type T = OwnedStatic<T>; -} - -impl<'a, 'ctx, T: ?Sized + 'ctx> WithContextLt::RaiseForLt<'a, 'ctx, &'a (&'ctx (),)> - for OwnedStatic<T> -{ - type HigherRanked = DynOwnedStatic<T>; +bijective_higher_ranked_type! { + /// Higher ranked type for [`OwnedStatic`]. + pub for['ctx] type DynOwnedStatic[][T]: WithContextLt['ctx][] + for<'a> + (OwnedStatic<T>) + where { + T: ?Sized + 'ctx, + } } bijective_higher_ranked_type! { @@ -128,22 +123,15 @@ bijective_higher_ranked_type! { #[repr(transparent)] pub struct BoxedStatic<T: ?Sized>(pub Box<T>); -/// Higher ranked type for [`BoxedStatic`]. -#[cfg(feature = "alloc")] -pub struct DynBoxedStatic<T: ?Sized>(PhantomData<fn() -> *const T>); - #[cfg(feature = "alloc")] -impl<'a, 'ctx, T: ?Sized + 'ctx> WithContextLt::LowerForLt<'a, 'ctx, &'a (&'ctx (),)> - for DynBoxedStatic<T> -{ - type T = BoxedStatic<T>; -} - -#[cfg(feature = "alloc")] -impl<'a, 'ctx, T: ?Sized + 'ctx> WithContextLt::RaiseForLt<'a, 'ctx, &'a (&'ctx (),)> - for BoxedStatic<T> -{ - type HigherRanked = DynBoxedStatic<T>; +bijective_higher_ranked_type! { + /// Higher ranked type for [`BoxedStatic`]. + pub for['ctx] type DynBoxedStatic[][T]: WithContextLt['ctx][] + for<'a> + (BoxedStatic<T>) + where { + T: ?Sized + 'ctx, + } } #[cfg(feature = "alloc")] diff --git a/src/any/type_name_id.rs b/src/any/type_name_id.rs index 5198073..2ba7ffc 100644 --- a/src/any/type_name_id.rs +++ b/src/any/type_name_id.rs @@ -88,7 +88,7 @@ impl Eq for TypeNameId {} impl PartialOrd for TypeNameId { fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { - self.name_id.partial_cmp(&other.name_id) + Some(self.name_id.cmp(&other.name_id)) } } diff --git a/src/build.rs b/src/build.rs index 24232a0..d77bb39 100644 --- a/src/build.rs +++ b/src/build.rs @@ -6,7 +6,7 @@ use crate::{ }; /// A buildable type. -pub trait Build<'ctx, M, E: Effect<'ctx>>: BuilderTypes<Value = Self> + Send { +pub trait Build<'ctx, M, E: Effect>: BuilderTypes<Value = Self> + Send { /// The builder that can be used to build a value of `Self`. type Builder: Builder<'ctx, E, Seed = Self::Seed, Error = Self::Error, Value = Self>; } @@ -34,8 +34,8 @@ pub trait BuilderTypes { /// 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: Effect<'ctx>>: BuilderTypes + Sized + Send { - fn from_seed<'a>(seed: Self::Seed) -> Future<'a, 'ctx, Self, E> +pub trait Builder<'ctx, E: Effect>: BuilderTypes + Sized + Send { + fn from_seed<'a>(seed: Self::Seed) -> Future<'a, Self, E> where Self: 'a; @@ -43,7 +43,7 @@ pub trait Builder<'ctx, E: Effect<'ctx>>: BuilderTypes + Sized + Send { /// /// If an error happened with the builder during the walk /// it will be reported here. - fn build<'a>(self) -> Future<'a, 'ctx, Result<Self::Value, Self::Error>, E> + fn build<'a>(self) -> Future<'a, Result<Self::Value, Self::Error>, E> where Self: 'a; diff --git a/src/build/builders/core/bool.rs b/src/build/builders/core/bool.rs index 208e88b..fd41ed6 100644 --- a/src/build/builders/core/bool.rs +++ b/src/build/builders/core/bool.rs @@ -1,4 +1,4 @@ -use core::{marker::PhantomData, ops::ControlFlow}; +use core::marker::PhantomData; use crate::{ any::static_wrapper::{DynOwnedStatic, OwnedStatic}, @@ -11,7 +11,7 @@ use crate::{ Flow, }; -impl<'ctx, M, E: Effect<'ctx>> crate::Build<'ctx, M, E> for bool { +impl<'ctx, M, E: Effect> crate::Build<'ctx, M, E> for bool { type Builder = Builder<E>; } @@ -38,16 +38,16 @@ impl<E> crate::BuilderTypes for Builder<E> { type Seed = (); } -impl<'ctx, E: Effect<'ctx>> crate::Builder<'ctx, E> for Builder<E> { +impl<'ctx, E: Effect> crate::Builder<'ctx, E> for Builder<E> { #[inline] - fn build<'a>(self) -> Future<'a, 'ctx, Result<Self::Value, Self::Error>, E> + fn build<'a>(self) -> Future<'a, Result<Self::Value, Self::Error>, E> where Self: 'a, { E::wrap(core::future::ready(self.0.ok_or(Error::Incomplete))) } - fn from_seed<'a>(_seed: Self::Seed) -> Future<'a, 'ctx, Self, E> + fn from_seed<'a>(_seed: Self::Seed) -> Future<'a, Self, E> where Self: 'a, { @@ -62,12 +62,15 @@ impl<'ctx, E: Effect<'ctx>> crate::Builder<'ctx, E> for Builder<E> { any_trait! { impl['ctx, E] Builder<E> = [ DynValue<'ctx, DynOwnedStatic<bool>, E>, - ] where E: Effect<'ctx> + ] where E: Effect } -impl<'ctx, E: Effect<'ctx>> Value<'ctx, DynOwnedStatic<bool>, E> for Builder<E> { +impl<'ctx, E: Effect> Value<'ctx, DynOwnedStatic<bool>, E> for Builder<E> { #[inline] - fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Future<'a, 'ctx, Flow, E> { + fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Future<'a, Flow, E> + where + 'ctx: 'a + { self.0 = Some(value); E::ready(Flow::Continue) } diff --git a/src/build/builders/debug.rs b/src/build/builders/debug.rs index 54efc96..68d9de6 100644 --- a/src/build/builders/debug.rs +++ b/src/build/builders/debug.rs @@ -1,13 +1,9 @@ -use core::{any::TypeId, marker::PhantomData, ops::ControlFlow}; +use core::{any::TypeId, marker::PhantomData}; use crate::{ - any::{ - static_wrapper::{DynOwnedStatic, OwnedStatic}, - TypeNameId, - }, + any::static_wrapper::{DynOwnedStatic, OwnedStatic}, any_trait, effect::{Effect, Future}, - never::Never, protocol::{ self, visitor::{ @@ -38,10 +34,16 @@ any_trait! { let id; println!("Unknown trait: {:?}", id); None - } where E: Effect<'ctx> + } where E: Effect +} + +impl<E: Effect> Default for Visitor<E> { + fn default() -> Self { + Self::new() + } } -impl<'ctx, E: Effect<'ctx>> Visitor<E> { +impl<E: Effect> Visitor<E> { pub fn new() -> Self { Self(0, PhantomData) } @@ -56,11 +58,11 @@ impl<'ctx, E: Effect<'ctx>> Visitor<E> { } } -impl<'ctx, E: Effect<'ctx>> RequestHint<'ctx, E> for Visitor<E> { +impl<'ctx, E: Effect> RequestHint<'ctx, E> for Visitor<E> { fn request_hint<'a>( &'a mut self, _walker: crate::protocol::Walker<'a, 'ctx>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { // self.tab(); // println!("Visit request hint (no hint given)"); // println!("Visit request hint (hint for recoverable)"); @@ -68,12 +70,12 @@ impl<'ctx, E: Effect<'ctx>> RequestHint<'ctx, E> for Visitor<E> { } } -impl<'ctx, E: Effect<'ctx>> Tag<'ctx, TagDyn, E> for Visitor<E> { +impl<'ctx, E: Effect> Tag<'ctx, TagDyn, E> for Visitor<E> { fn visit<'a>( &'a mut self, kind: TagDyn, walker: DynWalker<'a, 'ctx, E>, - ) -> Future<'a, 'ctx, Status, E> { + ) -> Future<'a, Status, E> { E::wrap(async move { match kind.0 { crate::TAG_TYPE_NAME => { @@ -81,7 +83,7 @@ impl<'ctx, E: Effect<'ctx>> Tag<'ctx, TagDyn, E> for Visitor<E> { println!("type name:"); self.0 += 1; - walker.walk(self).await; + let _ = walker.walk(self).await; self.0 -= 1; Status::r#continue() @@ -91,7 +93,7 @@ impl<'ctx, E: Effect<'ctx>> Tag<'ctx, TagDyn, E> for Visitor<E> { println!("key:"); self.0 += 1; - walker.walk(self).await; + let _ = walker.walk(self).await; self.0 -= 1; Status::r#continue() @@ -101,7 +103,7 @@ impl<'ctx, E: Effect<'ctx>> Tag<'ctx, TagDyn, E> for Visitor<E> { println!("value:"); self.0 += 1; - walker.walk(self).await; + let _ = walker.walk(self).await; self.0 -= 1; Status::r#continue() @@ -112,63 +114,71 @@ impl<'ctx, E: Effect<'ctx>> Tag<'ctx, TagDyn, E> for Visitor<E> { } } -impl<'ctx, E: Effect<'ctx>> Value<'ctx, DynOwnedStatic<&'static str>, E> for Visitor<E> { +impl<'ctx, E: Effect> Value<'ctx, DynOwnedStatic<&'static str>, E> for Visitor<E> { fn visit<'a>( &'a mut self, OwnedStatic(value): OwnedStatic<&'static str>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> + where + 'ctx: 'a + { self.tab(); println!("{:?}", value); E::ready(Flow::Continue) } } -impl<'ctx, E: Effect<'ctx>> Value<'ctx, DynOwnedStatic<usize>, E> for Visitor<E> { +impl<'ctx, E: Effect> Value<'ctx, DynOwnedStatic<usize>, E> for Visitor<E> { fn visit<'a>( &'a mut self, OwnedStatic(value): OwnedStatic<usize>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> + where + 'ctx: 'a { self.tab(); println!("{}", value); E::ready(Flow::Continue) } } -impl<'ctx, E: Effect<'ctx>> Value<'ctx, DynOwnedStatic<bool>, E> for Visitor<E> { - fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Future<'a, 'ctx, Flow, E> { +impl<'ctx, E: Effect> Value<'ctx, DynOwnedStatic<bool>, E> for Visitor<E> { + fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Future<'a, Flow, E> + where 'ctx: 'a{ self.tab(); println!("{}", value); E::ready(Flow::Continue) } } -impl<'ctx, E: Effect<'ctx>> Value<'ctx, DynOwnedStatic<&'static [&'static str]>, E> for Visitor<E> { +impl<'ctx, E: Effect> Value<'ctx, DynOwnedStatic<&'static [&'static str]>, E> for Visitor<E> { fn visit<'a>( &'a mut self, OwnedStatic(value): OwnedStatic<&'static [&'static str]>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> + where 'ctx: 'a{ self.tab(); println!("{:?}", value); E::ready(Flow::Continue) } } -impl<'ctx, E: Effect<'ctx>> Value<'ctx, DynOwnedStatic<TypeId>, E> for Visitor<E> { +impl<'ctx, E: Effect> Value<'ctx, DynOwnedStatic<TypeId>, E> for Visitor<E> { fn visit<'a>( &'a mut self, OwnedStatic(value): OwnedStatic<TypeId>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> + where 'ctx: 'a{ self.tab(); println!("Visit type ID: {:?}", value); E::ready(Flow::Continue) } } -impl<'ctx, E: Effect<'ctx>> Sequence<'ctx, E> for Visitor<E> { +impl<'ctx, E: Effect> Sequence<'ctx, E> for Visitor<E> { fn visit<'a>( &'a mut self, scope: protocol::visitor::sequence::DynSequenceScope<'a, 'ctx, E>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { E::wrap(async { self.tab(); println!("sequence{:?}", scope.size_hint().await); diff --git a/src/effect.rs b/src/effect.rs index b52f94a..71e4aec 100644 --- a/src/effect.rs +++ b/src/effect.rs @@ -5,33 +5,30 @@ use core::{ task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, }; -use crate::{higher_ranked_trait, higher_ranked_type}; +use crate::{bijective_higher_ranked_type, bijective_higher_ranked_trait}; -higher_ranked_trait! { - pub type class SendFuture['ctx, Output]: [for<'lt> core::future::Future<Output = Output> + Send + 'lt] +bijective_higher_ranked_trait! { + pub type class SendFuture[][Output]: [for<'lt> core::future::Future<Output = Output> + Sized + Send + 'lt] where { Output: Send, } - for where { - Output: 'lt, - } } /// Trait for effects. -pub trait Effect<'ctx>: Send + 'static { - type Future<T: Send>: SendFuture::Trait<'ctx, T>; +pub trait Effect: Send + 'static { + type Future<T: Send>: SendFuture::MemberType<T>; - fn wrap<'a, F>(future: F) -> SendFuture::T<'a, 'ctx, Self::Future<F::Output>, F::Output> + fn wrap<'a, F>(future: F) -> SendFuture::T<'a, Self::Future<F::Output>, F::Output> where F: core::future::Future + Send + 'a, <F as core::future::Future>::Output: Send; - fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, 'ctx, Self::Future<T>, T>; + fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, Self::Future<T>, T>; fn map<'a, T, U, F>( - future: SendFuture::T<'a, 'ctx, Self::Future<T>, T>, + future: SendFuture::T<'a, Self::Future<T>, T>, func: F, - ) -> SendFuture::T<'a, 'ctx, Self::Future<U>, U> + ) -> SendFuture::T<'a, Self::Future<U>, U> where T: Send, U: Send, @@ -41,7 +38,7 @@ pub trait Effect<'ctx>: Send + 'static { #[inline] fn wrap_boxed<'a, F>( future: core::pin::Pin<Box<F>>, - ) -> SendFuture::T<'a, 'ctx, Self::Future<F::Output>, F::Output> + ) -> SendFuture::T<'a, Self::Future<F::Output>, F::Output> where F: core::future::Future + Send + 'a, <F as core::future::Future>::Output: Send, @@ -50,7 +47,7 @@ pub trait Effect<'ctx>: Send + 'static { } } -pub type Future<'a, 'ctx, T, E> = SendFuture::T<'a, 'ctx, <E as Effect<'ctx>>::Future<T>, T>; +pub type Future<'a, T, E> = SendFuture::T<'a, <E as Effect>::Future<T>, T>; pub struct Blocking<B = Spin> { _marker: PhantomData<fn() -> B>, @@ -88,7 +85,7 @@ impl BlockOn for Spin { #[inline] pub fn noop() -> Waker { - const VTABLE: &'static RawWakerVTable = &RawWakerVTable::new( + const VTABLE: &RawWakerVTable = &RawWakerVTable::new( // Cloning just returns a new no-op raw waker |_| RAW, // `wake` does nothing @@ -98,21 +95,22 @@ pub fn noop() -> Waker { // Dropping does nothing as we don't allocate anything |_| {}, ); - const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE); + const RAW: RawWaker = RawWaker::new(ptr::null(), VTABLE); unsafe { Waker::from_raw(RAW) } } -higher_ranked_type! { - pub type ReadyFuture['ctx, Output]: (SendFuture)[Output] +bijective_higher_ranked_type! { + pub type ReadyFuture[][Output]: SendFuture[][Output] + for<'lt> (core::future::Ready<Output>) where { Output: Send, - } = for<'lt> core::future::Ready<Output> + } } -impl<'ctx, B: BlockOn> Effect<'ctx> for Blocking<B> { - type Future<T: Send> = ReadyFuture<'ctx, T>; +impl<B: BlockOn> Effect for Blocking<B> { + type Future<T: Send> = ReadyFuture<T>; - fn wrap<'a, F>(future: F) -> SendFuture::T<'a, 'ctx, Self::Future<F::Output>, F::Output> + fn wrap<'a, F>(future: F) -> SendFuture::T<'a, Self::Future<F::Output>, F::Output> where F: core::future::Future + Send + 'a, <F as core::future::Future>::Output: Send, @@ -120,14 +118,14 @@ impl<'ctx, B: BlockOn> Effect<'ctx> for Blocking<B> { core::future::ready(B::block_on(future)) } - fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, 'ctx, Self::Future<T>, T> { + fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, Self::Future<T>, T> { core::future::ready(value) } fn map<'a, T, U, F>( - future: SendFuture::T<'a, 'ctx, Self::Future<T>, T>, + future: SendFuture::T<'a, Self::Future<T>, T>, func: F, - ) -> SendFuture::T<'a, 'ctx, Self::Future<U>, U> + ) -> SendFuture::T<'a, Self::Future<U>, U> where T: Send, U: Send, @@ -160,21 +158,22 @@ mod sealed { } #[cfg(feature = "alloc")] -higher_ranked_type! { - pub type BoxFuture['ctx, Output]: (SendFuture)[Output] +bijective_higher_ranked_type! { + pub type BoxFuture[][Output]: SendFuture[][Output] + for<'lt> (sealed::BoxedFuture<'lt, Output>) where { Output: Send, - } = for<'lt> sealed::BoxedFuture<'lt, Output> + } } #[cfg(feature = "alloc")] pub enum Async {} #[cfg(feature = "alloc")] -impl<'ctx> Effect<'ctx> for Async { - type Future<T: Send> = BoxFuture<'ctx, T>; +impl Effect for Async { + type Future<T: Send> = BoxFuture<T>; - fn wrap<'a, F>(future: F) -> SendFuture::T<'a, 'ctx, Self::Future<F::Output>, F::Output> + fn wrap<'a, F>(future: F) -> SendFuture::T<'a, Self::Future<F::Output>, F::Output> where F: core::future::Future + Send + 'a, <F as core::future::Future>::Output: Send, @@ -182,14 +181,14 @@ impl<'ctx> Effect<'ctx> for Async { sealed::BoxedFuture::Box(Box::pin(future)) } - fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, 'ctx, Self::Future<T>, T> { + fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, Self::Future<T>, T> { sealed::BoxedFuture::Ready(core::future::ready(value)) } fn map<'a, T, U, F>( - future: SendFuture::T<'a, 'ctx, Self::Future<T>, T>, + future: SendFuture::T<'a, Self::Future<T>, T>, func: F, - ) -> SendFuture::T<'a, 'ctx, Self::Future<U>, U> + ) -> SendFuture::T<'a, Self::Future<U>, U> where T: Send, U: Send, @@ -206,7 +205,7 @@ impl<'ctx> Effect<'ctx> for Async { fn wrap_boxed<'a, F>( future: core::pin::Pin<Box<F>>, - ) -> SendFuture::T<'a, 'ctx, Self::Future<F::Output>, F::Output> + ) -> SendFuture::T<'a, Self::Future<F::Output>, F::Output> where F: core::future::Future + Send + 'a, <F as core::future::Future>::Output: Send, @@ -19,82 +19,31 @@ //! Bounding a generic by a higher-ranked trait simultaniously allows any higher-ranked type with //! a "true" type with the required traits and any lifetime to be given to that "true" type. -/// Used to cause `'lt` to have extra bounds when using `for<'lt>` syntax. -/// -/// Including this type where a `for<'lt>` is being generated will result in the following bounds -/// being applied. -/// * `'bound: 'lt` - `'lt` will **not** outlive `'bound`. -/// * `T: 'lt` - `T` will outlive `'lt`. -pub type Bound<'lt, 'bound, T = ()> = (&'lt &'bound (), &'lt T); +#[derive(Debug, Default, Copy, Clone)] +#[repr(transparent)] +pub struct Invariant<'a>(PhantomData<fn(&'a ()) -> &'a ()>); -/// Generate a higher-ranked trait. -#[doc(hidden)] -#[macro_export] -macro_rules! higher_ranked_trait { - { - $vis:vis type class $name:ident[$ctx:lifetime $(, $($generic:tt)*)?]: [for<$lt:lifetime> $($($provides:tt)+)?] - $(where { - $($bound:tt)* - })? - $(for where { - $($for_bound:tt)* - })? - } => { - $vis mod $name { - #![allow(unused, non_snake_case)] - - use super::*; - - pub trait ForLt<$lt, $ctx: $lt, B $(, $($generic)*)?> - where $($($bound)*)? $($($for_bound)*)? - - { - type T: $lt $(+ $($provides)+)?; - } - - pub trait Trait<$ctx $(, $($generic)*)?>: for<$lt> ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx $(, $($generic)*)?> $(, $($generic)*)?> - where - $($($bound)*)? - {} - - impl<$ctx, ____ $(, $($generic)*)?> Trait<$ctx $(, $($generic)*)?> for ____ - where - ____: for<$lt> ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx $(, $($generic)*)?> $(, $($generic)*)?>, - $($($bound)*)? - {} +#[repr(transparent)] +pub struct Marker<T>(PhantomData<fn() -> T>); - pub type T<$lt, $ctx, H $(, $($generic)*)?> = <H as ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx $(, $($generic)*)?> $(, $($generic)*)?>>::T; - } - }; +impl<T> Copy for Marker<T> {} +impl<T> Clone for Marker<T> { + fn clone(&self) -> Self { + *self + } } -use core::marker::PhantomData; - -#[doc(inline)] -pub use higher_ranked_trait; - -/// Generate a higher-ranked type. -#[doc(hidden)] -#[macro_export] -macro_rules! higher_ranked_type { - { - $vis:vis type $name:ident[$ctx:lifetime $(, $($generic:tt)*)?]: ($($type_class:tt)*)$([$($type_class_generic:tt)*])? - $(where {$($bound:tt)*})? - = for<$lt:lifetime> $for_lt_type:ty - $(where {$($higher_bound:tt)*})? - } => { - $vis struct $name<$ctx $(, $($generic)*)?>(core::marker::PhantomData<fn() -> (&$ctx (), $($($generic)*)?)>); - - impl<$lt, $ctx $(, $($generic)*)?> $($type_class)*::ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx $(, $($generic)*)?> $(, $($type_class_generic)*)?> for $name<$ctx $(, $($generic)*)?> - where $($($bound)*)? $($($higher_bound)*)? - { - type T = $for_lt_type; - } +impl<T> core::fmt::Debug for Marker<T> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("Marker").finish() } } -#[doc(inline)] -pub use higher_ranked_type; +impl<T> Default for Marker<T> { + fn default() -> Self { + Self(PhantomData) + } +} #[doc(hidden)] #[macro_export] @@ -139,7 +88,7 @@ macro_rules! bijective_higher_ranked_trait { type T: ?Sized + RaiseForLt< $lt, $($lifetimes,)* - &$lt ($(&$lifetimes (),)* $($generic),*), + &$lt ($(&$lifetimes (),)* $(*const $generic,)*), $($generic,)* HigherRanked = Self > $(+ $($provides)+)? + $lt; @@ -163,7 +112,7 @@ macro_rules! bijective_higher_ranked_trait { type HigherRanked: ?Sized + LowerForLt< $lt, $($lifetimes,)* - &$lt ($(&$lifetimes (),)* $($generic),*), + &$lt ($(&$lifetimes (),)* $(*const $generic,)*), $($generic,)* T = Self > $(+ $lifetimes)*; @@ -181,7 +130,7 @@ macro_rules! bijective_higher_ranked_trait { $($lifetimes,)* // Use a implied bound to make sure the lifetime from the for syntax is // correctly bounded. - &$lt ($(&$lifetimes (),)* $($generic),*), + &$lt ($(&$lifetimes (),)* $(*const $generic,)*), $($generic),* > where @@ -198,7 +147,7 @@ macro_rules! bijective_higher_ranked_trait { __: for<$lt> LowerForLt< $lt, $($lifetimes,)* - &$lt ($(&$lifetimes (),)* $($generic),*), + &$lt ($(&$lifetimes (),)* $(*const $generic,)*), $($generic),* >, $($($bound)*)? @@ -209,7 +158,7 @@ macro_rules! bijective_higher_ranked_trait { <__ as LowerForLt< $lt, $($lifetimes,)* - &$lt ($(&$lifetimes (),)* $($generic),*), + &$lt ($(&$lifetimes (),)* $(*const $generic,)*), $($generic),* >>::T; @@ -226,7 +175,7 @@ macro_rules! bijective_higher_ranked_trait { >: RaiseForLt< $lt, $($lifetimes,)* - &$lt ($(&$lifetimes (),)* $($generic),*), + &$lt ($(&$lifetimes (),)* $(*const $generic,)*), $($generic),* > $(+ $($provides)+)? where @@ -244,7 +193,7 @@ macro_rules! bijective_higher_ranked_trait { __: RaiseForLt< $lt, $($lifetimes,)* - &$lt ($(&$lifetimes (),)* $($generic),*), + &$lt ($(&$lifetimes (),)* $(*const $generic,)*), $($generic),* > $(+ $($provides)+)?, $($($bound)*)? @@ -255,13 +204,15 @@ macro_rules! bijective_higher_ranked_trait { <__ as RaiseForLt< $lt, $($lifetimes,)* - &$lt ($(&$lifetimes (),)* $($generic),*), + &$lt ($(&$lifetimes (),)* $(*const $generic,)*), $($generic),* >>::HigherRanked; } }; } +use core::marker::PhantomData; + #[doc(inline)] pub use bijective_higher_ranked_trait; @@ -271,7 +222,7 @@ pub use bijective_higher_ranked_trait; macro_rules! bijective_higher_ranked_type { { $(#[$($meta:tt)*])* - $vis:vis type $name:ident[ + $vis:vis $(for[$($extra_lt:lifetime)*])? type $name:ident[ $($ctx:lifetime),* ][ $($generic:ident),* @@ -285,12 +236,12 @@ macro_rules! bijective_higher_ranked_type { } => { $(#[$($meta)*])* $vis struct $name< - $($type_class_lifetime,)* + $($ctx,)* $($generic: ?Sized,)* $($($forwarding_generic: ?Sized),*)? >( core::marker::PhantomData<fn() -> ( - $(&$type_class_lifetime (),)* + $(&$ctx (),)* $(*const $generic,)* $($(*const $forwarding_generic,)*)? )> @@ -298,6 +249,7 @@ macro_rules! bijective_higher_ranked_type { impl< $lt, + $($($extra_lt,)*)? $($ctx,)* $($generic,)* $($($forwarding_generic),*)? @@ -310,7 +262,7 @@ macro_rules! bijective_higher_ranked_type { ), $($type_class_generic),* > for $name< - $($type_class_lifetime,)* + $($ctx,)* $($generic,)* $($($forwarding_generic),*)? > @@ -322,7 +274,7 @@ macro_rules! bijective_higher_ranked_type { &$lt ( $(&$forward_lt (),)* $(*const $forward_generic,)* - ) + ), $($forward_generic,)* >, )*)? @@ -333,6 +285,7 @@ macro_rules! bijective_higher_ranked_type { impl< $lt, + $($($extra_lt,)*)? $($ctx,)* $($generic,)* $($($forwarding_generic),*)? @@ -353,14 +306,14 @@ macro_rules! bijective_higher_ranked_type { &$lt ( $(&$forward_lt (),)* $(*const $forward_generic,)* - ) + ), $($forward_generic,)* >, )*)? $($($bound)*)? { type HigherRanked = $name< - $($type_class_lifetime,)* + $($ctx,)* $($generic,)* $($( <$forwarding_generic as $type_class::RaiseForLt< @@ -369,7 +322,7 @@ macro_rules! bijective_higher_ranked_type { &$lt ( $(&$forward_lt (),)* $(*const $forward_generic,)* - ) + ), $($forward_generic,)* >>::HigherRanked ),*)? @@ -377,7 +330,7 @@ macro_rules! bijective_higher_ranked_type { } }; { - $vis:vis type [ + $vis:vis $(for[$($extra_lt:lifetime)*])? type [ $($ctx:lifetime),* ][ $($generic:ident),* @@ -391,7 +344,7 @@ macro_rules! bijective_higher_ranked_type { } => { const _: () = { $crate::hkt::bijective_higher_ranked_type! { - $vis type __HigherRanked[ + $vis $(for[$($extra_lt)*])? type __HigherRanked[ $($ctx),* ][ $($generic),* @@ -407,7 +360,7 @@ macro_rules! bijective_higher_ranked_type { }; { $(#[$($meta:tt)*])* - $vis:vis type $name:ident[ + $vis:vis $(for[$($extra_lt:lifetime)*])? type $name:ident[ $($ctx:lifetime),* ][ $($generic:ident),* @@ -420,7 +373,7 @@ macro_rules! bijective_higher_ranked_type { } => { $crate::hkt::bijective_higher_ranked_type! { $(#[$($meta)*])* - $vis type $name[ + $vis $(for[$($extra_lt)*])? type $name[ $($ctx),* ][ $($generic),* @@ -438,70 +391,70 @@ macro_rules! bijective_higher_ranked_type { #[doc(inline)] pub use bijective_higher_ranked_type; -higher_ranked_trait! { - pub type class AnySend['ctx]: [for<'lt> Send] +bijective_higher_ranked_trait! { + pub type class AnySizedSend[][]: [for<'lt> Send + Sized] } -#[cfg(test)] -mod test { - use super::*; - - /// Some trait with two lifetimes and a generic. - trait Demo<'lt, 'ctx, T: Send + 'lt> { - fn add(&self, x: &'lt &'ctx i32) -> i32; - } - - impl<'lt, 'ctx, T: Send + 'lt> Demo<'lt, 'ctx, T> for i32 { - fn add(&self, x: &'lt &'ctx i32) -> i32 { - self + **x - } - } - - impl<'lt, 'ctx, T: Send + 'lt> Demo<'lt, 'ctx, T> for &'lt (dyn Demo<'lt, 'ctx, T> + 'lt) { - fn add(&self, x: &'lt &'ctx i32) -> i32 { - (**self).add(x) - } - } - - // Higher-ranked trait that requires the "true" type to implement Demo. - higher_ranked_trait! { - type class Any['ctx, T]: [for<'lt> Demo<'lt, 'ctx, T>] - where { - T: Send, - } - for where { - T: 'lt - } - } - - // Higher-ranked type with a "true" type of a borrow of a trait object. - // The complex part to support here is the `+ 'lt`. - // This entire module is specialized to support this usecase because that is what treaty needs - // for it's API. - higher_ranked_type! { - type X['ctx, T]: (Any)[T] - where { - T: Send, - } = for<'lt> &'lt (dyn Demo<'lt, 'ctx, T> + 'lt) - } - - // We bound the generic T by the higher-ranked trait Any. - // - // We then inject a 'lt into the higher-ranked type to get a "true" type. - fn demo<'lt, 'ctx, T: Any::Trait<'ctx, i32>>(x: Any::T<'lt, 'ctx, T, i32>, y: &'lt &'ctx i32) { - assert_eq!(x.add(y), 10); - } - - #[test] - fn can_use_hkt() { - let ctx = 2; - let ctx = &ctx; - - { - // The lifetimes here can't be 'static because local isn't static even though z could be. - let local = &ctx; - let z: &dyn Demo<'_, '_, i32> = &8i32; - demo::<X<'_, i32>>(z, local); - } - } -} +// #[cfg(test)] +// mod test { +// use super::*; +// +// /// Some trait with two lifetimes and a generic. +// trait Demo<'lt, 'ctx, T: Send + 'lt> { +// fn add(&self, x: &'lt &'ctx i32) -> i32; +// } +// +// impl<'lt, 'ctx, T: Send + 'lt> Demo<'lt, 'ctx, T> for i32 { +// fn add(&self, x: &'lt &'ctx i32) -> i32 { +// self + **x +// } +// } +// +// impl<'lt, 'ctx, T: Send + 'lt> Demo<'lt, 'ctx, T> for &'lt (dyn Demo<'lt, 'ctx, T> + 'lt) { +// fn add(&self, x: &'lt &'ctx i32) -> i32 { +// (**self).add(x) +// } +// } +// +// // Higher-ranked trait that requires the "true" type to implement Demo. +// bijective_higher_ranked_trait! { +// type class Any['ctx, T]: [for<'lt> Demo<'lt, 'ctx, T>] +// where { +// T: Send, +// } +// for where { +// T: 'lt +// } +// } +// +// // Higher-ranked type with a "true" type of a borrow of a trait object. +// // The complex part to support here is the `+ 'lt`. +// // This entire module is specialized to support this usecase because that is what treaty needs +// // for it's API. +// higher_ranked_type! { +// type X['ctx, T]: (Any)[T] +// where { +// T: Send, +// } = for<'lt> &'lt (dyn Demo<'lt, 'ctx, T> + 'lt) +// } +// +// // We bound the generic T by the higher-ranked trait Any. +// // +// // We then inject a 'lt into the higher-ranked type to get a "true" type. +// fn demo<'lt, 'ctx, T: Any::Trait<'ctx, i32>>(x: Any::T<'lt, 'ctx, T, i32>, y: &'lt &'ctx i32) { +// assert_eq!(x.add(y), 10); +// } +// +// #[test] +// fn can_use_hkt() { +// let ctx = 2; +// let ctx = &ctx; +// +// { +// // The lifetimes here can't be 'static because local isn't static even though z could be. +// let local = &ctx; +// let z: &dyn Demo<'_, '_, i32> = &8i32; +// demo::<X<'_, i32>>(z, local); +// } +// } +// } @@ -15,27 +15,13 @@ pub mod protocol; pub mod symbol; mod transform; mod walk; - -#[cfg(any(test, feature = "mock"))] -pub mod mock; - -// pub use build::Build; -// pub use build::Builder; -// -// pub use walk::Walk; -// pub use walk::Walker; - -use core::ops::ControlFlow; +pub mod macros; pub use build::*; -use effect::{Effect, Future}; -// use protocol::{visitor::tag::TagError, Visitor}; -use symbol::Symbol; pub use transform::*; pub use walk::*; -// #[doc(hidden)] -pub mod macros; +use symbol::Symbol; pub mod never { mod sealed { @@ -93,7 +79,7 @@ macro_rules! Walk { ),* $(,)?} } => { const _: () = { - impl<'ctx, M: 'ctx, E: $crate::effect::Effect<'ctx>> $crate::Walk<'ctx, M, E> for &'ctx $name { + impl<'ctx, M: 'ctx, E: $crate::effect::Effect> $crate::Walk<'ctx, M, E> for &'ctx $name { type Walker = $crate::walkers::core::r#struct::StructWalker<'ctx, $name, Info, M, E>; fn into_walker(self) -> Self::Walker { @@ -109,12 +95,13 @@ macro_rules! Walk { $vis enum Info {} #[derive(Debug)] - #[allow(non_camel_case_types)] + #[allow(non_camel_case_types, unused)] enum FieldErrorKind<'ctx> {$( $field($crate::walkers::core::key_value::KeyValueError<$crate::never::Never, <&'ctx $type as $crate::WalkerTypes>::Error>) ),*} #[derive(Debug)] + #[allow(unused)] $vis struct FieldError<'ctx>(FieldErrorKind<'ctx>); impl<'ctx, M: 'ctx> $crate::walkers::core::r#struct::StructTypeInfo<'ctx, M> for Info { @@ -125,11 +112,11 @@ macro_rules! Walk { type T = $name; #[allow(unreachable_code, non_snake_case, non_upper_case_globals, non_camel_case_types)] - fn walk_field<'a, E: $crate::effect::Effect<'ctx>>( + fn walk_field<'a, E: $crate::effect::Effect>( index: usize, value: &'ctx Self::T, visitor: $crate::protocol::Visitor<'a, 'ctx>, - ) -> $crate::effect::Future<'a, 'ctx, Result<$crate::Flow, Self::FieldError>, E> { + ) -> $crate::effect::Future<'a, Result<$crate::Flow, Self::FieldError>, E> { mod fields { enum Fields {$($field),*} @@ -173,41 +160,41 @@ Walk! { } } -#[cfg(test)] -mod test { - use crate::effect::{BlockOn, Blocking, Spin}; - - use super::*; - use macro_rules_attribute::derive; - - #[derive(Walk!)] - struct Demo { - a: bool, - b: bool, - other: Other, - } - - #[derive(Walk!)] - struct Other { - value: bool, - } - - #[test] - fn demo() { - let value = Demo { - a: true, - b: false, - other: Other { value: true }, - }; - - let walker = Walk::<DefaultMode, Blocking>::into_walker(&value); - let mut visitor = builders::debug::Visitor::<Blocking>::new(); - - dbg!(Spin::block_on(Walker::<Blocking>::walk( - walker, - &mut visitor - ))); - - todo!(); - } -} +// #[cfg(test)] +// mod test { +// use crate::effect::{BlockOn, Blocking, Spin}; +// +// use super::*; +// use macro_rules_attribute::derive; +// +// #[derive(Walk!)] +// struct Demo { +// a: bool, +// b: bool, +// other: Other, +// } +// +// #[derive(Walk!)] +// struct Other { +// value: bool, +// } +// +// #[test] +// fn demo() { +// let value = Demo { +// a: true, +// b: false, +// other: Other { value: true }, +// }; +// +// let walker = Walk::<DefaultMode, Blocking>::into_walker(&value); +// let mut visitor = builders::debug::Visitor::<Blocking>::new(); +// +// dbg!(Spin::block_on(Walker::<Blocking>::walk( +// walker, +// &mut visitor +// ))); +// +// todo!(); +// } +// } diff --git a/src/mock.rs b/src/mock.rs index 89a7a64..e69de29 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -1,81 +0,0 @@ -use core::{ - any::{Any, TypeId}, - ops::Deref, -}; -use std::{ - collections::HashMap, - sync::{Mutex, MutexGuard, OnceLock, RwLock}, -}; - -pub mod builder; -pub mod protocol; - -pub struct StaticTypeMap { - map: OnceLock<RwLock<HashMap<TypeId, &'static (dyn Any + Send + Sync)>>>, -} - -impl StaticTypeMap { - pub const fn new() -> Self { - Self { - map: OnceLock::new(), - } - } - - pub fn get_or_init<T: Send + Sync + 'static, F: FnOnce() -> T>(&self, f: F) -> &'static T { - let map_init = || RwLock::new(HashMap::new()); - - let map = self.map.get_or_init(map_init).read().unwrap(); - - if let Some(once) = map.get(&TypeId::of::<T>()) { - return once.downcast_ref::<T>().unwrap(); - } - - drop(map); - - let mut map = self.map.get_or_init(map_init).write().unwrap(); - let once = &*Box::leak(Box::new(f())); - map.insert(TypeId::of::<T>(), once); - - once - } -} - -pub struct ContextLock<T> { - lock: Mutex<T>, - checkpoint: fn(&T), -} - -impl<T> ContextLock<T> { - pub const fn new(context: T, checkpoint: fn(&T)) -> Self { - Self { - lock: Mutex::new(context), - checkpoint, - } - } - - pub fn lock(&self) -> ContextGuard<'_, T> { - ContextGuard { - lock: self, - guard: self.lock.lock().unwrap(), - } - } -} - -pub struct ContextGuard<'a, T> { - lock: &'a ContextLock<T>, - guard: MutexGuard<'a, T>, -} - -impl<'a, T> Drop for ContextGuard<'a, T> { - fn drop(&mut self) { - (self.lock.checkpoint)(&*self.guard) - } -} - -impl<'a, T> Deref for ContextGuard<'a, T> { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.guard - } -} diff --git a/src/mock/protocol.rs b/src/mock/protocol.rs deleted file mode 100644 index 422fa94..0000000 --- a/src/mock/protocol.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod tag; -pub mod value; diff --git a/src/protocol/visitor/recoverable.rs b/src/protocol/visitor/recoverable.rs index a3a9d65..90c671b 100644 --- a/src/protocol/visitor/recoverable.rs +++ b/src/protocol/visitor/recoverable.rs @@ -1,20 +1,14 @@ use crate::{ - any::{TypeName, WithContextLt}, - bijective_higher_ranked_type, - effect::{Effect, Future}, - higher_ranked_type, - hkt::AnySend, - protocol::{walker::hint::HintMeta, Visitor}, - Flow, + any::{TypeName, WithContextLt}, bijective_higher_ranked_type, effect::{Effect, Future}, hkt::AnySizedSend, protocol::{walker::hint::HintMeta, Visitor}, Flow }; use super::Status; -pub trait Recoverable<'ctx, E: Effect<'ctx>> { +pub trait Recoverable<'ctx, E: Effect> { fn visit<'a>( &'a mut self, scope: DynRecoverableScope<'a, 'ctx, E>, - ) -> Future<'a, 'ctx, Flow, E>; + ) -> Future<'a, Flow, E>; } bijective_higher_ranked_type! { @@ -22,7 +16,7 @@ bijective_higher_ranked_type! { for<'a> (dyn Recoverable<'ctx, E> + Send + 'a) where { - E: Effect<'ctx> + E: Effect } } @@ -31,30 +25,30 @@ bijective_higher_ranked_type! { for<'ctx> (DynRecoverable<'ctx, E>) where { - E: Effect<'ctx> + E: Effect } } -pub trait RecoverableScope<'ctx, E: Effect<'ctx>> { - fn new_walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>; +pub trait RecoverableScope<'ctx, E: Effect> { + fn new_walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, Flow, E>; } pub type DynRecoverableScope<'a, 'ctx, E> = &'a mut (dyn RecoverableScope<'ctx, E> + Send + 'a); -higher_ranked_type! { - pub type RecoverableKnownHkt['ctx]: (AnySend) = for<'lt> () +bijective_higher_ranked_type! { + pub type RecoverableKnownHkt[][]: AnySizedSend[][] for<'lt> (()) } -impl<'ctx, E: Effect<'ctx>> HintMeta<'ctx> for DynRecoverable<'ctx, E> { - type Known = RecoverableKnownHkt<'ctx>; +impl<'ctx, E: Effect> HintMeta<'ctx> for DynRecoverable<'ctx, E> { + type Known = RecoverableKnownHkt; type Hint = (); } -pub fn visit_recoverable<'a, 'ctx, E: Effect<'ctx>>( +pub fn visit_recoverable<'a, 'ctx, E: Effect>( visitor: Visitor<'a, 'ctx>, scope: DynRecoverableScope<'a, 'ctx, E>, -) -> Future<'a, 'ctx, Status, E> { +) -> Future<'a, Status, E> { if let Some(object) = visitor.upcast_mut::<DynRecoverable<'ctx, E>>() { // Allow the visitor to give a hint if it wants. E::map(object.visit(scope), |flow| match flow { diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index 123e187..343dcb9 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -7,12 +7,12 @@ use crate::{ }; /// Protocol for requesting a hint from a visitor. -pub trait RequestHint<'ctx, E: Effect<'ctx>> { +pub trait RequestHint<'ctx, E: Effect> { /// Call this to request a hint. /// /// `walker` is what the visitor (`self`) will call to give a hint using the /// [`Hint`][crate::builtins::walker::Hint] protocol. - fn request_hint<'a>(&'a mut self, walker: Walker<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>; + fn request_hint<'a>(&'a mut self, walker: Walker<'a, 'ctx>) -> Future<'a, Flow, E>; } bijective_higher_ranked_type! { @@ -20,7 +20,7 @@ bijective_higher_ranked_type! { for<'a> (dyn RequestHint<'ctx, E> + Send + 'a) where { - E: Effect<'ctx> + E: Effect } } @@ -29,7 +29,7 @@ bijective_higher_ranked_type! { for<'ctx> (DynRequestHint<'ctx, E>) where { - E: Effect<'ctx> + E: Effect } } @@ -40,10 +40,10 @@ bijective_higher_ranked_type! { /// If [`Flow::Done`] is returned then the visitor doesn't need any more information and the walker /// should stop walking. /// If [`Flow::Break`] is returned then there was an error and the walker should stop walking. -pub fn visit_request_hint<'a, 'ctx, E: Effect<'ctx>>( +pub fn visit_request_hint<'a, 'ctx, E: Effect>( visitor: Visitor<'a, 'ctx>, walker: Walker<'a, 'ctx>, -) -> Future<'a, 'ctx, Flow, E> { +) -> Future<'a, Flow, E> { if let Some(object) = visitor.upcast_mut::<DynRequestHint<'ctx, E>>() { // Allow the visitor to give a hint if it wants. object.request_hint(walker) diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index 88fd248..25ba8dd 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -2,16 +2,15 @@ use crate::{ any::{TypeName, WithContextLt}, bijective_higher_ranked_type, effect::{Effect, Future}, - higher_ranked_type, - hkt::AnySend, + hkt::AnySizedSend, protocol::{walker::hint::HintMeta, Visitor}, Flow, }; use super::Status; -pub trait Sequence<'ctx, E: Effect<'ctx>> { - fn visit<'a>(&'a mut self, scope: DynSequenceScope<'a, 'ctx, E>) -> Future<'a, 'ctx, Flow, E>; +pub trait Sequence<'ctx, E: Effect> { + fn visit<'a>(&'a mut self, scope: DynSequenceScope<'a, 'ctx, E>) -> Future<'a, Flow, E>; } bijective_higher_ranked_type! { @@ -19,7 +18,7 @@ bijective_higher_ranked_type! { for<'a> (dyn Sequence<'ctx, E> + Send + 'a) where { - E: Effect<'ctx> + E: Effect } } @@ -28,20 +27,20 @@ bijective_higher_ranked_type! { for<'ctx> (DynSequence<'ctx, E>) where { - E: Effect<'ctx> + E: Effect } } -pub trait SequenceScope<'ctx, E: Effect<'ctx>> { - fn size_hint<'a>(&'a mut self) -> Future<'a, 'ctx, (usize, Option<usize>), E>; +pub trait SequenceScope<'ctx, E: Effect> { + fn size_hint(&mut self) -> Future<'_, (usize, Option<usize>), E>; - fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>; + fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, Flow, E>; } pub type DynSequenceScope<'a, 'ctx, E> = &'a mut (dyn SequenceScope<'ctx, E> + Send + 'a); -higher_ranked_type! { - pub type SequenceKnownHkt['ctx]: (AnySend) = for<'lt> SequenceKnown +bijective_higher_ranked_type! { + pub type SequenceKnownHkt[][]: AnySizedSend[][] for<'lt> (SequenceKnown) } #[derive(Default)] @@ -53,16 +52,16 @@ pub struct SequenceHint { pub len: (usize, Option<usize>), } -impl<'ctx, E: Effect<'ctx>> HintMeta<'ctx> for DynSequence<'ctx, E> { - type Known = SequenceKnownHkt<'ctx>; +impl<'ctx, E: Effect> HintMeta<'ctx> for DynSequence<'ctx, E> { + type Known = SequenceKnownHkt; type Hint = SequenceHint; } -pub fn visit_sequence<'a, 'ctx, E: Effect<'ctx>>( +pub fn visit_sequence<'a, 'ctx, E: Effect>( visitor: Visitor<'a, 'ctx>, scope: DynSequenceScope<'a, 'ctx, E>, -) -> Future<'a, 'ctx, Status, E> { +) -> Future<'a, Status, E> { if let Some(object) = visitor.upcast_mut::<DynSequence<'ctx, E>>() { // Allow the visitor to give a hint if it wants. E::map(object.visit(scope), |flow| match flow { diff --git a/src/protocol/visitor/tag.rs b/src/protocol/visitor/tag.rs index 0bd5750..4d0bfb2 100644 --- a/src/protocol/visitor/tag.rs +++ b/src/protocol/visitor/tag.rs @@ -2,8 +2,7 @@ use crate::{ any::{TypeName, WithContextLt}, bijective_higher_ranked_type, effect::{Effect, Future}, - higher_ranked_type, - hkt::AnySend, + hkt::AnySizedSend, protocol::{walker::hint::HintMeta, Visitor}, symbol::Symbol, DynWalker, DynWalkerAdapter, DynWalkerError, Flow, WalkerTypes, @@ -39,12 +38,12 @@ impl TagKind for TagDyn { } } -pub trait Tag<'ctx, K: TagKind, E: Effect<'ctx>> { +pub trait Tag<'ctx, K: TagKind, E: Effect> { fn visit<'a>( &'a mut self, kind: K, walker: DynWalker<'a, 'ctx, E>, - ) -> Future<'a, 'ctx, K::Flow, E>; + ) -> Future<'a, K::Flow, E>; } bijective_higher_ranked_type! { @@ -52,7 +51,7 @@ bijective_higher_ranked_type! { for<'a> (dyn Tag<'ctx, K, E> + Send + 'a) where { - E: Effect<'ctx>, + E: Effect, K: TagKind, } } @@ -62,13 +61,13 @@ bijective_higher_ranked_type! { for<'ctx> (DynTag<'ctx, K, E>) where { - E: Effect<'ctx>, + E: Effect, K: TagKind, } } -higher_ranked_type! { - pub type TagKnownHkt['ctx]: (AnySend) = for<'lt> TagKnown +bijective_higher_ranked_type! { + pub type TagKnownHkt[][]: AnySizedSend[][] for<'lt> (TagKnown) } pub struct TagKnown { @@ -80,7 +79,7 @@ pub struct TagHint<K> { } impl<'ctx, K, E> HintMeta<'ctx> for DynTag<'ctx, K, E> { - type Known = TagKnownHkt<'ctx>; + type Known = TagKnownHkt; type Hint = TagHint<K>; } @@ -99,6 +98,7 @@ pub enum TagErrorKind<E> { } #[derive(Debug)] +#[allow(unused)] pub struct TagError<E> { symbol: Symbol, err: TagErrorKind<E>, @@ -134,11 +134,11 @@ impl<E> TagError<E> { } } -pub fn visit_tag<'a, 'ctx: 'a, K: TagKind, E: Effect<'ctx>, W: crate::Walker<'ctx, E> + 'a>( +pub fn visit_tag<'a, 'ctx: 'a, K: TagKind, E: Effect, W: crate::Walker<'ctx, E> + 'a>( kind: K, visitor: Visitor<'a, 'ctx>, walker: W, -) -> Future<'a, 'ctx, Result<Status<W>, TagError<W::Error>>, E> +) -> Future<'a, Result<Status<W>, TagError<W::Error>>, E> where W: WalkerTypes, { diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index 419964b..43a845f 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -6,18 +6,17 @@ use crate::{ any::{TypeName, WithContextLt}, bijective_higher_ranked_type, effect::{Effect, Future}, - higher_ranked_type, - hkt::AnySend, + hkt::AnySizedSend, protocol::{walker::hint::HintMeta, Visitor}, Flow, }; -use super::{recoverable::Recoverable, Status}; +use super::Status; /// Trait object for the [`Value`] protocol. /// /// Types implementing the [`Value`] protocol will implement this trait. -pub trait Value<'ctx, T: WithContextLt::MemberType<'ctx>, E: Effect<'ctx>> { +pub trait Value<'ctx, T: WithContextLt::MemberType<'ctx>, E: Effect> { /// Visit a value of type `T`. /// /// Use this to give a value to a visitor. Its expected that a walker @@ -27,7 +26,9 @@ pub trait Value<'ctx, T: WithContextLt::MemberType<'ctx>, E: Effect<'ctx>> { /// If a [`ControlFlow::Break`] is returned then the walker /// should stop walking as soon as possible as there has likely been /// and error. - fn visit<'a>(&'a mut self, value: WithContextLt::T<'a, 'ctx, T>) -> Future<'a, 'ctx, Flow, E>; + fn visit<'a>(&'a mut self, value: WithContextLt::T<'a, 'ctx, T>) -> Future<'a, Flow, E> + where + 'ctx: 'a; } bijective_higher_ranked_type! { @@ -35,7 +36,7 @@ bijective_higher_ranked_type! { for<'a> (dyn Value<'ctx, T, E> + Send + 'a) where { - E: Effect<'ctx>, + E: Effect, T: ?Sized + WithContextLt::MemberType<'ctx> + 'ctx } } @@ -46,26 +47,28 @@ bijective_higher_ranked_type! { (DynValue<'ctx, TypeName::T<'ctx, T>, E>) (DynValue<'ctx, T, E>) where { - E: Effect<'ctx>, + E: Effect, T: ?Sized, } } -higher_ranked_type! { - pub type ValueKnownHkt['ctx]: (AnySend) = for<'lt> () +pub struct ValueKnown; + +bijective_higher_ranked_type! { + pub type ValueKnownHkt[][]: AnySizedSend[][] for<'lt> (ValueKnown) } // This enrolls the Value protocol into the walker hint system. -impl<'a, 'ctx: 'a, T, E: Effect<'ctx>> HintMeta<'ctx> for DynValue<'ctx, T, E> { - type Known = ValueKnownHkt<'ctx>; +impl<'a, 'ctx: 'a, T, E: Effect> HintMeta<'ctx> for DynValue<'ctx, T, E> { + type Known = ValueKnownHkt; type Hint = (); } -pub fn visit_value<'a, 'ctx, T: WithContextLt::LowerType<'a, 'ctx> + 'ctx, E: Effect<'ctx>>( +pub fn visit_value<'a, 'ctx, T: WithContextLt::LowerType<'a, 'ctx> + 'ctx, E: Effect>( visitor: Visitor<'a, 'ctx>, value: T, -) -> Future<'a, 'ctx, Status, E> +) -> Future<'a, Status, E> where WithContextLt::HigherRanked<'a, 'ctx, T>: TypeName::LowerType<'ctx> + Sized, { @@ -115,12 +118,13 @@ mod test { impl<'ctx, E> Value<'ctx, DynOwnedStatic<i32>, E> for Visitor<E> where - E: Effect<'ctx>, + E: Effect, { fn visit<'a>( &'a mut self, OwnedStatic(value): OwnedStatic<i32>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> + where 'ctx: 'a{ E::wrap(async move { self.0 = Some(value); Flow::Continue @@ -130,12 +134,15 @@ mod test { impl<'ctx, E> Value<'ctx, DynBorrowedStatic<'ctx, i32>, E> for Visitor<E> where - E: Effect<'ctx>, + E: Effect, { fn visit<'a>( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, i32>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> + where + 'ctx: 'a + { E::wrap(async { self.0 = Some(*value); Flow::Continue @@ -147,12 +154,12 @@ mod test { impl['ctx, E] Visitor<E> = [ DynValue<'ctx, DynOwnedStatic<i32>, E>, DynValue<'ctx, DynBorrowedStatic<'ctx, i32>, E>, - ] where E: Effect<'ctx>, + ] where E: Effect, } let mut v = Visitor::<Blocking>(None, PhantomData); let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; - Spin::block_on( + let _ = Spin::block_on( object .upcast_mut::<DynValue<'_, DynOwnedStatic<i32>, Blocking>>() .unwrap() @@ -162,7 +169,7 @@ mod test { assert_eq!(v.0, Some(42)); let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; - Spin::block_on( + let _ = Spin::block_on( object .upcast_mut::<DynValue<'_, DynBorrowedStatic<'_, i32>, Blocking>>() .unwrap() @@ -178,12 +185,13 @@ mod test { impl<'ctx, E> Value<'ctx, DynBorrowedMutStatic<'ctx, String>, E> for Visitor<'ctx, E> where - E: Effect<'ctx>, + E: Effect, { fn visit<'a>( &'a mut self, BorrowedMutStatic(value): BorrowedMutStatic<'ctx, String>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> + where 'ctx: 'a{ E::wrap(async { self.0 = Some(value); @@ -195,14 +203,14 @@ mod test { any_trait! { impl['ctx, E] Visitor<'ctx, E> = [ DynValue<'ctx, DynBorrowedMutStatic<'ctx, String>, E>, - ] where E: Effect<'ctx> + ] where E: Effect } let mut v = Visitor::<Blocking>(None, PhantomData); let mut y = String::from("abc"); let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; - Spin::block_on( + let _ = Spin::block_on( object .upcast_mut::<DynValue<'_, DynBorrowedMutStatic<'_, _>, Blocking>>() .unwrap() @@ -219,12 +227,13 @@ mod test { impl<'ctx, E> Value<'ctx, DynBorrowedStatic<'ctx, str>, E> for Visitor<'ctx, E> where - E: Effect<'ctx>, + E: Effect, { fn visit<'a>( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, str>, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> + where 'ctx: 'a{ E::wrap(async { self.0 = Some(value); Flow::Continue @@ -235,14 +244,14 @@ mod test { any_trait! { impl['ctx, E] Visitor<'ctx, E> = [ DynValue<'ctx, DynBorrowedStatic<'ctx, str>, E>, - ] where E: Effect<'ctx> + ] where E: Effect } let mut v = Visitor::<Blocking>(None, PhantomData); let y = String::from("abc"); let object: &mut (dyn AnyTrait<'_> + Send) = &mut v; - Spin::block_on( + let _ = Spin::block_on( object .upcast_mut::<DynValue<'_, DynBorrowedStatic<'_, str>, Blocking>>() .unwrap() diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index e7d41c6..b5ebd37 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -8,7 +8,7 @@ use crate::{ any::{TypeName, WithContextLt}, bijective_higher_ranked_type, effect::{Effect, Future}, - hkt::AnySend, + hkt::AnySizedSend, protocol::Visitor, Flow, }; @@ -21,16 +21,16 @@ pub trait HintMeta<'ctx> { /// /// This should be information easy to get without changing the state of the walker /// in an irreversible way. - type Known: AnySend::Trait<'ctx>; + type Known: AnySizedSend::MemberType; /// Extra information the visitor can give to the walker about what it is expecting. type Hint; } -pub type Known<'a, 'ctx, Protocol> = AnySend::T<'a, 'ctx, <Protocol as HintMeta<'ctx>>::Known>; +pub type Known<'a, 'ctx, Protocol> = AnySizedSend::T<'a, <Protocol as HintMeta<'ctx>>::Known>; /// Object implementing the [`Hint`] protocol. -pub trait Hint<'ctx, Protocol: ?Sized + HintMeta<'ctx>, E: Effect<'ctx>> { +pub trait Hint<'ctx, Protocol: ?Sized + HintMeta<'ctx>, E: Effect> { /// Hint to the walker to use the `P` protocol. /// /// This should only be called once per [`RequestHint`]. @@ -38,13 +38,13 @@ pub trait Hint<'ctx, Protocol: ?Sized + HintMeta<'ctx>, E: Effect<'ctx>> { &'a mut self, visitor: Visitor<'a, 'ctx>, hint: <Protocol as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E>; + ) -> Future<'a, Flow, E>; /// Ask the walker for information about it's support of the protocol. fn known<'a>( &'a mut self, hint: &'a <Protocol as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, Protocol>, ()>, E>; + ) -> Future<'a, Result<Known<'a, 'ctx, Protocol>, ()>, E>; } bijective_higher_ranked_type! { @@ -52,7 +52,7 @@ bijective_higher_ranked_type! { for<'a> (dyn Hint<'ctx, Protocol, E> + Send + 'a) where { - E: Effect<'ctx>, + E: Effect, Protocol: ?Sized + WithContextLt::MemberType<'ctx> + 'ctx, } } @@ -63,75 +63,74 @@ bijective_higher_ranked_type! { (DynHint<'ctx, TypeName::T<'ctx, Protocol>, E>) (DynHint<'ctx, Protocol, E>) where { - E: Effect<'ctx>, + E: Effect, Protocol: ?Sized, } } -#[cfg(test)] -mod test { - use crate::{ - effect::{BlockOn, Blocking, Spin}, - higher_ranked_type, - }; - - use super::*; - - #[test] - fn demo() { - struct X<'ctx>(&'ctx mut i32); - - #[derive(Debug)] - struct Y; - - bijective_higher_ranked_type! { - type DynY['ctx][]: WithContextLt['ctx][] for<'a> (Y) - } - - bijective_higher_ranked_type! { - type [][]: TypeName[][] for<'ctx> (DynY<'ctx>) - } - - impl<'ctx, E: Effect<'ctx>> Hint<'ctx, DynY<'ctx>, E> for X<'ctx> { - fn hint<'a>( - &'a mut self, - _visitor: Visitor<'a, 'ctx>, - _hint: <DynY<'ctx> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { - todo!() - } - - fn known<'a>( - &'a mut self, - _hint: &'a <DynY<'ctx> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, DynY<'ctx>>, ()>, E> { - E::ready(Ok(&mut *self.0)) - } - } - - higher_ranked_type! { - type KnownHkt['ctx]: (AnySend) = for<'lt> &'lt mut i32 - } - - impl<'ctx> HintMeta<'ctx> for DynY<'ctx> { - type Known = KnownHkt<'ctx>; - - type Hint = (); - } - - let mut z = 42; - let mut x = X(&mut z); - let y: &mut WithContextLt::T<'_, '_, DynHint<'_, DynY<'_>, Blocking>> = &mut x; - - fn id<'a, 'ctx, T: ?Sized + TypeName::LowerType<'ctx>>(_x: &WithContextLt::T<'a, 'ctx, T>) { - } - id::<DynHint<'_, DynY<'_>, Blocking>>(y); - - let x = Spin::block_on(y.known(&())); - match x { - Ok(value) => *value += 1, - Err(_) => todo!(), - } - assert_eq!(z, 43); - } -} +// #[cfg(test)] +// mod test { +// use crate::{ +// effect::{BlockOn, Blocking, Spin}, +// }; +// +// use super::*; +// +// #[test] +// fn demo() { +// struct X<'ctx>(&'ctx mut i32); +// +// #[derive(Debug)] +// struct Y; +// +// bijective_higher_ranked_type! { +// type DynY['ctx][]: WithContextLt['ctx][] for<'a> (Y) +// } +// +// bijective_higher_ranked_type! { +// type [][]: TypeName[][] for<'ctx> (DynY<'ctx>) +// } +// +// impl<'ctx, E: Effect<'ctx>> Hint<'ctx, DynY<'ctx>, E> for X<'ctx> { +// fn hint<'a>( +// &'a mut self, +// _visitor: Visitor<'a, 'ctx>, +// _hint: <DynY<'ctx> as HintMeta<'ctx>>::Hint, +// ) -> Future<'a, 'ctx, Flow, E> { +// todo!() +// } +// +// fn known<'a>( +// &'a mut self, +// _hint: &'a <DynY<'ctx> as HintMeta<'ctx>>::Hint, +// ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, DynY<'ctx>>, ()>, E> { +// E::ready(Ok(&mut *self.0)) +// } +// } +// +// higher_ranked_type! { +// type KnownHkt['ctx]: (AnySend) = for<'lt> &'lt mut i32 +// } +// +// impl<'ctx> HintMeta<'ctx> for DynY<'ctx> { +// type Known = KnownHkt<'ctx>; +// +// type Hint = (); +// } +// +// let mut z = 42; +// let mut x = X(&mut z); +// let y: &mut WithContextLt::T<'_, '_, DynHint<'_, DynY<'_>, Blocking>> = &mut x; +// +// fn id<'a, 'ctx, T: ?Sized + TypeName::LowerType<'ctx>>(_x: &WithContextLt::T<'a, 'ctx, T>) { +// } +// id::<DynHint<'_, DynY<'_>, Blocking>>(y); +// +// let x = Spin::block_on(y.known(&())); +// match x { +// Ok(value) => *value += 1, +// Err(_) => todo!(), +// } +// assert_eq!(z, 43); +// } +// } diff --git a/src/symbol.rs b/src/symbol.rs index e5d984f..1809897 100644 --- a/src/symbol.rs +++ b/src/symbol.rs @@ -10,7 +10,7 @@ use range::*; /// Unique symbol, given a unique tag. /// /// ``` -/// use uniserde::symbol::Symbol; +/// use treaty::symbol::Symbol; /// /// const PROPERTY: Symbol = Symbol::new("Property"); /// # let _ = PROPERTY; @@ -78,7 +78,7 @@ impl Symbol { /// This is provided to allow using a [`Symbol`] as a const generic. /// /// ``` - /// use uniserde::symbol::Symbol; + /// use treaty::symbol::Symbol; /// /// struct MyType<const N: u64>; /// @@ -210,6 +210,7 @@ fn decode(input: u64, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut offset = 0; // Read a bit to fill the precision. + #[allow(clippy::mut_range_bound)] for _ in 0..precision { input_buffer = (input_buffer << 1) | match bit(&mut precision, &mut offset, input) { @@ -755,6 +756,7 @@ mod test { } #[test] + #[allow(clippy::approx_constant)] fn alphabet() { // This test is special. It generates the model table from a set // of basic probability lists. If the table in the code is wrong @@ -790,7 +792,7 @@ mod test { ('z', 0.07), ]); assert_eq!(lower.len(), 26); - assert!((lower.iter().map(|(_, x)| x).sum::<f64>() - 100.0).abs() < 0.1); + assert!((lower.values().sum::<f64>() - 100.0).abs() < 0.1); let upper = HashMap::<char, f64>::from([ ('A', 5.64), @@ -821,7 +823,7 @@ mod test { ('Z', 0.27), ]); assert_eq!(upper.len(), 26); - assert!((upper.iter().map(|(_, x)| x).sum::<f64>() - 100.0).abs() < 0.1); + assert!((upper.values().sum::<f64>() - 100.0).abs() < 0.1); let digit = HashMap::<char, f64>::from([ ('1', 30.1), @@ -836,11 +838,11 @@ mod test { ('0', 1.0), ]); assert_eq!(digit.len(), 10); - assert!((digit.iter().map(|(_, x)| x).sum::<f64>() - 100.0).abs() < 0.1); + assert!((digit.values().sum::<f64>() - 100.0).abs() < 0.1); let extra = HashMap::<char, f64>::from([(' ', 30.0), ('_', 60.0), ('-', 10.0)]); assert_eq!(extra.len(), 3); - assert!((extra.iter().map(|(_, x)| x).sum::<f64>() - 100.0).abs() < 0.1); + assert!((extra.values().sum::<f64>() - 100.0).abs() < 0.1); let all: HashMap<char, f64> = lower .iter() @@ -897,6 +899,7 @@ mod test { // This is the model used in the arithmetic coding. #[rustfmt::skip] +#[allow(clippy::items_after_test_module)] const ALPHABET: &[(u8, [(u64, u64); 18])] = &[ (b' ', [(0,1180),(0,1178),(0,1168),(0,1153),(0,1123),(0,1092),(0,1058),(0,1020),(0,980),(0,935),(0,885),(0,828),(0,763),(0,685),(0,590),(0,468),(0,0),(0,0),]), (b'-', [(1180,393),(1178,393),(1168,389),(1153,384),(1123,374),(1092,364),(1058,353),(1020,340),(980,327),(935,312),(885,295),(828,276),(763,254),(685,228),(590,197),(468,156),(0,0),(0,0),]), diff --git a/src/transform.rs b/src/transform.rs index 9d696be..64aea20 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -5,10 +5,11 @@ use crate::{ }; #[inline] -pub fn transform<'a, 'ctx, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Effect<'ctx>>( +#[allow(clippy::type_complexity)] +pub fn transform<'a, 'ctx, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Effect>( seed: B::Seed, walker: W, -) -> Future<'a, 'ctx, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> { +) -> Future<'a, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> { E::wrap(async { // Create builder from seed value; let mut builder = B::from_seed(seed).await; diff --git a/src/walk.rs b/src/walk.rs index c991377..672bfd3 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -7,7 +7,7 @@ use crate::{ }; /// A type that can be walked. -pub trait Walk<'ctx, M, E: Effect<'ctx>>: WalkerTypes + Sized { +pub trait Walk<'ctx, M, E: Effect>: WalkerTypes + Sized { /// The walker for the type. type Walker: Walker<'ctx, E, Error = Self::Error, Output = Self::Output>; @@ -33,20 +33,20 @@ pub trait WalkerTypes { /// - Call [From::from()] with a value to be walked to make a walker. /// - Call [Self::walk()] to walk the value. Data will be sent to the provided /// visitor. -pub trait Walker<'ctx, E: Effect<'ctx>>: WalkerTypes + Send { +pub trait Walker<'ctx, E: Effect>: WalkerTypes + Send { /// Walk the value. /// /// The walker should send data to the `visitor` as it walks the value. fn walk<'a>( self, visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> + ) -> Future<'a, Result<Self::Output, Self::Error>, E> where Self: 'a; } -pub trait WalkerObjSafe<'ctx, E: Effect<'ctx>>: Send { - fn walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> +pub trait WalkerObjSafe<'ctx, E: Effect>: Send { + fn walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, Flow, E> where Self: 'a; } @@ -102,8 +102,8 @@ impl<W: WalkerTypes> DynWalkerAdapter<W> { } } -impl<'ctx, W: Walker<'ctx, E>, E: Effect<'ctx>> WalkerObjSafe<'ctx, E> for DynWalkerAdapter<W> { - fn walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> +impl<'ctx, W: Walker<'ctx, E>, E: Effect> WalkerObjSafe<'ctx, E> for DynWalkerAdapter<W> { + fn walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, Flow, E> where Self: 'a, { diff --git a/src/walk/walkers/core/bool.rs b/src/walk/walkers/core/bool.rs index 5e173fa..03929e5 100644 --- a/src/walk/walkers/core/bool.rs +++ b/src/walk/walkers/core/bool.rs @@ -1,8 +1,8 @@ use crate::{effect::Effect, Walk, WalkerTypes}; -use super::value::{BorrowWalker, ValueWalker}; +use super::value::ValueWalker; -impl<'ctx, M, E: Effect<'ctx>> Walk<'ctx, M, E> for bool { +impl<'ctx, M, E: Effect> Walk<'ctx, M, E> for bool { type Walker = ValueWalker<bool>; fn into_walker(self) -> Self::Walker { @@ -15,7 +15,7 @@ impl WalkerTypes for bool { type Output = <ValueWalker<bool> as WalkerTypes>::Output; } -impl<'ctx, M, E: Effect<'ctx>> Walk<'ctx, M, E> for &'ctx bool { +impl<'ctx, M, E: Effect> Walk<'ctx, M, E> for &'ctx bool { type Walker = ValueWalker<bool>; fn into_walker(self) -> Self::Walker { diff --git a/src/walk/walkers/core/key_value.rs b/src/walk/walkers/core/key_value.rs index 6eb2210..36f2281 100644 --- a/src/walk/walkers/core/key_value.rs +++ b/src/walk/walkers/core/key_value.rs @@ -29,6 +29,7 @@ impl<T, K, V> KeyValueWalker<T, K, V> { } #[derive(Debug)] +#[allow(unused)] enum KeyValueErrorKind<K, V> { Tag(TagError<Never>), Key(K), @@ -50,7 +51,7 @@ where impl<'ctx, T, K, V, E> crate::Walker<'ctx, E> for KeyValueWalker<T, K, V> where - E: Effect<'ctx>, + E: Effect, T: TagKind, K: crate::Walker<'ctx, E>, V: crate::Walker<'ctx, E>, @@ -58,7 +59,7 @@ where fn walk<'a>( self, visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> + ) -> Future<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { @@ -73,12 +74,12 @@ where .await { Ok(Status::Skipped(_) | Status::Flow(Flow::Continue)) => {} - Ok(Status::Flow(flow)) => return Ok(()), + Ok(Status::Flow(_flow)) => return Ok(()), Err(_) => todo!(), } } Ok(Status::Flow(Flow::Continue)) => {} - Ok(Status::Flow(flow)) => todo!(), + Ok(Status::Flow(_flow)) => todo!(), Err(_) => todo!(), } @@ -90,7 +91,7 @@ where .await { Ok(Status::Skipped(_) | Status::Flow(Flow::Continue)) => {} - Ok(Status::Flow(flow)) => return Ok(()), + Ok(Status::Flow(_flow)) => return Ok(()), Err(_) => todo!(), } @@ -106,10 +107,10 @@ where // Fallback to just walking the value. match value_walker.walk(visitor).await { Ok(_) => {} - Err(err) => todo!(), + Err(_err) => todo!(), } } - Ok(Status::Flow(flow)) => todo!(), + Ok(Status::Flow(_flow)) => todo!(), Err(_) => todo!(), } diff --git a/src/walk/walkers/core/noop.rs b/src/walk/walkers/core/noop.rs index ec7f8ae..8bb05cb 100644 --- a/src/walk/walkers/core/noop.rs +++ b/src/walk/walkers/core/noop.rs @@ -9,7 +9,7 @@ use crate::{ /// /// This walker is useful for tags that don't need a value. #[non_exhaustive] -#[derive(Debug)] +#[derive(Debug, Default)] pub struct NoopWalker; impl NoopWalker { @@ -24,11 +24,11 @@ impl WalkerTypes for NoopWalker { type Output = (); } -impl<'ctx, E: Effect<'ctx>> crate::Walker<'ctx, E> for NoopWalker { +impl<'ctx, E: Effect> crate::Walker<'ctx, E> for NoopWalker { fn walk<'a>( self, _visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> + ) -> Future<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { diff --git a/src/walk/walkers/core/struct.rs b/src/walk/walkers/core/struct.rs index e78094e..406e703 100644 --- a/src/walk/walkers/core/struct.rs +++ b/src/walk/walkers/core/struct.rs @@ -1,24 +1,19 @@ -use core::{any::TypeId, marker::PhantomData}; +use core::any::TypeId; use crate::{ - any::static_wrapper::{BorrowedStatic, DynBorrowedStatic}, - any_trait, - effect::{Effect, Future}, - never::Never, - protocol::{ + any::static_wrapper::{BorrowedStatic, DynBorrowedStatic}, any_trait, effect::{Effect, Future}, hkt::Marker, never::Never, protocol::{ visitor::{ recoverable::{visit_recoverable, DynRecoverable, RecoverableScope}, request_hint::visit_request_hint, sequence::{visit_sequence, DynSequence, SequenceKnown, SequenceScope}, tag::{visit_tag, DynTag, TagConst, TagDyn, TagError, TagHint, TagKnown}, - value::{visit_value, DynValue}, + value::{visit_value, DynValue, ValueKnown}, Status, }, walker::hint::{DynHint, HintMeta}, walker::hint::{Hint, Known}, Visitor, - }, - Flow, WalkerTypes, TAG_FIELD_NAMES, TAG_MAP, TAG_STRUCT, TAG_TYPE_ID, TAG_TYPE_NAME, + }, Flow, WalkerTypes, TAG_FIELD_NAMES, TAG_MAP, TAG_STRUCT, TAG_TYPE_ID, TAG_TYPE_NAME }; use super::{noop::NoopWalker, tag::StaticSliceWalker, value::ValueWalker}; @@ -38,7 +33,7 @@ pub struct StructWalker<'ctx, T, I: StructTypeInfo<'ctx, M>, M, E> { /// The visitor tracks it's own errors. error: Option<StructWalkErrorKind<I::FieldError>>, - _marker: PhantomData<fn() -> (I, M, E)>, + _generics: Marker<(I, M, E)>, } /// Type info about a struct needed by [`StructWalker`]. @@ -56,14 +51,15 @@ pub trait StructTypeInfo<'ctx, M>: 'static { type T: Send; /// Walk the given field. - fn walk_field<'a, E: Effect<'ctx>>( + fn walk_field<'a, E: Effect>( index: usize, value: &'ctx Self::T, visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Flow, Self::FieldError>, E>; + ) -> Future<'a, Result<Flow, Self::FieldError>, E>; } #[derive(Debug)] +#[allow(unused)] enum StructWalkErrorKind<T> { /// Error with visiting a tag for the struct. /// @@ -81,6 +77,7 @@ enum StructWalkErrorKind<T> { /// Error from walking a struct. #[derive(Debug)] +#[allow(unused)] pub struct StructWalkError<T> { kind: StructWalkErrorKind<T>, } @@ -95,7 +92,7 @@ where value, index: 0, error: None, - _marker: PhantomData, + _generics: Default::default(), } } } @@ -110,14 +107,14 @@ where impl<'ctx, T, I, E, M> crate::Walker<'ctx, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M, T = T>, T: Sync + 'static, { fn walk<'a>( mut self, visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> + ) -> Future<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { @@ -146,14 +143,14 @@ any_trait! { DynHint<'ctx, DynTag<'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E>, E>, DynHint<'ctx, DynTag<'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>, E>, ] where - E: Effect<'ctx>, + E: Effect, T: Sync + 'static, I: StructTypeInfo<'ctx, M, T = T> } impl<'ctx, T, I, M, E> Hint<'ctx, DynRecoverable<'ctx, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M, T = T>, T: Sync + 'static, { @@ -161,7 +158,7 @@ where &'a mut self, visitor: Visitor<'a, 'ctx>, _hint: <DynRecoverable<'ctx, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { E::map( visit_recoverable::<E>(visitor, self), |status| match status { @@ -174,7 +171,7 @@ where fn known<'a>( &'a mut self, _hint: &'a <DynRecoverable<'ctx, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, DynRecoverable<'ctx, E>>, ()>, E> { + ) -> Future<'a, Result<Known<'a, 'ctx, DynRecoverable<'ctx, E>>, ()>, E> { E::ready(Ok(())) } } @@ -182,7 +179,7 @@ where impl<'ctx, T, I, M, E> Hint<'ctx, DynTag<'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M>, T: Sync + 'static, { @@ -190,7 +187,7 @@ where &'a mut self, visitor: Visitor<'a, 'ctx>, _hint: <DynTag<'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { E::map( visit_tag::<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E, _>( TagConst, @@ -213,9 +210,7 @@ where _hint: &'a <DynTag<'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E> as HintMeta< 'ctx, >>::Hint, - ) -> Future< - 'a, - 'ctx, + ) -> Future<'a, Result<Known<'a, 'ctx, DynTag<'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>>, ()>, E, > { @@ -228,7 +223,7 @@ where impl<'ctx, T, I, M, E> Hint<'ctx, DynTag<'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M>, T: Sync + 'static, { @@ -236,7 +231,7 @@ where &'a mut self, visitor: Visitor<'a, 'ctx>, _hint: <DynTag<'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { E::map( visit_tag::<TagConst<{ TAG_TYPE_NAME.to_int() }>, E, _>( TagConst, @@ -259,7 +254,6 @@ where _hint: &'a <DynTag<'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E> as HintMeta<'ctx>>::Hint, ) -> Future< 'a, - 'ctx, Result<Known<'a, 'ctx, DynTag<'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E>>, ()>, E, > { @@ -272,7 +266,7 @@ where impl<'ctx, T, I, M, E> Hint<'ctx, DynTag<'ctx, TagConst<{ TAG_MAP.to_int() }>, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M>, T: Sync + 'static, { @@ -280,7 +274,7 @@ where &'a mut self, visitor: Visitor<'a, 'ctx>, _hint: <DynTag<'ctx, TagConst<{ TAG_MAP.to_int() }>, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { E::map( visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>(TagConst, visitor, NoopWalker::new()), |status| match status { @@ -299,7 +293,6 @@ where _hint: &'a <DynTag<'ctx, TagConst<{ TAG_MAP.to_int() }>, E> as HintMeta<'ctx>>::Hint, ) -> Future< 'a, - 'ctx, Result<Known<'a, 'ctx, DynTag<'ctx, TagConst<{ TAG_MAP.to_int() }>, E>>, ()>, E, > { @@ -312,7 +305,7 @@ where impl<'ctx, T, I, M, E> Hint<'ctx, DynTag<'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M>, T: Sync + 'static, { @@ -320,7 +313,7 @@ where &'a mut self, visitor: Visitor<'a, 'ctx>, _hint: <DynTag<'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { E::map( visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>( TagConst, @@ -343,7 +336,6 @@ where _hint: &'a <DynTag<'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E> as HintMeta<'ctx>>::Hint, ) -> Future< 'a, - 'ctx, Result<Known<'a, 'ctx, DynTag<'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E>>, ()>, E, > { @@ -356,7 +348,7 @@ where impl<'ctx, T, I, M, E> Hint<'ctx, DynTag<'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M>, T: Sync + 'static, { @@ -364,7 +356,7 @@ where &'a mut self, visitor: Visitor<'a, 'ctx>, _hint: <DynTag<'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { E::map( visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>( TagConst, @@ -387,7 +379,6 @@ where _hint: &'a <DynTag<'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E> as HintMeta<'ctx>>::Hint, ) -> Future< 'a, - 'ctx, Result<Known<'a, 'ctx, DynTag<'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E>>, ()>, E, > { @@ -399,7 +390,7 @@ where impl<'ctx, T, I, M, E> Hint<'ctx, DynTag<'ctx, TagDyn, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M>, T: Sync + 'static, { @@ -407,7 +398,7 @@ where &'a mut self, visitor: Visitor<'a, 'ctx>, hint: <DynTag<'ctx, TagDyn, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { match hint.kind.0 { crate::TAG_TYPE_ID => Hint::< 'ctx, @@ -445,7 +436,7 @@ where fn known<'a>( &'a mut self, hint: &'a <DynTag<'ctx, TagDyn, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, DynTag<'ctx, TagDyn, E>>, ()>, E> { + ) -> Future<'a, Result<Known<'a, 'ctx, DynTag<'ctx, TagDyn, E>>, ()>, E> { E::ready(match hint.kind { TagDyn(crate::TAG_TYPE_ID) | TagDyn(crate::TAG_STRUCT) => Ok(TagKnown { kind_available: Some(true), @@ -460,11 +451,11 @@ where impl<'ctx, T, I, M, E> Hint<'ctx, DynValue<'ctx, DynBorrowedStatic<'ctx, T>, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M>, T: Sync + 'static, { - fn hint<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>, _hint: ()) -> Future<'a, 'ctx, Flow, E> { + fn hint<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>, _hint: ()) -> Future<'a, Flow, E> { E::map( visit_value::<_, E>(visitor, BorrowedStatic(self.value)), |status| match status { @@ -474,14 +465,14 @@ where ) } - fn known<'a>(&'a mut self, _hint: &'a ()) -> Future<'a, 'ctx, Result<(), ()>, E> { - E::ready(Ok(())) + fn known<'a>(&'a mut self, _hint: &'a ()) -> Future<'a, Result<ValueKnown, ()>, E> { + E::ready(Ok(ValueKnown)) } } impl<'ctx, T, I, M, E> Hint<'ctx, DynSequence<'ctx, E>, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M, T = T>, T: Sync, { @@ -489,7 +480,7 @@ where &'a mut self, visitor: Visitor<'a, 'ctx>, _hint: <DynSequence<'ctx, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Flow, E> { + ) -> Future<'a, Flow, E> { E::map(visit_sequence::<E>(visitor, self), |status| match status { Status::Skipped(_) => Flow::Continue, Status::Flow(flow) => flow, @@ -499,7 +490,7 @@ where fn known<'a>( &'a mut self, _hint: &'a <DynSequence<'ctx, E> as HintMeta<'ctx>>::Hint, - ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, DynSequence<'ctx, E>>, ()>, E> { + ) -> Future<'a, Result<Known<'a, 'ctx, DynSequence<'ctx, E>>, ()>, E> { let len = I::FIELDS.len(); E::ready(Ok(SequenceKnown { @@ -510,16 +501,16 @@ where impl<'ctx, T, I, M, E> SequenceScope<'ctx, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M, T = T>, { - fn size_hint<'a>(&'a mut self) -> Future<'a, 'ctx, (usize, Option<usize>), E> { + fn size_hint(&mut self) -> Future<'_, (usize, Option<usize>), E> { let len = I::FIELDS.len(); E::ready((len, Some(len))) } - fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> { + fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, Flow, E> { if self.index >= I::FIELDS.len() { return E::ready(Flow::Done); } @@ -543,11 +534,11 @@ where impl<'ctx, T, I, M, E> RecoverableScope<'ctx, E> for StructWalker<'ctx, T, I, M, E> where - E: Effect<'ctx>, + E: Effect, I: StructTypeInfo<'ctx, M, T = T>, T: Sync + 'static, { - fn new_walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> { + fn new_walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, Flow, E> { // Reset the errors to default state. self.error = None; @@ -659,152 +650,3 @@ where }) } } - -#[cfg(test)] -mod test { - use mockall::{predicate::eq, Sequence}; - - use crate::{ - any::{ - static_wrapper::{DynOwnedStatic, OwnedStatic}, - TypeNameId, - }, - effect::{BlockOn as _, Blocking, Spin}, - mock::{ - builder::MockBuilder, - protocol::{tag::MockTagVisitor, value::MockValueVisitor}, - }, - symbol::Symbol, - Builder, DefaultMode, Walker, - }; - - use super::*; - - struct Demo { - a: bool, - b: bool, - } - - impl<'ctx, M> StructTypeInfo<'ctx, M> for Demo { - const NAME: &'static str = "Demo"; - - const FIELDS: &'static [&'static str] = &["a", "b"]; - - type FieldError = (); - - type T = Demo; - - fn walk_field<'a, E: Effect<'ctx>>( - index: usize, - value: &'ctx Self::T, - visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Flow, Self::FieldError>, E> { - E::wrap(async move { - match index { - 0 => { - let walker = ValueWalker::<bool>::new(value.a); - Walker::<E>::walk(walker, visitor).await.unwrap(); - Ok(Flow::Continue) - } - 1 => { - let walker = ValueWalker::<bool>::new(value.b); - Walker::<E>::walk(walker, visitor).await.unwrap(); - Ok(Flow::Continue) - } - _ => Ok(Flow::Done), - } - }) - } - } - - #[test] - fn demo2() { - let mut builder = MockBuilder::<(), (), ()>::new(); - - let mut seq = Sequence::new(); - - builder - .expect_traits_mut() - .times(4) - .in_sequence(&mut seq) - .return_var(None); - - builder - .expect_traits_mut() - .once() - .with(eq(TypeNameId::of::< - DynTag<'static, TagConst<{ TAG_STRUCT.to_int() }>, Blocking>, - >())) - .in_sequence(&mut seq) - .return_var(Some(Box::new({ - let mut mock = MockTagVisitor::<TagConst<{ TAG_STRUCT.to_int() }>, Blocking>::new(); - - mock.expect_visit().once().returning(|_, walker| { - let mut builder = MockBuilder::<(), (), ()>::new(); - assert_eq!( - Spin::block_on(walker.walk(Builder::<Blocking>::as_visitor(&mut builder))), - Flow::Done - ); - - Flow::Continue - }); - - mock - }))); - - builder - .expect_traits_mut() - .once() - .with(eq(TypeNameId::of::< - DynTag<'static, TagConst<{ TAG_TYPE_NAME.to_int() }>, Blocking>, - >())) - .in_sequence(&mut seq) - .return_var(Some(Box::new({ - let mut mock = - MockTagVisitor::<TagConst<{ TAG_TYPE_NAME.to_int() }>, Blocking>::new(); - - mock.expect_visit().return_once(|_, walker| { - let mut builder = MockBuilder::<(), (), ()>::new(); - - builder - .expect_traits_mut() - .once() - .with(eq(TypeNameId::of::< - DynValue<'static, DynOwnedStatic<&'static str>, Blocking>, - >())) - .return_var(Some(Box::new({ - let mut mock = - MockValueVisitor::<DynOwnedStatic<&'static str>, Blocking>::new(); - - mock.expect_visit() - .once() - .with(eq(OwnedStatic("Demo"))) - .return_const(Flow::Done); - - mock - }))); - - assert_eq!( - Spin::block_on(walker.walk(Builder::<Blocking>::as_visitor(&mut builder))), - Flow::Done - ); - - Flow::Continue - }); - - mock - }))); - - builder - .expect_traits_mut() - .times(3) - .in_sequence(&mut seq) - .return_var(None); - - let value = Demo { a: true, b: false }; - - let walker = StructWalker::<Demo, Demo, DefaultMode, Blocking>::new(&value); - - Spin::block_on(walker.walk(Builder::<Blocking>::as_visitor(&mut builder))).unwrap(); - } -} diff --git a/src/walk/walkers/core/tag.rs b/src/walk/walkers/core/tag.rs index 22e117b..0deab96 100644 --- a/src/walk/walkers/core/tag.rs +++ b/src/walk/walkers/core/tag.rs @@ -1,25 +1,23 @@ -use core::{any::TypeId, marker::PhantomData}; +use core::marker::PhantomData; use crate::{ - any::static_wrapper::{DynOwnedStatic, OwnedStatic}, + any::static_wrapper::OwnedStatic, any_trait, effect::{Effect, Future}, never::Never, protocol::{ visitor::{ - request_hint::{visit_request_hint, DynRequestHint, RequestHint}, + request_hint::visit_request_hint, sequence::{DynSequence, SequenceScope}, - tag::{DynTag, TagError}, - value::{visit_value, DynValue, Value}, + tag::TagError, + value::visit_value, Status, }, Visitor, }, - Flow, WalkerTypes, TAG_FIELD_NAMES, TAG_SEQ_INDEX, TAG_SEQ_LEN, + Flow, WalkerTypes }; -use super::value::ValueWalker; - pub struct StaticSliceWalker<T: 'static, W> { names: &'static [T], current: usize, @@ -44,7 +42,7 @@ impl<T, W> WalkerTypes for StaticSliceWalker<T, W> { impl<'ctx, T, W, E> crate::Walker<'ctx, E> for StaticSliceWalker<T, W> where - E: Effect<'ctx>, + E: Effect, W: crate::Walker<'ctx, E> + WalkerTypes<Output = ()>, T: Sync, &'static T: Into<W>, @@ -52,7 +50,7 @@ where fn walk<'a>( mut self, visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> + ) -> Future<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { @@ -85,12 +83,12 @@ any_trait! { impl<'ctx, T, W, E> SequenceScope<'ctx, E> for StaticSliceWalker<T, W> where - E: Effect<'ctx>, + E: Effect, W: crate::Walker<'ctx, E> + WalkerTypes<Output = ()>, T: Sync, &'static T: Into<W>, { - fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> { + fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, Flow, E> { if let Some(name) = self.names.get(self.current) { self.current += 1; E::wrap(async move { @@ -104,7 +102,7 @@ where } } - fn size_hint<'a>(&'a mut self) -> Future<'a, 'ctx, (usize, Option<usize>), E> { + fn size_hint(&mut self) -> Future<'_, (usize, Option<usize>), E> { E::ready((self.names.len(), Some(self.names.len()))) } } diff --git a/src/walk/walkers/core/value.rs b/src/walk/walkers/core/value.rs index 64586ca..d5b35b9 100644 --- a/src/walk/walkers/core/value.rs +++ b/src/walk/walkers/core/value.rs @@ -38,11 +38,11 @@ impl<T> WalkerTypes for ValueWalker<T> { type Output = (); } -impl<'ctx, T: Send + 'static, E: Effect<'ctx>> crate::Walker<'ctx, E> for ValueWalker<T> { +impl<'ctx, T: Send + 'static, E: Effect> crate::Walker<'ctx, E> for ValueWalker<T> { fn walk<'a>( self, visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> + ) -> Future<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { @@ -72,13 +72,13 @@ impl<'ctx, T: ?Sized> WalkerTypes for BorrowWalker<'ctx, T> { type Output = (); } -impl<'ctx, T: ?Sized + Sync + 'static, E: Effect<'ctx>> crate::Walker<'ctx, E> +impl<'ctx, T: ?Sized + Sync + 'static, E: Effect> crate::Walker<'ctx, E> for BorrowWalker<'ctx, T> { fn walk<'a>( self, visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> + ) -> Future<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { diff --git a/tests/async.rs b/tests/async.rs deleted file mode 100644 index 13968ab..0000000 --- a/tests/async.rs +++ /dev/null @@ -1,148 +0,0 @@ -use std::{collections::VecDeque, future::Future, ops::ControlFlow, pin::Pin}; -use treaty::{ - any::{any_trait, static_wrapper::OwnedStatic}, - async_build_with, build_with, into_walker, - protocol::{ - visitor::{Sequence, SequenceScope, Status, Value}, - AsyncEffect, ControlFlowFor, Visitor, - }, - Builder, Walk, Walker, -}; - -#[tokio::test] -async fn demo() { - let a = Data::Sequence(vec![ - Data::Bool(true), - Data::Sequence(vec![Data::Bool(false), Data::Bool(true)]), - Data::Bool(false), - ]); - - let s = async_build_with::<JsonLike, _>(into_walker(a)) - .await - .unwrap(); - - assert_eq!(s, "[true,[false,true,],false,]"); -} - -#[derive(Debug)] -enum Data { - Bool(bool), - Sequence(Vec<Data>), -} - -const _: () = { - struct Impl(Data); - - impl From<Data> for Impl { - fn from(value: Data) -> Self { - Self(value) - } - } - - impl<'ctx> Walk<'ctx> for Data { - type Walker = Impl; - } - - impl<'ctx> Walker<'ctx> for Impl { - type Effect = AsyncEffect; - - type Error = (); - - type Output = (); - - fn walk<'a>(self, visitor: &'a mut Visitor<'a, 'ctx>) -> ControlFlowFor<'a, AsyncEffect> { - Box::pin(async { - match self.0 { - Data::Bool(value) => walk_bool(value, visitor), - Data::Sequence(value) => walk_vec(value, visitor).await, - } - core::ops::ControlFlow::Continue(()) - }) - } - } -}; - -fn walk_bool(value: bool, visitor: &mut Visitor<'_, '_>) { - visitor - .upcast_mut::<dyn Value<OwnedStatic<bool>>>() - .unwrap() - .visit(OwnedStatic(value)); -} - -async fn walk_vec(value: Vec<Data>, visitor: &mut Visitor<'_, '_>) { - struct Scope(VecDeque<Data>); - - impl<'ctx> SequenceScope<'ctx, AsyncEffect> for Scope { - fn next<'a>( - &'a mut self, - visitor: &'a mut Visitor<'a, 'ctx>, - ) -> ControlFlowFor<'a, AsyncEffect, Status> { - Box::pin(async { - if let Some(value) = self.0.pop_front() { - into_walker(value).walk(visitor).await; - - ControlFlow::Continue(Status::Continue) - } else { - ControlFlow::Continue(Status::Done) - } - }) - } - } - - let mut scope = Scope(value.into()); - - visitor - .upcast_mut::<dyn Sequence<'_, AsyncEffect>>() - .unwrap() - .visit(&mut scope) - .await; -} - -#[derive(Default)] -struct JsonLike(String); - -impl<'ctx> Builder<'ctx> for JsonLike { - type Error = (); - - type Value = String; - - fn as_visitor(&mut self) -> &mut Visitor<'_, 'ctx> { - self - } - - fn build(self) -> Result<Self::Value, Self::Error> { - Ok(self.0) - } -} - -any_trait! { - impl['a, 'ctx] JsonLike = [ - dyn Value<'a, OwnedStatic<bool>> + 'a, - dyn Sequence<'ctx, AsyncEffect> + 'a, - ]; -} - -impl Value<'_, OwnedStatic<bool>> for JsonLike { - fn visit(&mut self, value: OwnedStatic<bool>) -> core::ops::ControlFlow<()> { - self.0.push_str(&format!("{}", value.0)); - std::ops::ControlFlow::Continue(()) - } -} - -impl<'ctx> Sequence<'ctx, AsyncEffect> for JsonLike { - fn visit<'a>( - &'a mut self, - scope: &'a mut dyn SequenceScope<'ctx, AsyncEffect>, - ) -> ControlFlowFor<'a, AsyncEffect> { - Box::pin(async { - self.0.push_str("["); - while let std::ops::ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) = - scope.next(self).await - { - self.0.push_str(","); - } - self.0.push_str("]"); - std::ops::ControlFlow::Continue(()) - }) - } -} diff --git a/src/mock/builder.rs b/tests/common/builder.rs index 9fef358..d2b182f 100644 --- a/src/mock/builder.rs +++ b/tests/common/builder.rs @@ -1,12 +1,7 @@ use mockall::mock; +use treaty::{any::{indirect, AnyTrait, AnyTraitObject, TypeNameId}, effect::{Effect, Future}, protocol::Visitor, Builder, BuilderTypes}; -use crate::{ - any::{indirect, AnyTrait, AnyTraitObject, TypeNameId}, - effect::{Effect, Future}, - mock::{ContextLock, StaticTypeMap}, - protocol::Visitor, - Builder, BuilderTypes, -}; +use crate::common::{ContextLock, StaticTypeMap}; use self::__mock_MockBuilder::__from_seed::Context; @@ -44,33 +39,29 @@ impl<Seed: 'static, Value: 'static, Error: 'static> MockBuilder<Seed, Value, Err } } -impl<'ctx, Seed: Send, Value: Send, Error: Send, E: Effect<'ctx>> Builder<'ctx, E> +impl<'ctx, Seed: Send, Value: Send, Error: Send, E: Effect> Builder<'ctx, E> for MockBuilder<Seed, Value, Error> { - #[track_caller] - fn from_seed<'a>(seed: Self::Seed) -> Future<'a, 'ctx, Self, E> + fn from_seed<'a>(seed: Self::Seed) -> Future<'a, Self, E> where Self: 'a, { E::ready(Self::from_seed(seed)) } - #[track_caller] - fn build<'a>(self) -> Future<'a, 'ctx, Result<Self::Value, Self::Error>, E> + fn build<'a>(self) -> Future<'a, Result<Self::Value, Self::Error>, E> where Self: 'a, { E::ready(self.build()) } - #[track_caller] fn as_visitor(&mut self) -> Visitor<'_, 'ctx> { self } } impl<'ctx, Seed, Value, Error> AnyTrait<'ctx> for MockBuilder<Seed, Value, Error> { - #[track_caller] fn upcast_to_id<'a>(&'a self, id: TypeNameId) -> Option<AnyTraitObject<'a, 'ctx, indirect::Ref>> where 'ctx: 'a, @@ -79,7 +70,6 @@ impl<'ctx, Seed, Value, Error> AnyTrait<'ctx> for MockBuilder<Seed, Value, Error self.traits(id).as_ref().and_then(|t| t.upcast_to_id(id)) } - #[track_caller] fn upcast_to_id_mut<'a>( &'a mut self, id: TypeNameId, diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..8b9fb03 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,83 @@ +#![allow(unused)] + +use core::{ + any::{Any, TypeId}, + ops::Deref, +}; +use std::{ + collections::HashMap, + sync::{Mutex, MutexGuard, OnceLock, RwLock}, +}; + +pub mod builder; +pub mod protocol; + +pub struct StaticTypeMap { + map: OnceLock<RwLock<HashMap<TypeId, &'static (dyn Any + Send + Sync)>>>, +} + +impl StaticTypeMap { + pub const fn new() -> Self { + Self { + map: OnceLock::new(), + } + } + + pub fn get_or_init<T: Send + Sync + 'static, F: FnOnce() -> T>(&self, f: F) -> &'static T { + let map_init = || RwLock::new(HashMap::new()); + + let map = self.map.get_or_init(map_init).read().unwrap(); + + if let Some(once) = map.get(&TypeId::of::<T>()) { + return once.downcast_ref::<T>().unwrap(); + } + + drop(map); + + let mut map = self.map.get_or_init(map_init).write().unwrap(); + let once = &*Box::leak(Box::new(f())); + map.insert(TypeId::of::<T>(), once); + + once + } +} + +pub struct ContextLock<T> { + lock: Mutex<T>, + checkpoint: fn(&T), +} + +impl<T> ContextLock<T> { + pub const fn new(context: T, checkpoint: fn(&T)) -> Self { + Self { + lock: Mutex::new(context), + checkpoint, + } + } + + pub fn lock(&self) -> ContextGuard<'_, T> { + ContextGuard { + lock: self, + guard: self.lock.lock().unwrap(), + } + } +} + +pub struct ContextGuard<'a, T> { + lock: &'a ContextLock<T>, + guard: MutexGuard<'a, T>, +} + +impl<'a, T> Drop for ContextGuard<'a, T> { + fn drop(&mut self) { + (self.lock.checkpoint)(&*self.guard) + } +} + +impl<'a, T> Deref for ContextGuard<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.guard + } +} diff --git a/tests/common/protocol.rs b/tests/common/protocol.rs new file mode 100644 index 0000000..e33df66 --- /dev/null +++ b/tests/common/protocol.rs @@ -0,0 +1,2 @@ +pub mod visitor; +pub mod tag; diff --git a/src/mock/protocol/tag.rs b/tests/common/protocol/tag.rs index e1c9551..23916d1 100644 --- a/src/mock/protocol/tag.rs +++ b/tests/common/protocol/tag.rs @@ -1,11 +1,5 @@ use mockall::mock; - -use crate::{ - any_trait, - effect::{Effect, Future}, - protocol::visitor::tag::{DynTag, Tag, TagKind}, - DynWalker, -}; +use treaty::{any::any_trait, effect::{Effect, Future}, protocol::visitor::tag::{DynTag, Tag, TagKind}, DynWalker}; mock! { pub TagVisitor<K: TagKind, E> { @@ -18,16 +12,15 @@ any_trait! { DynTag<'ctx, K, E>, ] where K: TagKind, - E: Effect<'ctx>, + E: Effect, } -impl<'ctx, K: TagKind, E: Effect<'ctx>> Tag<'ctx, K, E> for MockTagVisitor<K, E> { - #[track_caller] +impl<'ctx, K: TagKind, E: Effect> Tag<'ctx, K, E> for MockTagVisitor<K, E> { fn visit<'a>( &'a mut self, kind: K, walker: DynWalker<'a, 'ctx, E>, - ) -> Future<'a, 'ctx, <K as TagKind>::Flow, E> { + ) -> Future<'a, <K as TagKind>::Flow, E> { E::ready(self.visit(kind, walker)) } } diff --git a/src/mock/protocol/value.rs b/tests/common/protocol/visitor.rs index eca11ee..a71e9ec 100644 --- a/src/mock/protocol/value.rs +++ b/tests/common/protocol/visitor.rs @@ -1,12 +1,5 @@ use mockall::mock; - -use crate::{ - any::{TypeName, WithContextLt}, - any_trait, - effect::{Effect, Future}, - protocol::visitor::value::{DynValue, Value}, - Flow, -}; +use treaty::{any::{any_trait, TypeName, WithContextLt}, effect::{Effect, Future}, protocol::visitor::value::{DynValue, Value}, Flow}; mock! { pub ValueVisitor<T: for<'ctx> WithContextLt::MemberType<'ctx>, E> @@ -23,16 +16,16 @@ any_trait! { ] where T: for<'lt> TypeName::LowerType<'lt> + 'ctx, for<'a, 'lt> WithContextLt::T<'a, 'lt, T>: Sized, - E: Effect<'ctx>, + E: Effect, } -impl<'ctx, T: for<'lt> WithContextLt::MemberType<'lt>, E: Effect<'ctx>> Value<'ctx, T, E> +impl<'ctx, T: for<'lt> WithContextLt::MemberType<'lt>, E: Effect> Value<'ctx, T, E> for MockValueVisitor<T, E> where for<'a, 'lt> WithContextLt::T<'a, 'lt, T>: Sized, { - #[track_caller] - fn visit<'a>(&'a mut self, value: WithContextLt::T<'a, 'ctx, T>) -> Future<'a, 'ctx, Flow, E> { + fn visit<'a>(&'a mut self, value: WithContextLt::T<'a, 'ctx, T>) -> Future<'a, Flow, E> + where 'ctx: 'a { E::ready(self.visit(value)) } } diff --git a/tests/demo.rs b/tests/demo.rs deleted file mode 100644 index b6bf557..0000000 --- a/tests/demo.rs +++ /dev/null @@ -1,192 +0,0 @@ -use std::{collections::VecDeque, ops::ControlFlow}; -use treaty::{ - any::{any_trait, static_wrapper::OwnedStatic}, - build, build_with, - builders::core::array, - effect::{SyncEffect, Yield}, - into_walker, - protocol::{ - visitor::{Sequence, SequenceScope, Value}, - Visitor, - }, - AsVisitor, Builder, Walk, Walker, -}; - -#[test] -fn demo() { - let a = Data::Sequence(vec![ - Data::Bool(true), - Data::Sequence(vec![Data::Bool(false), Data::Bool(true)]), - Data::Bool(false), - ]); - - dbg!(array_to_array2([true, false])); - dbg!(array_to_array([true, true])); - - let s = build_with::<array::Builder<'_, JsonLike, 3, _>, _>(into_walker(&a)).unwrap(); - dbg!(s); - - use treaty::builders::serde::deserialize::Builder as SerdeBuilder; - - let x = build_with::<SerdeBuilder<serde_json::Value, _>, _>(into_walker(&a)).unwrap(); - dbg!(x); - - // let s = build_with::<JsonLike, _>(into_walker(a)).unwrap(); - - todo!(); - // assert_eq!(s, "[true,[false,true,],false,]"); -} - -#[inline(never)] -pub fn array_to_array(x: [bool; 2]) -> [bool; 2] { - build(into_walker(x)).unwrap() -} - -#[inline(never)] -pub fn array_to_array2(x: [bool; 2]) -> [bool; 2] { - array_to_array(x) -} - -#[derive(Debug)] -enum Data { - Bool(bool), - Sequence(Vec<Data>), -} - -const _: () = { - struct Impl<'ctx>(&'ctx Data); - - impl<'ctx> From<&'ctx Data> for Impl<'ctx> { - fn from(value: &'ctx Data) -> Self { - Self(value) - } - } - - impl<'ctx> Walk<'ctx> for &'ctx Data { - type Walker = Impl<'ctx>; - } - - impl<'ctx> Walker<'ctx> for Impl<'ctx> { - type Effect = SyncEffect; - - type Error = (); - - type Output = (); - - fn walk<'a>( - self, - visitor: Visitor<'a, 'ctx, SyncEffect>, - ) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, SyncEffect> - where - 'ctx: 'a, - { - match self.0 { - Data::Bool(value) => walk_bool(*value, visitor), - Data::Sequence(value) => walk_vec(value, visitor), - } - Ok(()) - } - } -}; - -fn walk_bool(value: bool, visitor: Visitor<'_, '_, SyncEffect>) { - visitor - .upcast_mut::<dyn Value<OwnedStatic<bool>, SyncEffect>>() - .unwrap() - .visit(OwnedStatic(value)); -} - -fn walk_vec<'a, 'ctx>(value: &'ctx [Data], visitor: Visitor<'a, 'ctx, SyncEffect>) { - struct Scope<'ctx>(VecDeque<&'ctx Data>); - - impl<'ctx> SequenceScope<'ctx, SyncEffect> for Scope<'ctx> { - fn next<'a>( - &'a mut self, - visitor: Visitor<'a, 'ctx, SyncEffect>, - ) -> Yield<'a, 'ctx, ControlFlow<(), treaty::protocol::visitor::Status>, SyncEffect> - where - 'ctx: 'a, - { - if let Some(value) = self.0.pop_front() { - into_walker(value).walk(visitor); - - ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) - } else { - ControlFlow::Continue(treaty::protocol::visitor::Status::Done) - } - } - } - - let mut scope = Scope(value.into_iter().collect()); - - visitor - .upcast_mut::<dyn Sequence<'_, SyncEffect>>() - .unwrap() - .visit(&mut scope); -} - -#[derive(Default)] -struct JsonLike(String); - -impl<'ctx> Builder<'ctx, SyncEffect> for JsonLike { - type Error = (); - - type Value = String; - - fn build<'a>(self) -> Result<Self::Value, Self::Error> - where - Self: 'a, - { - Ok(self.0) - } - - type Seed = (); - - fn from_seed(seed: Self::Seed) -> Self { - Self::default() - } - - type Effect = SyncEffect; -} - -impl<'ctx> AsVisitor<'ctx, SyncEffect> for JsonLike { - fn as_visitor(&mut self) -> Visitor<'_, 'ctx, SyncEffect> { - self - } -} - -any_trait! { - impl['a, 'ctx] JsonLike = [ - dyn Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> + 'a, - dyn Sequence<'ctx, SyncEffect> + 'a, - ] -} - -impl<'a, 'ctx: 'a> Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> for JsonLike { - fn visit( - &'a mut self, - value: OwnedStatic<bool>, - ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { - self.0.push_str(&format!("{}", value.0)); - ControlFlow::Continue(()) - } -} - -impl<'ctx> Sequence<'ctx, SyncEffect> for JsonLike { - fn visit<'a>( - &'a mut self, - scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>, - ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> - where - 'ctx: 'a, - { - self.0.push_str("["); - while let ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) = - scope.next(self) - { - self.0.push_str(","); - } - self.0.push_str("]"); - ControlFlow::Continue(()) - } -} diff --git a/tests/demo2.rs b/tests/demo2.rs deleted file mode 100644 index 4bb811a..0000000 --- a/tests/demo2.rs +++ /dev/null @@ -1,14 +0,0 @@ -use macro_rules_attribute::derive; -use uniserde::Build; - -#[derive(Build!)] -struct A { - b: B, - c: B, -} - -#[derive(Build!)] -struct B {} - -#[test] -fn demo() {} diff --git a/tests/hook.rs b/tests/hook.rs deleted file mode 100644 index 1cb633a..0000000 --- a/tests/hook.rs +++ /dev/null @@ -1,138 +0,0 @@ -use std::{marker::PhantomData, ops::ControlFlow, pin::Pin, thread::yield_now, time::Duration}; - -use treaty::{ - any::{any_trait, static_wrapper::OwnedStatic, AnyTrait, IndirectLtAny, LtTypeId}, - builders::core::option::IgnoreMissing, - effect::{BlockOn, Blocking, Effect, Future, Spin}, - protocol::visitor::value::Value, - protocol::Visitor, - transform, Build, Builder, Walk, Walker, WalkerTypes, -}; - -#[test] -fn demo() { - let hook = Hook::<_, Blocking> { - inner: true.into_walker::<Blocking>(), - _marker: PhantomData, - }; - // let x = build_with::<<bool as Build<_>>::Builder, _>(hook).unwrap(); - // dbg!(x); - // let x = Spin::block_on(transform::<<Option<bool> as Build>::Builder<_>, _, Blocking>(IgnoreMissing::No, hook)); - let x = Spin::block_on(transform::<<bool as Build>::Builder<_>, _, Blocking>( - (), - hook, - )); - dbg!(x); - todo!(); -} - -#[no_mangle] -fn invert(x: bool) -> bool { - let hook = Hook::<_, Blocking> { - inner: x.into_walker::<Blocking>(), - _marker: PhantomData, - }; - Spin::block_on(transform::<<bool as Build>::Builder<_>, _, Blocking>( - (), - hook, - )) - .0 - .unwrap() -} - -struct Hook<T, E> { - inner: T, - _marker: PhantomData<fn() -> E>, -} - -struct VisitorHook<'a, 'ctx: 'a, E> { - inner: Visitor<'a, 'ctx>, - _marker: PhantomData<fn() -> E>, -} - -impl<'ctx, T: Walker<'ctx, Effect = E>, E: Effect<'ctx>> WalkerTypes<'ctx> for Hook<T, E> { - type Error = T::Error; - - type Output = T::Output; -} - -impl<'ctx, T: Walker<'ctx, Effect = E>, E: Effect<'ctx>> Walker<'ctx> for Hook<T, E> { - type Effect = E; - - fn walk<'a>( - self, - visitor: Visitor<'a, 'ctx>, - ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E> - where - Self: 'a, - { - E::wrap(async { - let mut visitor = VisitorHook::<E> { - inner: visitor, - _marker: PhantomData, - }; - - let flow = self.inner.walk(&mut visitor); - - flow.await - }) - } -} - -impl<'b, 'ctx: 'b, E: Effect<'ctx>> AnyTrait<'ctx> for VisitorHook<'b, 'ctx, E> { - fn upcast_to_id<'a>( - &'a self, - id: treaty::any::LtTypeId<'ctx>, - ) -> Option<treaty::any::IndirectLtAny<'a, 'ctx, treaty::any::Ref>> - where - 'ctx: 'a, - { - match id { - id => self.inner.upcast_to_id(id), - } - } - - #[inline] - fn upcast_to_id_mut<'a>( - &'a mut self, - id: treaty::any::LtTypeId<'ctx>, - ) -> Option<treaty::any::IndirectLtAny<'a, 'ctx, treaty::any::Mut>> - where - 'ctx: 'a, - { - match id { - id if id == LtTypeId::of::<dyn Value<'a, 'ctx, OwnedStatic<bool>, E> + 'a>() => { - // println!("hook: {:?}", id); - if self.inner.upcast_to_id_mut(id).is_some() { - Some(IndirectLtAny::<'a, 'ctx, _>::new::< - dyn Value<'a, 'ctx, OwnedStatic<bool>, E> + 'a, - >(self as _)) - } else { - None - } - } - id => { - // println!("fallback: {:?}", id); - self.inner.upcast_to_id_mut(id) - } - } - } -} - -impl<'a, 'b, 'ctx: 'a + 'b, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<bool>, E> - for VisitorHook<'b, 'ctx, E> -{ - #[inline] - fn visit( - &'a mut self, - OwnedStatic(value): OwnedStatic<bool>, - ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> { - let visitor = self - .inner - .upcast_mut::<dyn Value<'a, 'ctx, OwnedStatic<bool>, E> + 'a>() - .unwrap(); - - // println!("Hooked bool: {}", value); - visitor.visit(OwnedStatic(!value)) - } -} diff --git a/tests/walk.rs b/tests/walk.rs new file mode 100644 index 0000000..f83ef24 --- /dev/null +++ b/tests/walk.rs @@ -0,0 +1,3 @@ +mod common; + +mod walkers; diff --git a/tests/walkers/core.rs b/tests/walkers/core.rs new file mode 100644 index 0000000..c10aef3 --- /dev/null +++ b/tests/walkers/core.rs @@ -0,0 +1 @@ +mod r#struct; diff --git a/tests/walkers/core/struct.rs b/tests/walkers/core/struct.rs new file mode 100644 index 0000000..9ea8c31 --- /dev/null +++ b/tests/walkers/core/struct.rs @@ -0,0 +1,132 @@ +use mockall::{predicate::eq, Sequence}; +use treaty::{any::{static_wrapper::{DynOwnedStatic, OwnedStatic}, TypeNameId}, effect::{BlockOn, Blocking, Effect, Future, Spin}, protocol::{visitor::{tag::{DynTag, TagConst}, value::DynValue}, Visitor}, walkers::core::{r#struct::{StructTypeInfo, StructWalker}, value::ValueWalker}, Builder, DefaultMode, Flow, Walker, TAG_STRUCT, TAG_TYPE_NAME}; + +use crate::common::{builder::MockBuilder, protocol::{tag::MockTagVisitor, visitor::MockValueVisitor}}; + +struct Demo { + a: bool, + b: bool, +} + +impl<'ctx, M> StructTypeInfo<'ctx, M> for Demo { + const NAME: &'static str = "Demo"; + + const FIELDS: &'static [&'static str] = &["a", "b"]; + + type FieldError = (); + + type T = Demo; + + fn walk_field<'a, E: Effect>( + index: usize, + value: &'ctx Self::T, + visitor: Visitor<'a, 'ctx>, + ) -> Future<'a, Result<Flow, Self::FieldError>, E> { + E::wrap(async move { + match index { + 0 => { + let walker = ValueWalker::<bool>::new(value.a); + Walker::<E>::walk(walker, visitor).await.unwrap(); + Ok(Flow::Continue) + } + 1 => { + let walker = ValueWalker::<bool>::new(value.b); + Walker::<E>::walk(walker, visitor).await.unwrap(); + Ok(Flow::Continue) + } + _ => Ok(Flow::Done), + } + }) + } +} + +#[test] +fn demo2() { + let mut builder = MockBuilder::<(), (), ()>::new(); + + let mut seq = Sequence::new(); + + builder + .expect_traits_mut() + .times(4) + .in_sequence(&mut seq) + .return_var(None); + + builder + .expect_traits_mut() + .once() + .with(eq(TypeNameId::of::< + DynTag<'static, TagConst<{ TAG_STRUCT.to_int() }>, Blocking>, + >())) + .in_sequence(&mut seq) + .return_var(Some(Box::new({ + let mut mock = MockTagVisitor::<TagConst<{ TAG_STRUCT.to_int() }>, Blocking>::new(); + + mock.expect_visit().once().returning(|_, walker| { + let mut builder = MockBuilder::<(), (), ()>::new(); + assert_eq!( + Spin::block_on(walker.walk(Builder::<Blocking>::as_visitor(&mut builder))), + Flow::Done + ); + + Flow::Continue + }); + + mock + }))); + + builder + .expect_traits_mut() + .once() + .with(eq(TypeNameId::of::< + DynTag<'static, TagConst<{ TAG_TYPE_NAME.to_int() }>, Blocking>, + >())) + .in_sequence(&mut seq) + .return_var(Some(Box::new({ + let mut mock = + MockTagVisitor::<TagConst<{ TAG_TYPE_NAME.to_int() }>, Blocking>::new(); + + mock.expect_visit().return_once(|_, walker| { + let mut builder = MockBuilder::<(), (), ()>::new(); + + builder + .expect_traits_mut() + .once() + .with(eq(TypeNameId::of::< + DynValue<'static, DynOwnedStatic<&'static str>, Blocking>, + >())) + .return_var(Some(Box::new({ + let mut mock = + MockValueVisitor::<DynOwnedStatic<&'static str>, Blocking>::new(); + + mock.expect_visit() + .once() + .with(eq(OwnedStatic("Demo"))) + .return_const(Flow::Done); + + mock + }))); + + assert_eq!( + Spin::block_on(walker.walk(Builder::<Blocking>::as_visitor(&mut builder))), + Flow::Done + ); + + Flow::Continue + }); + + mock + }))); + + builder + .expect_traits_mut() + .times(3) + .in_sequence(&mut seq) + .return_var(None); + + let value = Demo { a: true, b: false }; + + let walker = StructWalker::<Demo, Demo, DefaultMode, Blocking>::new(&value); + + Spin::block_on(walker.walk(Builder::<Blocking>::as_visitor(&mut builder))).unwrap(); +} diff --git a/tests/walkers/mod.rs b/tests/walkers/mod.rs new file mode 100644 index 0000000..9816037 --- /dev/null +++ b/tests/walkers/mod.rs @@ -0,0 +1 @@ +mod core; |