1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use crate::{any::AnyTrait, hkt, type_class};

pub trait AsObj<'a, 'ctx: 'a> {
    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> AsObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) {
    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> AsObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + Send + 'a) {
    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
    }
}

type_class!(for<'lt, 'ctx> pub as_obj: AsObj<'lt, 'ctx>);
type_class!(for<'lt, 'ctx> pub any_t);

pub trait EffectAnyTrait<'ctx>: 'static {
    /// The `dyn AnyTrait<'ctx>` for the effect.
    ///
    /// this allows adding extra bounds to the trait object.
    type AnyTrait: as_obj::Hkt<'ctx>;
}

/// Trait for effects.
pub trait Effect<'ctx, T>: EffectAnyTrait<'ctx> {
    /// The type functions return for this effect.
    ///
    /// This type should resolve into a `T`.
    type Yield: any_t::Hkt<'ctx>;
}

pub type Yield<'a, 'ctx, T, E> = any_t::T<'a, 'ctx, <E as Effect<'ctx, T>>::Yield>;

pub enum SyncEffect {}

hkt!((as_obj): for<'a, 'ctx> pub AnyTraitSendObj => &'a mut (dyn AnyTrait<'ctx> + Send + 'a));
hkt!((as_obj): for<'a, 'ctx> pub AnyTraitObj => &'a mut (dyn AnyTrait<'ctx> + 'a));

hkt!((any_t): for<'a, 'ctx> pub SyncYield[T] => T);

impl<'ctx, T> Effect<'ctx, T> for SyncEffect {
    type Yield = SyncYield<'ctx, T>;
}

impl<'ctx> EffectAnyTrait<'ctx> for SyncEffect {
    type AnyTrait = AnyTraitObj<'ctx>;
}

#[cfg(feature = "alloc")]
hkt!((any_t): for<'a, 'ctx> pub AsyncSendYield[T] =>
    core::pin::Pin<
        Box<dyn core::future::Future<Output = T> + Send + 'a>,
    >
);

#[cfg(feature = "alloc")]
pub enum AsyncSendEffect {}

#[cfg(feature = "alloc")]
impl<'ctx, T> Effect<'ctx, T> for AsyncSendEffect {
    type Yield = AsyncSendYield<'ctx, T>;
}

#[cfg(feature = "alloc")]
impl<'ctx> EffectAnyTrait<'ctx> for AsyncSendEffect {
    type AnyTrait = AnyTraitSendObj<'ctx>;
}

#[cfg(feature = "alloc")]
hkt!((any_t): for<'a, 'ctx> pub AsyncYield[T] =>
    core::pin::Pin<
        Box<dyn core::future::Future<Output = T> + 'a>,
    >
);

#[cfg(feature = "alloc")]
pub enum AsyncEffect {}

#[cfg(feature = "alloc")]
impl<'ctx, T> Effect<'ctx, T> for AsyncEffect {
    type Yield = AsyncYield<'ctx, T>;
}

#[cfg(feature = "alloc")]
impl<'ctx> EffectAnyTrait<'ctx> for AsyncEffect {
    type AnyTrait = AnyTraitObj<'ctx>;
}