GATs but not
| -rw-r--r-- | Cargo.lock | 105 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/build.rs | 132 | ||||
| -rw-r--r-- | src/build/builders/core/array.rs | 49 | ||||
| -rw-r--r-- | src/build/builders/core/bool.rs | 46 | ||||
| -rw-r--r-- | src/build/builders/serde/deserialize.rs | 47 | ||||
| -rw-r--r-- | src/build/builders/serde/deserialize_seed.rs | 52 | ||||
| -rw-r--r-- | src/lib.rs | 8 | ||||
| -rw-r--r-- | src/protocol.rs | 132 | ||||
| -rw-r--r-- | src/protocol/visitor/request_hint.rs | 10 | ||||
| -rw-r--r-- | src/protocol/visitor/sequence.rs | 34 | ||||
| -rw-r--r-- | src/protocol/visitor/tagged.rs | 29 | ||||
| -rw-r--r-- | src/protocol/visitor/value.rs | 20 | ||||
| -rw-r--r-- | src/protocol/walker/hint.rs | 29 | ||||
| -rw-r--r-- | src/walk.rs | 8 | ||||
| -rw-r--r-- | src/walk/walkers/core/array.rs | 17 | ||||
| -rw-r--r-- | src/walk/walkers/core/bool.rs | 10 | ||||
| -rw-r--r-- | tests/hook.rs | 175 |
18 files changed, 679 insertions, 225 deletions
@@ -109,6 +109,95 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] name = "getrandom" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -278,6 +367,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -465,6 +560,15 @@ dependencies = [ ] [[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] name = "smallvec" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -538,6 +642,7 @@ dependencies = [ name = "treaty" version = "0.1.0" dependencies = [ + "futures", "macro_rules_attribute", "proptest", "serde", @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +futures = "0.3.30" serde = { version = "1.0", default-features = false, optional = true } [features] diff --git a/src/build.rs b/src/build.rs index b17413a..ebea4ff 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,14 +1,14 @@ -pub mod builders; +// pub mod builders; use crate::{ - protocol::{SyncEffect, Visitor}, + protocol::{AnyTraitSendObj as _, Effect, SyncEffect, Visitor}, Walker, }; /// A buildable type. -pub trait Build<'ctx>: Sized { +pub trait Build<'ctx, E: Effect<'ctx>>: Sized { /// The builder that can be used to build a value of `Self`. - type Builder: Builder<'ctx, Value = Self>; + type Builder: Builder<'ctx, E, Value = Self>; } /// Builder for a type. @@ -24,7 +24,7 @@ pub trait Build<'ctx>: Sized { /// 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> { +pub trait Builder<'ctx, E: Effect<'ctx>>: AsVisitor<'ctx, E> { type Seed; /// Error that can happen during filling the builder with data. @@ -35,11 +35,6 @@ pub trait Builder<'ctx> { fn from_seed(seed: Self::Seed) -> Self; - /// Get the builder as a visitor that a walker can use. - /// - /// This is expected to just be `self`. - fn as_visitor(&mut self) -> &mut Visitor<'_, 'ctx>; - /// Finish the value. /// /// If an error happened with the builder during the walk @@ -47,11 +42,18 @@ pub trait Builder<'ctx> { fn build(self) -> Result<Self::Value, Self::Error>; } -pub trait DefaultBuilder<'ctx>: Builder<'ctx> { +pub trait AsVisitor<'ctx, E: Effect<'ctx>> { + /// Get the builder as a visitor that a walker can use. + /// + /// This is expected to just be `self`. + fn as_visitor(&mut self) -> Visitor<'_, 'ctx, E>; +} + +pub trait DefaultBuilder<'ctx, E: Effect<'ctx>>: Builder<'ctx, E> { fn default() -> Self; } -impl<'ctx, B: Builder<'ctx>> DefaultBuilder<'ctx> for B +impl<'ctx, B: Builder<'ctx, E>, E: Effect<'ctx>> DefaultBuilder<'ctx, E> for B where B::Seed: Default, { @@ -66,53 +68,59 @@ pub enum BuildError<B, W> { Walker(W), } -#[inline] -pub fn build<'ctx, T: Build<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( - walker: W, -) -> Result<T, BuildError<<<T as Build<'ctx>>::Builder as Builder<'ctx>>::Error, W::Error>> -where - <<T as Build<'ctx>>::Builder as Builder<'ctx>>::Seed: Default, -{ - let mut builder = T::Builder::from_seed(Default::default()); - - if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()) { - return Err(BuildError::Walker(err)); - } - - builder.build().map_err(BuildError::Builder) -} - -pub fn build_with<'ctx, B: Builder<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( - walker: W, -) -> Result<B::Value, BuildError<B::Error, W::Error>> -where - <B as Builder<'ctx>>::Seed: Default, -{ - let mut builder = B::from_seed(Default::default()); - - if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()) { - return Err(BuildError::Walker(err)); - } - - builder.build().map_err(BuildError::Builder) -} - -#[cfg(feature = "alloc")] -use crate::protocol::AsyncEffect; - -#[cfg(feature = "alloc")] -pub async fn async_build_with< - 'ctx, - B: DefaultBuilder<'ctx>, - W: Walker<'ctx, Effect = AsyncEffect>, ->( - walker: W, -) -> Result<B::Value, BuildError<B::Error, W::Error>> { - let mut builder = B::default(); - - if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()).await { - return Err(BuildError::Walker(err)); - } - - builder.build().map_err(BuildError::Builder) -} +// #[inline] +// pub fn build<'ctx, T: Build<'ctx, SyncEffect>, W: for<'a> Walker<'a, 'ctx, Effect = SyncEffect>>( +// walker: W, +// ) -> Result< +// T, +// BuildError< +// <<T as Build<'ctx, SyncEffect>>::Builder as Builder<'ctx, SyncEffect>>::Error, +// W::Error, +// >, +// > +// where +// <<T as Build<'ctx, SyncEffect>>::Builder as Builder<'ctx, SyncEffect>>::Seed: Default, +// { +// let mut builder = T::Builder::from_seed(Default::default()); +// +// if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor().as_obj_mut()) { +// return Err(BuildError::Walker(err)); +// } +// +// builder.build().map_err(BuildError::Builder) +// } +// +// pub fn build_with<'ctx, B: Builder<'ctx, SyncEffect>, W: for<'a> Walker<'a, 'ctx, Effect = SyncEffect>>( +// walker: W, +// ) -> Result<B::Value, BuildError<B::Error, W::Error>> +// where +// <B as Builder<'ctx, SyncEffect>>::Seed: Default, +// { +// let mut builder = B::from_seed(Default::default()); +// +// if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor().as_obj_mut()) { +// return Err(BuildError::Walker(err)); +// } +// +// builder.build().map_err(BuildError::Builder) +// } + +// #[cfg(feature = "alloc")] +// use crate::protocol::AsyncEffect; +// +// #[cfg(feature = "alloc")] +// pub async fn async_build_with< +// 'ctx, +// B: DefaultBuilder<'ctx, AsyncEffect>, +// W: for<'a> Walker<'a, 'ctx, Effect = AsyncEffect>, +// >( +// walker: W, +// ) -> Result<B::Value, BuildError<B::Error, W::Error>> { +// let mut builder = B::default(); +// +// if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()).await { +// return Err(BuildError::Walker(err)); +// } +// +// builder.build().map_err(BuildError::Builder) +// } diff --git a/src/build/builders/core/array.rs b/src/build/builders/core/array.rs index 8638fae..0c07561 100644 --- a/src/build/builders/core/array.rs +++ b/src/build/builders/core/array.rs @@ -1,12 +1,12 @@ -use core::{mem::MaybeUninit, ops::ControlFlow}; +use core::{marker::PhantomData, mem::MaybeUninit, ops::ControlFlow}; use crate::{ any_trait, protocol::{ visitor::{Sequence, SequenceScope, Status}, - ControlFlowFor, Effect, + AnyTraitObj, AnyTraitSendObj as _, ControlFlowFor, Effect, SyncEffect, }, - DefaultBuilder, + AsVisitor, DefaultBuilder, }; #[cfg(feature = "alloc")] @@ -15,12 +15,13 @@ use crate::protocol::AsyncEffect; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; -impl<'ctx, T, const N: usize> crate::Build<'ctx> for [T; N] +impl<'ctx, T, const N: usize, E: for<'a> Effect<'a, 'ctx>> crate::Build<'ctx, E> for [T; N] where - T: crate::Build<'ctx>, - <T as crate::Build<'ctx>>::Builder: DefaultBuilder<'ctx>, + T: crate::Build<'ctx, E>, + <T as crate::Build<'ctx, E>>::Builder: DefaultBuilder<'ctx, E>, + Builder<'ctx, T::Builder, N, E>: AsVisitor<'ctx, E>, { - type Builder = Builder<'ctx, T::Builder, N>; + type Builder = Builder<'ctx, T::Builder, N, E>; } #[derive(Debug)] @@ -29,23 +30,22 @@ pub enum ArrayError<E> { Item(usize, E), } -pub struct Builder<'ctx, B: crate::Builder<'ctx>, const N: usize> { +pub struct Builder<'ctx, B: crate::Builder<'ctx, E>, const N: usize, E: for<'a> Effect<'a, 'ctx>> { array: MaybeUninit<[B::Value; N]>, index: usize, item_err: Option<(usize, B::Error)>, + _marker: PhantomData<fn() -> E>, } -impl<'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize> crate::Builder<'ctx> - for Builder<'ctx, B, N> +impl<'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: for<'a> Effect<'a, 'ctx>> crate::Builder<'ctx, E> + for Builder<'ctx, B, N, E> +where + Self: AsVisitor<'ctx, E>, { type Error = ArrayError<B::Error>; type Value = [B::Value; N]; - fn as_visitor(&mut self) -> &mut crate::protocol::Visitor<'_, 'ctx> { - self - } - fn build(self) -> Result<Self::Value, Self::Error> { if let Some((index, err)) = self.item_err { return Err(ArrayError::Item(index, err)); @@ -65,14 +65,23 @@ impl<'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize> crate::Builder<'ctx> array: MaybeUninit::uninit(), index: 0, item_err: None, + _marker: PhantomData, } } } +impl<'ctx, B: crate::DefaultBuilder<'ctx, SyncEffect>, const N: usize> AsVisitor<'ctx, SyncEffect> + for Builder<'ctx, B, N, SyncEffect> +{ + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { + AnyTraitObj::from_obj(self) + } +} + // #[cfg(not(feature = "alloc"))] any_trait! { - impl['a, 'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize] Builder<'ctx, B, N> = [ - dyn Sequence<'ctx> + 'a, + impl['a, 'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: Effect<'a, 'ctx>] Builder<'ctx, B, N, E> = [ + dyn Sequence<'a, 'ctx> + 'a, ] } @@ -84,9 +93,11 @@ any_trait! { // ] // } -impl<'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize> Sequence<'ctx> for Builder<'ctx, B, N> { +impl<'a, 'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: Effect<'a, 'ctx>> Sequence<'a, 'ctx> + for Builder<'ctx, B, N, E> +{ #[inline] - fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a> { + fn visit(&'a mut self, scope: &'a mut dyn for<'b> SequenceScope<'b, 'ctx>) -> ControlFlowFor<'a, 'ctx> { loop { // Check if the array is full. if self.index >= N { @@ -95,7 +106,7 @@ impl<'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize> Sequence<'ctx> for Bu // Try to build the next value. let mut builder = B::default(); - match scope.next(builder.as_visitor()) { + match scope.next(builder.as_visitor().into_obj()) { ControlFlow::Continue(Status::Done) => { // The sequence is done so the builder wasn't given a value. // We just throw away the empty builder. diff --git a/src/build/builders/core/bool.rs b/src/build/builders/core/bool.rs index 56ef873..6d80d39 100644 --- a/src/build/builders/core/bool.rs +++ b/src/build/builders/core/bool.rs @@ -1,13 +1,20 @@ -use core::ops::ControlFlow; +use core::{marker::PhantomData, ops::ControlFlow}; use crate::{ any::static_wrapper::OwnedStatic, any_trait, - protocol::{visitor::Value, ControlFlowFor, Effect, SyncEffect}, + protocol::{ + visitor::Value, AnyTraitObj, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, + SyncEffect, + }, + AsVisitor, }; -impl<'ctx> crate::Build<'ctx> for bool { - type Builder = Builder; +impl<'ctx, E: for<'a> Effect<'a, 'ctx>> crate::Build<'ctx, E> for bool +where + Builder<E>: AsVisitor<'ctx, E>, +{ + type Builder = Builder<E>; } #[derive(Debug)] @@ -15,17 +22,16 @@ pub enum Error { Incomplete, } -pub struct Builder(Option<bool>); +pub struct Builder<E>(Option<bool>, PhantomData<fn() -> E>); -impl<'ctx> crate::Builder<'ctx> for Builder { +impl<'ctx, E: for<'a> Effect<'a, 'ctx>> crate::Builder<'ctx, E> for Builder<E> +where + Self: AsVisitor<'ctx, E>, +{ type Error = Error; type Value = bool; - fn as_visitor(&mut self) -> &mut crate::protocol::Visitor<'_, 'ctx> { - self - } - #[inline] fn build(self) -> Result<Self::Value, Self::Error> { self.0.ok_or(Error::Incomplete) @@ -34,19 +40,31 @@ impl<'ctx> crate::Builder<'ctx> for Builder { type Seed = (); fn from_seed(seed: Self::Seed) -> Self { - Self(None) + Self(None, PhantomData) + } +} + +impl<'ctx> AsVisitor<'ctx, SyncEffect> for Builder<SyncEffect> { + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { + AnyTraitObj::from_obj(self) + } +} + +impl<'ctx> AsVisitor<'ctx, AsyncEffect> for Builder<AsyncEffect> { + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncEffect> { + AnyTraitSendObj::from_obj_send(self) } } any_trait! { - impl['a, 'ctx] Builder = [ + impl['a, 'ctx, E] Builder<E> = [ dyn Value<'a, OwnedStatic<bool>> + 'a, ] } -impl<'a> Value<'a, OwnedStatic<bool>> for Builder { +impl<'a, 'ctx, E> Value<'a, 'ctx, OwnedStatic<bool>> for Builder<E> { #[inline] - fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a> { + fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a, 'ctx> { self.0 = Some(value); ControlFlow::Continue(()) } diff --git a/src/build/builders/serde/deserialize.rs b/src/build/builders/serde/deserialize.rs index 1c24e6e..664647d 100644 --- a/src/build/builders/serde/deserialize.rs +++ b/src/build/builders/serde/deserialize.rs @@ -1,6 +1,6 @@ //! Adapter for serde's Deserialize trait. -use core::ops::ControlFlow; +use core::{marker::PhantomData, ops::ControlFlow}; use serde::{de::SeqAccess, forward_to_deserialize_any, Deserialize, Deserializer}; @@ -9,9 +9,9 @@ use crate::{ any_trait, protocol::{ visitor::{Sequence, SequenceScope, Status, Value}, - ControlFlowFor, + AnyTraitObj, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, SyncEffect, }, - Builder as _, + AsVisitor, Builder as _, }; #[derive(Debug)] @@ -23,17 +23,16 @@ pub enum Error { #[cfg(feature = "std")] impl std::error::Error for Error {} -pub struct Builder<T>(Result<T, Error>); +pub struct Builder<T, E>(Result<T, Error>, PhantomData<fn() -> E>); -impl<'ctx, T: Deserialize<'ctx>> crate::Builder<'ctx> for Builder<T> { +impl<'ctx, T: Deserialize<'ctx>, E: for<'a> Effect<'a, 'ctx>> crate::Builder<'ctx, E> for Builder<T, E> +where + Self: AsVisitor<'ctx, E>, +{ type Error = Error; type Value = T; - fn as_visitor(&mut self) -> &mut crate::protocol::Visitor<'_, 'ctx> { - self - } - fn build(self) -> Result<Self::Value, Self::Error> { self.0 } @@ -41,12 +40,24 @@ impl<'ctx, T: Deserialize<'ctx>> crate::Builder<'ctx> for Builder<T> { type Seed = (); fn from_seed(seed: Self::Seed) -> Self { - Self(Err(Error::Incomplete)) + Self(Err(Error::Incomplete), PhantomData) + } +} + +impl<'ctx, T: Deserialize<'ctx>> AsVisitor<'ctx, SyncEffect> for Builder<T, SyncEffect> { + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { + AnyTraitObj::from_obj(self) + } +} + +impl<'ctx, T: Deserialize<'ctx> + Send> AsVisitor<'ctx, AsyncEffect> for Builder<T, AsyncEffect> { + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncEffect> { + AnyTraitSendObj::from_obj_send(self) } } any_trait! { - impl['a, 'ctx, T: Deserialize<'ctx>] Builder<T> = [ + impl['a, 'ctx, T: Deserialize<'ctx>, E] Builder<T, E> = [ dyn Value<'a, OwnedStatic<bool>> + 'a, dyn Sequence<'ctx> + 'a, ] @@ -54,12 +65,12 @@ any_trait! { enum InjectedValue<'a, 'ctx> { Bool(bool), - Sequence(&'a mut dyn SequenceScope<'ctx>), + Sequence(&'a mut dyn for<'b> SequenceScope<'b, 'ctx>), } -impl<'a, 'ctx, T: Deserialize<'ctx>> Value<'a, OwnedStatic<bool>> for Builder<T> { +impl<'a, 'ctx, T: Deserialize<'ctx>, E> Value<'a, 'ctx, OwnedStatic<bool>> for Builder<T, E> { #[inline] - fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a> { + fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a, 'ctx> { self.0 = T::deserialize(InjectedValue::Bool(value)); if self.0.is_err() { @@ -70,9 +81,9 @@ impl<'a, 'ctx, T: Deserialize<'ctx>> Value<'a, OwnedStatic<bool>> for Builder<T> } } -impl<'ctx, T: Deserialize<'ctx>> Sequence<'ctx> for Builder<T> { +impl<'a, 'ctx, T: Deserialize<'ctx>, E> Sequence<'a, 'ctx> for Builder<T, E> { #[inline] - fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a> { + fn visit(&'a mut self, scope: &'a mut dyn for<'b> SequenceScope<'b, 'ctx>) -> ControlFlowFor<'a, 'ctx> { self.0 = T::deserialize(InjectedValue::Sequence(scope)); if self.0.is_err() { @@ -119,7 +130,7 @@ impl<'a, 'ctx> Deserializer<'ctx> for InjectedValue<'a, 'ctx> { } } -struct SequenceAccess<'a, 'ctx>(&'a mut dyn SequenceScope<'ctx>); +struct SequenceAccess<'a, 'ctx>(&'a mut dyn for<'b> SequenceScope<'b, 'ctx>); impl<'a, 'ctx> SeqAccess<'ctx> for SequenceAccess<'a, 'ctx> { type Error = Error; @@ -128,7 +139,7 @@ impl<'a, 'ctx> SeqAccess<'ctx> for SequenceAccess<'a, 'ctx> { where T: serde::de::DeserializeSeed<'ctx>, { - let mut builder = super::deserialize_seed::Builder::from_seed(seed); + let mut builder = super::deserialize_seed::Builder::<_, SyncEffect>::from_seed(seed); match self.0.next(builder.as_visitor()) { ControlFlow::Continue(Status::Continue) => match builder.build() { Ok(value) => Ok(Some(value)), diff --git a/src/build/builders/serde/deserialize_seed.rs b/src/build/builders/serde/deserialize_seed.rs index 614cbda..866206c 100644 --- a/src/build/builders/serde/deserialize_seed.rs +++ b/src/build/builders/serde/deserialize_seed.rs @@ -12,9 +12,9 @@ use crate::{ any_trait, protocol::{ visitor::{Sequence, SequenceScope, Status, Value}, - ControlFlowFor, + AnyTraitObj, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, SyncEffect, }, - Builder as _, + AsVisitor, Builder as _, }; pub enum Error<T> { @@ -36,17 +36,19 @@ impl<T> core::fmt::Debug for Error<T> { } } -pub struct Builder<'ctx, T: DeserializeSeed<'ctx>>(Result<T::Value, Error<T>>); +pub struct Builder<'ctx, T: DeserializeSeed<'ctx>, E>( + Result<T::Value, Error<T>>, + PhantomData<fn() -> E>, +); -impl<'ctx, T: DeserializeSeed<'ctx>> crate::Builder<'ctx> for Builder<'ctx, T> { +impl<'ctx, T: DeserializeSeed<'ctx>, E: for<'a> Effect<'a, 'ctx>> crate::Builder<'ctx, E> for Builder<'ctx, T, E> +where + Self: AsVisitor<'ctx, E>, +{ type Error = Error<T>; type Value = T::Value; - fn as_visitor(&mut self) -> &mut crate::protocol::Visitor<'_, 'ctx> { - self - } - fn build(self) -> Result<Self::Value, Self::Error> { self.0 } @@ -54,12 +56,28 @@ impl<'ctx, T: DeserializeSeed<'ctx>> crate::Builder<'ctx> for Builder<'ctx, T> { type Seed = T; fn from_seed(seed: Self::Seed) -> Self { - Self(Err(Error::Pending(seed))) + Self(Err(Error::Pending(seed)), PhantomData) + } +} + +impl<'ctx, T: DeserializeSeed<'ctx>> AsVisitor<'ctx, SyncEffect> for Builder<'ctx, T, SyncEffect> { + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { + AnyTraitObj::from_obj(self) + } +} + +impl<'ctx, T: DeserializeSeed<'ctx> + Send> AsVisitor<'ctx, AsyncEffect> + for Builder<'ctx, T, AsyncEffect> +where + T::Value: Send, +{ + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncEffect> { + AnyTraitSendObj::from_obj_send(self) } } any_trait! { - impl['a, 'ctx, T: DeserializeSeed<'ctx>] Builder<'ctx, T> = [ + impl['a, 'ctx, T: DeserializeSeed<'ctx>, E] Builder<'ctx, T, E> = [ dyn Value<'a, OwnedStatic<bool>> + 'a, dyn Sequence<'ctx> + 'a, ] @@ -67,13 +85,13 @@ any_trait! { enum InjectedValue<'a, 'ctx, T> { Bool(bool), - Sequence(&'a mut dyn SequenceScope<'ctx>), + Sequence(&'a mut dyn for<'b> SequenceScope<'b, 'ctx>), Extra(PhantomData<T>), } -impl<'a, 'ctx, T: DeserializeSeed<'ctx>> Value<'a, OwnedStatic<bool>> for Builder<'ctx, T> { +impl<'a, 'ctx, T: DeserializeSeed<'ctx>, E> Value<'a, 'ctx, OwnedStatic<bool>> for Builder<'ctx, T, E> { #[inline] - fn visit(&'a mut self, OwnedStatic(bool_value): OwnedStatic<bool>) -> ControlFlowFor<'a> { + fn visit(&'a mut self, OwnedStatic(bool_value): OwnedStatic<bool>) -> ControlFlowFor<'a, 'ctx> { let pending = core::mem::replace(&mut self.0, Err(Error::Incomplete)); let Err(Error::Pending(value)) = pending else { todo!() @@ -89,9 +107,9 @@ impl<'a, 'ctx, T: DeserializeSeed<'ctx>> Value<'a, OwnedStatic<bool>> for Builde } } -impl<'ctx, T: DeserializeSeed<'ctx>> Sequence<'ctx> for Builder<'ctx, T> { +impl<'a, 'ctx, T: DeserializeSeed<'ctx>, E> Sequence<'a, 'ctx> for Builder<'ctx, T, E> { #[inline] - fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a> { + fn visit(&'a mut self, scope: &'a mut dyn for<'b> SequenceScope<'b, 'ctx>) -> ControlFlowFor<'a, 'ctx> { let pending = core::mem::replace(&mut self.0, Err(Error::Incomplete)); let Err(Error::Pending(value)) = pending else { todo!() @@ -144,7 +162,7 @@ impl<'a, 'ctx, T> Deserializer<'ctx> for InjectedValue<'a, 'ctx, T> { } } -struct SequenceAccess<'a, 'ctx, T>(&'a mut dyn SequenceScope<'ctx>, PhantomData<T>); +struct SequenceAccess<'a, 'ctx, T>(&'a mut dyn for<'b> SequenceScope<'b, 'ctx>, PhantomData<T>); impl<'a, 'ctx, T> SeqAccess<'ctx> for SequenceAccess<'a, 'ctx, T> { type Error = Error<T>; @@ -153,7 +171,7 @@ impl<'a, 'ctx, T> SeqAccess<'ctx> for SequenceAccess<'a, 'ctx, T> { where U: serde::de::DeserializeSeed<'ctx>, { - let mut builder = Builder::from_seed(seed); + let mut builder = Builder::<_, SyncEffect>::from_seed(seed); match self.0.next(builder.as_visitor()) { ControlFlow::Continue(Status::Continue) => match builder.build() { Ok(value) => Ok(Some(value)), @@ -8,10 +8,10 @@ extern crate alloc; pub mod any; -mod build; +// mod build; pub mod protocol; pub mod symbol; -mod walk; +// mod walk; // pub mod impls; // pub mod transform; @@ -22,8 +22,8 @@ mod walk; // pub use walk::Walk; // pub use walk::Walker; -pub use build::*; -pub use walk::*; +// pub use build::*; +// pub use walk::*; #[macro_export] macro_rules! Build { diff --git a/src/protocol.rs b/src/protocol.rs index c763730..fccb8ed 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -38,43 +38,143 @@ use core::{ pin::{pin, Pin}, ptr, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + marker::PhantomData, }; use crate::any::AnyTrait; -pub mod visitor; -pub mod walker; +// pub mod visitor; +// pub mod walker; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; -pub type Visitor<'a, 'ctx> = dyn AnyTrait<'ctx> + 'a; -pub type Walker<'a, 'ctx> = dyn AnyTrait<'ctx> + 'a; +pub type Visitor<'a, 'ctx, Effect> = <<Effect as self::Effect<'ctx>>::VisitorHkt as ForLtAnyTraitSendObj<'a, 'ctx, Bound<'a, 'ctx>>>::T; +pub type Walker<'a, 'ctx, Effect> = <<Effect as self::Effect<'ctx>>::WalkerHkt as ForLtAnyTraitSendObj<'a, 'ctx, Bound<'a, 'ctx>>>::T; -pub trait Effect: 'static { - type ControlFlow<'a, C, B>; +pub trait AnyTraitObj<'a, 'ctx: 'a>: AnyTraitSendObj<'a, 'ctx> { + fn from_obj(value: &'a mut (dyn AnyTrait<'ctx> + 'a)) -> Self; } -pub type ControlFlowFor<'a, E = SyncEffect, C = (), B = ()> = <E as Effect>::ControlFlow<'a, C, B>; +// Lifetime bound to be used in `for<'lt>` blocks. +pub type Bound<'lt, 'bound> = &'lt &'bound (); + +pub trait ForLtAnyTraitSendObj<'lt, 'ctx: 'lt, B> { + type T: AnyTraitSendObj<'lt, 'ctx>; +} + +pub trait HktAnyTraitSendObj<'ctx>: for<'lt> ForLtAnyTraitSendObj<'lt, 'ctx, Bound<'lt, 'ctx>> {} +impl<'ctx, T> HktAnyTraitSendObj<'ctx> for T where T: for<'lt> ForLtAnyTraitSendObj<'lt, 'ctx, Bound<'lt, 'ctx>> {} + +pub trait ForLt<'lt, 'ctx: 'lt, B> { + type T; +} + +pub trait Hkt<'ctx>: for<'lt> ForLt<'lt, 'ctx, Bound<'lt, 'ctx>> {} +impl<'ctx, T> Hkt<'ctx> for T where T: for<'lt> ForLt<'lt, 'ctx, Bound<'lt, 'ctx>> {} + +pub trait AnyTraitSendObj<'a, 'ctx: 'a> { + fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self; + fn as_obj(&self) -> &dyn AnyTrait<'ctx>; + fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx>; + fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx>; +} + +impl<'a, 'ctx: 'a> AnyTraitSendObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) { + fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self { + value + } + + fn as_obj(&self) -> &dyn AnyTrait<'ctx> { + *self + } + + fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx> { + *self + } + + fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx> { + self + } +} + +impl<'a, 'ctx: 'a> AnyTraitSendObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + Send + 'a) { + fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self { + value + } + + fn as_obj(&self) -> &dyn AnyTrait<'ctx> { + *self + } + + fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx> { + *self + } + + fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx> { + self + } +} + +impl<'a, 'ctx: 'a> AnyTraitObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) { + fn from_obj(value: &'a mut (dyn AnyTrait<'ctx> + 'a)) -> Self { + value + } +} + +pub trait Effect<'ctx, C = (), B = ()>: 'static { + type VisitorHkt: HktAnyTraitSendObj<'ctx>; + type WalkerHkt: HktAnyTraitSendObj<'ctx>; + type ControlFlowHkt: Hkt<'ctx>; +} + +pub type ControlFlowFor<'a, 'ctx, E = SyncEffect, C = (), B = ()> = + <<E as Effect<'ctx, C, B>>::ControlFlowHkt as ForLt<'a, 'ctx, Bound<'a, 'ctx>>>::T; pub enum SyncEffect {} -impl Effect for SyncEffect { - type ControlFlow<'a, C, B> = core::ops::ControlFlow<B, C>; +pub struct AnyTraitSendObjHkt<'ctx>(PhantomData<fn() -> &'ctx ()>); + +impl<'a, 'ctx> ForLtAnyTraitSendObj<'a, 'ctx, Bound<'a, 'ctx>> for AnyTraitSendObjHkt<'ctx> { + type T = &'a mut (dyn AnyTrait<'ctx> + Send + 'a); +} + +pub struct AnyTraitObjHkt<'ctx>(PhantomData<fn() -> &'ctx ()>); + +impl<'a, 'ctx> ForLtAnyTraitSendObj<'a, 'ctx, Bound<'a, 'ctx>> for AnyTraitObjHkt<'ctx> { + type T = &'a mut (dyn AnyTrait<'ctx> + 'a); } -fn noop() -> Waker { - const VTABLE: RawWakerVTable = RawWakerVTable::new(|_| RAW, |_| {}, |_| {}, |_| {}); - const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE); +pub struct SyncControlFlowHkt<'ctx, C, B>(PhantomData<fn() -> (&'ctx (), C, B)>); - unsafe { Waker::from_raw(RAW) } +impl<'a, 'ctx, C, B> ForLt<'a, 'ctx, Bound<'a, 'ctx>> for SyncControlFlowHkt<'ctx, C, B> { + type T = core::ops::ControlFlow<B, C>; +} + +impl<'ctx, C, B> Effect<'ctx, C, B> for SyncEffect { + type ControlFlowHkt = SyncControlFlowHkt<'ctx, C, B>; + + type VisitorHkt = AnyTraitSendObjHkt<'ctx>; + + type WalkerHkt = AnyTraitSendObjHkt<'ctx>; +} + +#[cfg(feature = "alloc")] +pub struct AsyncControlFlowHkt<'ctx, C, B>(PhantomData<fn() -> (&'ctx (), C, B)>); + +#[cfg(feature = "alloc")] +impl<'a, 'ctx, C, B> ForLt<'a, 'ctx, Bound<'a, 'ctx>> for AsyncControlFlowHkt<'ctx, C, B> { + type T = core::pin::Pin< + Box<dyn core::future::Future<Output = core::ops::ControlFlow<B, C>> + Send + 'a>, + >; } #[cfg(feature = "alloc")] pub enum AsyncEffect {} #[cfg(feature = "alloc")] -impl Effect for AsyncEffect { - type ControlFlow<'a, C, B> = - core::pin::Pin<Box<dyn core::future::Future<Output = core::ops::ControlFlow<B, C>> + 'a>>; +impl<'ctx, C, B> Effect<'ctx, C, B> for AsyncEffect { + type VisitorHkt = AnyTraitObjHkt<'ctx>; + type WalkerHkt = AnyTraitObjHkt<'ctx>; + type ControlFlowHkt = AsyncControlFlowHkt<'ctx, C, B>; } diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index d012b73..772a908 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -4,18 +4,18 @@ use crate::{ }; /// Protocol for requesting a hint from a visitor. -pub trait RequestHint<'ctx, E: Effect = SyncEffect> { +pub trait RequestHint<'a, 'ctx: 'a, E: Effect<'ctx> = SyncEffect> { /// 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: &'a mut Walker<'a, 'ctx>) -> ControlFlowFor<'a, E>; + fn request_hint(&'a mut self, walker: Walker<'a, 'ctx, E>) -> ControlFlowFor<'a, 'ctx, E>; } nameable! { - pub struct Name['a, 'ctx, E]; - impl [E] for dyn RequestHint<'ctx, E> + 'a where { - E: Effect + 'static, + pub struct Name['a, 'ctx: 'a, E]; + impl [E] for dyn RequestHint<'a, 'ctx, E> + 'a where { + E: Effect<'ctx>, 'ctx: 'a } } diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index 44a80c6..d1b16d9 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -3,26 +3,32 @@ use crate::{ protocol::{walker::HintMeta, ControlFlowFor, Effect, SyncEffect, Visitor}, }; -pub trait Sequence<'ctx, E: Effect = SyncEffect> { - fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx, E>) -> ControlFlowFor<'a, E>; +pub trait Sequence<'a, 'ctx: 'a, E: Effect<'ctx> = SyncEffect> { + fn visit( + &'a mut self, + scope: &'a mut dyn for<'b> SequenceScope<'b, 'ctx, E>, + ) -> ControlFlowFor<'a, 'ctx, E>; } nameable! { - pub struct Name['a, 'ctx, E]; + pub struct Name['a, 'ctx: 'a, E]; - impl [E] for dyn Sequence<'ctx, E> + 'a where { - E: Effect + 'static, + impl [E] for dyn Sequence<'a, 'ctx, E> + 'a where { + E: Effect<'ctx>, 'ctx: 'a } - impl [E] where dyn Sequence<'ctx, E> + 'a { - E: Effect + 'static, + impl [E] where dyn Sequence<'a, 'ctx, E> + 'a { + E: Effect<'ctx>, 'ctx: 'a } } -pub trait SequenceScope<'ctx, E: Effect = SyncEffect> { - fn next<'a>(&'a mut self, visitor: &'a mut Visitor<'a, 'ctx>) -> ControlFlowFor<'a, E, Status>; +pub trait SequenceScope<'a, 'ctx: 'a, E = SyncEffect> +where + E: Effect<'ctx> + Effect<'ctx, Status>, +{ + fn next(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> ControlFlowFor<'a, 'ctx, E, Status>; } #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] @@ -40,12 +46,8 @@ pub struct Hint { pub len: (usize, Option<usize>), } -impl<'ctx, E: Effect> HintMeta<'ctx> for dyn Sequence<'ctx, E> + '_ { - type Known<'a> = Known - where - 'ctx: 'a; +impl<'a, 'ctx: 'a, E: Effect<'ctx>> HintMeta<'a, 'ctx> for dyn Sequence<'a, 'ctx, E> + '_ { + type Known = Known; - type Hint<'a> = Hint - where - 'ctx: 'a; + type Hint = Hint; } diff --git a/src/protocol/visitor/tagged.rs b/src/protocol/visitor/tagged.rs index e6ff575..0258ac9 100644 --- a/src/protocol/visitor/tagged.rs +++ b/src/protocol/visitor/tagged.rs @@ -4,30 +4,33 @@ use crate::{ symbol::Symbol, }; -pub trait Tagged<'ctx, E: Effect = SyncEffect> { - fn visit<'a>(&'a mut self, scope: &'a mut dyn TaggedScope<'ctx, E>) -> ControlFlowFor<'a, E>; +pub trait Tagged<'a, 'ctx: 'a, E: Effect<'ctx> = SyncEffect> { + fn visit( + &'a mut self, + scope: &'a mut dyn TaggedScope<'a, 'ctx, E>, + ) -> ControlFlowFor<'a, 'ctx, E>; } nameable! { - pub struct Name['a, 'ctx, E]; + pub struct Name['a, 'ctx: 'a, E]; - impl [E] for dyn Tagged<'ctx, E> + 'a where { - E: Effect + 'static, + impl [E] for dyn Tagged<'a, 'ctx, E> + 'a where { + E: Effect<'ctx>, 'ctx: 'a } - impl [E] where dyn Tagged<'ctx, E> + 'a { - E: Effect + 'static, + impl [E] where dyn Tagged<'a, 'ctx, E> + 'a { + E: Effect<'ctx>, 'ctx: 'a } } -pub trait TaggedScope<'ctx, E: Effect = SyncEffect> { +pub trait TaggedScope<'a, 'ctx: 'a, E: Effect<'ctx> = SyncEffect> { fn kind(&mut self) -> Symbol; - fn tag<'a>(&'a mut self, visitor: &'a mut Visitor<'a, 'ctx>) -> ControlFlowFor<'a, E>; + fn tag(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> ControlFlowFor<'a, 'ctx, E>; - fn value<'a>(&'a mut self, visitor: &'a mut Visitor<'a, 'ctx>) -> ControlFlowFor<'a, E>; + fn value(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> ControlFlowFor<'a, 'ctx, E>; } pub struct Known { @@ -38,8 +41,8 @@ pub struct Hint { pub kind: Option<Symbol>, } -impl<'ctx, Return> HintMeta<'ctx> for dyn Tagged<'ctx, Return> + '_ { - type Known<'a> = Known where 'ctx: 'a; +impl<'a, 'ctx: 'a, Return> HintMeta<'a, 'ctx> for dyn Tagged<'a, 'ctx, Return> + 'a { + type Known = Known; - type Hint<'a> = Hint where 'ctx: 'a; + type Hint = Hint; } diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index d8461f5..320d1ae 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -11,7 +11,7 @@ use crate::{ /// Trait object for the [`Value`] protocol. /// /// Types implementing the [`Value`] protocol will implement this trait. -pub trait Value<'a, T, E: Effect = SyncEffect> { +pub trait Value<'a, 'ctx: 'a, T, E: Effect<'ctx> = SyncEffect> { /// Visit a value of type `T`. /// /// Use this to give a value to a visitor. Its expected that a walker @@ -21,28 +21,28 @@ pub trait Value<'a, T, E: Effect = SyncEffect> { /// If a [`ControlFlow::Break`] is returned then the walker /// should stop walking as soon as possible as there has likely been /// and error. - fn visit(&'a mut self, value: T) -> ControlFlowFor<'a, E>; + fn visit(&'a mut self, value: T) -> ControlFlowFor<'a, 'ctx, E>; } nameable! { - pub struct Name['a, 'ctx, T, E]; + pub struct Name['a, 'ctx: 'a, T, E]; - impl [T::Name, E] for dyn Value<'a, T, E> + 'a where { + impl [T::Name, E] for dyn Value<'a, 'ctx, T, E> + 'a where { T: TypeNameable<'a, 'ctx> + ?Sized, - E: Effect + 'static, + E: Effect<'ctx>, } - impl [T, E] where dyn Value<'a, T::Nameable, E> + 'a { + impl [T, E] where dyn Value<'a, 'ctx, T::Nameable, E> + 'a { T: TypeName<'a, 'ctx> + ?Sized, - E: Effect + 'static, + E: Effect<'ctx>, } } // This enrolls the Value protocol into the walker hint system. -impl<'ctx, T, E: Effect> HintMeta<'ctx> for dyn Value<'_, T, E> + '_ { - type Known<'a> = () where 'ctx: 'a; +impl<'a, 'ctx: 'a, T, E: Effect<'ctx>> HintMeta<'a, 'ctx> for dyn Value<'a, 'ctx, T, E> + 'a { + type Known = (); - type Hint<'a> = () where 'ctx: 'a; + type Hint = (); } #[cfg(test)] diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index 28bf437..57eaa1a 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -13,37 +13,36 @@ use crate::{ /// Meta information for the hint. /// /// This gives the visitor more information to work from when selecting a hint. -pub trait HintMeta<'ctx> { +pub trait HintMeta<'a, 'ctx: 'a> { /// Information known by the walker. /// /// This should be information easy to get without changing the state of the walker /// in an irreversible way. - type Known<'a> - where - 'ctx: 'a; + type Known; /// Extra information the visitor can give to the walker about what it is expecting. - type Hint<'a> - where - 'ctx: 'a; + type Hint; } /// Object implementing the [`Hint`] protocol. -pub trait Hint<'ctx, Protocol: ?Sized + HintMeta<'ctx>, E: Effect = SyncEffect> { +pub trait Hint<'ctx, Protocol: ?Sized + for<'a> HintMeta<'a, 'ctx>, E = SyncEffect> +where + E: Effect<'ctx> + Effect<'ctx, <Protocol as HintMeta<'a, 'ctx>>::Known>, +{ /// Hint to the walker to use the `P` protocol. /// /// This should only be called once per [`RequestHint`]. fn hint<'a>( &'a mut self, - visitor: &'a mut Visitor<'a, 'ctx>, - hint: Protocol::Hint<'a>, - ) -> ControlFlowFor<'a, E>; + visitor: &'a mut Visitor<'a, 'ctx, E>, + hint: <Protocol as HintMeta<'a, 'ctx>>::Hint, + ) -> ControlFlowFor<'a, 'ctx, E>; /// Ask the walker for information about it's support of the protocol. fn known<'a>( &'a mut self, - hint: &'a Protocol::Hint<'a>, - ) -> ControlFlowFor<'a, E, Protocol::Known<'_>> + hint: &'a <Protocol as HintMeta<'a, 'ctx>>::Hint, + ) -> ControlFlowFor<'a, 'ctx, E, <Protocol as HintMeta<'a, 'ctx>>::Known> where 'ctx: 'a; } @@ -53,13 +52,13 @@ nameable! { impl [Protocol::Name, E] for dyn Hint<'ctx, Protocol, E> + 'a where { Protocol: TypeNameable<'a, 'ctx> + ?Sized, - E: Effect + 'static, + E: Effect<'ctx>, 'ctx: 'a, } impl [Protocol, E] where dyn Hint<'ctx, Protocol::Nameable, E> + 'a { Protocol: TypeName<'a, 'ctx> + ?Sized, - E: Effect + 'static, + E: Effect<'ctx>, 'ctx: 'a, } } diff --git a/src/walk.rs b/src/walk.rs index d13316d..2ebe598 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,4 +1,4 @@ -pub mod walkers; +// pub mod walkers; use crate::protocol::{ControlFlowFor, Effect, Visitor}; @@ -22,7 +22,7 @@ pub fn into_walker<'ctx, T: Walk<'ctx>>(value: T) -> T::Walker { /// - Call [Self::walk()] to walk the value. Data will be sent to the provided /// visitor. pub trait Walker<'ctx> { - type Effect: Effect; + type Effect: Effect<'ctx, Self::Output, Self::Error> + Effect<'ctx, (), ()>; type Error; @@ -37,6 +37,6 @@ pub trait Walker<'ctx> { #[must_use] fn walk<'a>( self, - visitor: &'a mut Visitor<'a, 'ctx>, - ) -> ControlFlowFor<'a, Self::Effect, Self::Output, Self::Error>; + visitor: Visitor<'a, 'ctx, Self::Effect>, + ) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error>; } diff --git a/src/walk/walkers/core/array.rs b/src/walk/walkers/core/array.rs index 571787c..ba85d54 100644 --- a/src/walk/walkers/core/array.rs +++ b/src/walk/walkers/core/array.rs @@ -53,8 +53,11 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From #[inline] fn walk<'a>( mut self, - visitor: &'a mut Visitor<'a, 'ctx>, - ) -> ControlFlowFor<'a, Self::Effect, Self::Output, Self::Error> { + visitor: Visitor<'a, 'ctx, Self::Effect>, + ) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error> + where + Self: 'a, + { if let Some(object) = visitor.upcast_mut::<dyn Sequence<'ctx, W::Effect> + '_>() { object.visit(&mut self); } @@ -67,14 +70,14 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From } } -impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> - SequenceScope<'ctx> for Walker<'ctx, T, N, W> +impl<'a, 'ctx: 'a, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> + SequenceScope<'a, 'ctx> for Walker<'ctx, T, N, W> { #[inline] - fn next<'a>( + fn next( &'a mut self, - visitor: &'a mut Visitor<'a, 'ctx>, - ) -> ControlFlowFor<'a, W::Effect, Status> { + visitor: Visitor<'a, 'ctx, SyncEffect>, + ) -> ControlFlowFor<'a, 'ctx, W::Effect, Status> { if self.index >= N { return ControlFlow::Continue(Status::Done); } diff --git a/src/walk/walkers/core/bool.rs b/src/walk/walkers/core/bool.rs index 7d1aca3..782c9df 100644 --- a/src/walk/walkers/core/bool.rs +++ b/src/walk/walkers/core/bool.rs @@ -13,7 +13,7 @@ use crate::{ }, }; -impl<'ctx> crate::Walk<'ctx> for bool { +impl<'a, 'ctx> crate::Walk<'a, 'ctx> for bool { type Walker = Walker; } @@ -25,7 +25,7 @@ impl<'ctx> From<bool> for Walker { } } -impl<'ctx> crate::Walker<'ctx> for Walker { +impl<'a, 'ctx> crate::Walker<'a, 'ctx> for Walker { type Effect = SyncEffect; type Error = (); @@ -33,10 +33,10 @@ impl<'ctx> crate::Walker<'ctx> for Walker { type Output = (); #[inline] - fn walk<'a>( + fn walk( self, - visitor: &'a mut Visitor<'a, 'ctx>, - ) -> ControlFlowFor<'a, Self::Effect, Self::Output, Self::Error> { + visitor: Visitor<'a, 'ctx, SyncEffect>, + ) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error> { { if let Some(object) = visitor.upcast_mut::<dyn Value<'_, OwnedStatic<bool>> + '_>() { object.visit(OwnedStatic(self.0)); diff --git a/tests/hook.rs b/tests/hook.rs index e69de29..a7f4509 100644 --- a/tests/hook.rs +++ b/tests/hook.rs @@ -0,0 +1,175 @@ +use std::{future::Future, marker::PhantomData, pin::Pin, thread::yield_now, time::Duration}; + +use treaty::{ + any::{any_trait, static_wrapper::OwnedStatic, AnyTrait, IndirectLtAny, LtTypeId}, + build_with, into_walker, + protocol::{ + visitor::Value, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, SyncEffect, Visitor, + }, + Build, Builder, Walker, +}; + +#[test] +fn demo() { + let hook = Hook { + inner: into_walker(true), + _marker: PhantomData, + }; + let x = build_with::<<bool as Build<_>>::Builder, _>(hook).unwrap(); + dbg!(x); + todo!(); +} + +struct Hook<T, Effect> { + inner: T, + _marker: PhantomData<fn() -> Effect>, +} + +struct VisitorHook<'a, 'ctx: 'a, E: Effect> { + inner: E::Visitor<'a, 'ctx>, +} + +impl<'ctx, T: Walker<'ctx, Effect = AsyncEffect> + Send> Walker<'ctx> for Hook<T, AsyncEffect> +where + <T as Walker<'ctx>>::Error: Send, + <T as Walker<'ctx>>::Output: Send, +{ + type Effect = T::Effect; + + type Error = T::Error; + + type Output = T::Output; + + fn walk<'a>( + self, + visitor: Visitor<'a, 'ctx, T::Effect>, + ) -> ControlFlowFor<'a, Self::Effect, Self::Output, Self::Error> + where + Self: 'a, + { + let visitor: &'a mut (dyn AnyTrait<'ctx> + Send + 'a) = is_send(visitor); + let inner: T = is_send(self.inner); + + let x = async move { + let mut visitor = is_send(VisitorHook::<Self::Effect> { + inner: is_send(visitor), + }); + let flow: Pin< + Box<dyn Future<Output = core::ops::ControlFlow<Self::Error, Self::Output>> + Send>, + > = is_send(is_send(inner).walk(is_send(&mut visitor))); + is_send(assert_send(is_send(flow)).await) + }; + + let y: Pin< + Box<dyn Future<Output = core::ops::ControlFlow<Self::Error, Self::Output>> + Send>, + > = Box::pin(assert_send(x)); + todo!(); + } +} + +pub trait Captures<U> {} +impl<T: ?Sized, U> Captures<U> for T {} + +pub fn make_async<'a, 'ctx, T: Walker<'ctx, Effect = AsyncEffect> + Send + 'a>( + visitor: &'a mut (dyn AnyTrait<'ctx> + Send + 'a), + inner: T, +) -> impl futures::Future<Output = ()> + Send + Captures<&'ctx ()> + 'a +where + AsyncEffect: Send, + T::Error: Send, + T::Output: Send, + T::Effect: Send, +{ + async move { + let mut visitor = is_send(VisitorHook::<AsyncEffect> { + inner: is_send(visitor), + }); + // let flow: Pin<Box<dyn Future<Output = _> + Send>> = + if false { + let _: Pin<Box<dyn Future<Output = _> + Send>> = + is_send(is_send(inner).walk(is_send(todo!()))); + } + tokio::time::sleep(Duration::from_secs(1)).await; + // is_send(assert_send(is_send(flow)).await); + () + } +} + +pub fn is_send<T: Send>(x: T) -> T { + x +} + +pub fn assert_send<T>( + s: impl futures::Future<Output = T> + Send, +) -> impl futures::Future<Output = T> + Send { + s +} + +impl<'ctx, T: Walker<'ctx, Effect = SyncEffect>> Walker<'ctx> for Hook<T, SyncEffect> { + type Effect = T::Effect; + + type Error = T::Error; + + type Output = T::Output; + + fn walk<'a>( + self, + visitor: Visitor<'a, 'ctx, T::Effect>, + ) -> ControlFlowFor<'a, Self::Effect, Self::Output, Self::Error> + where + Self: 'a, + { + let mut visitor = VisitorHook::<Self::Effect> { inner: visitor }; + let flow = self.inner.walk(&mut visitor); + flow + } +} + +impl<'b, 'ctx, E: Effect> 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.as_obj().upcast_to_id(id), + } + } + + 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, OwnedStatic<bool>> + 'a>() => { + if self.inner.as_obj_mut().upcast_to_id_mut(id).is_some() { + Some(IndirectLtAny::<'a, 'ctx, _>::new::< + dyn Value<'a, OwnedStatic<bool>> + 'a, + >(self as _)) + } else { + None + } + } + id => self.inner.as_obj_mut().upcast_to_id_mut(id), + } + } +} + +impl<'a, 'b, 'ctx, E: Effect> Value<'a, OwnedStatic<bool>> for VisitorHook<'b, 'ctx, E> { + #[inline] + fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a> { + let visitor = self + .inner + .as_obj_mut() + .upcast_mut::<dyn Value<'a, OwnedStatic<bool>> + 'a>() + .unwrap(); + + println!("Hooked bool: {}", value); + visitor.visit(OwnedStatic(!value)) + } +} |