GATs but not
Konnor Andrews 2024-03-13
parent 0f5b2de · commit d0f31f2
-rw-r--r--Cargo.lock105
-rw-r--r--Cargo.toml1
-rw-r--r--src/build.rs132
-rw-r--r--src/build/builders/core/array.rs49
-rw-r--r--src/build/builders/core/bool.rs46
-rw-r--r--src/build/builders/serde/deserialize.rs47
-rw-r--r--src/build/builders/serde/deserialize_seed.rs52
-rw-r--r--src/lib.rs8
-rw-r--r--src/protocol.rs132
-rw-r--r--src/protocol/visitor/request_hint.rs10
-rw-r--r--src/protocol/visitor/sequence.rs34
-rw-r--r--src/protocol/visitor/tagged.rs29
-rw-r--r--src/protocol/visitor/value.rs20
-rw-r--r--src/protocol/walker/hint.rs29
-rw-r--r--src/walk.rs8
-rw-r--r--src/walk/walkers/core/array.rs17
-rw-r--r--src/walk/walkers/core/bool.rs10
-rw-r--r--tests/hook.rs175
18 files changed, 679 insertions, 225 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1b0bfc2..6acb13a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
diff --git a/Cargo.toml b/Cargo.toml
index 09cb979..cb45b3d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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)),
diff --git a/src/lib.rs b/src/lib.rs
index 831d875..26e1bc6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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))
+ }
+}