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
use effectful::{
    bound::{Bool, DynBind, IsSend, IsSync, No, SsBound},
    effective::{Canonical, Effective},
    environment::Environment,
    forward_send_sync,
    higher_ranked::WithLt,
    is_not_send_sync,
};
use mockall::mock;
use treaty::{
    any::{trait_by_id, type_name, AnyTrait, MutAnyUnsized, WithLtTypeId},
    protocol::{
        visitor::VisitResult,
        walker::hint::{DynVisitorWith, Hint, HintMeta},
        DynVisitor,
    },
    Flow,
};

pub type KnownFactory<P> = for<'a, 'ctx> fn(
    &'ctx (),
    &'a WithLt<'a, <P as HintMeta>::Hint>,
) -> Result<WithLt<'a, <P as HintMeta>::Known>, ()>;

mock! {
    pub HintWalker<P: ?Sized + HintMeta>
    where
        for<'r> WithLt<'r, P::Hint>: Sized
    {
        pub fn hint<'r, 'src>(&'r mut self, visitor: DynVisitorWith<'r, 'src, P>, hint: WithLt<'r, P::Hint>) -> VisitResult;

        pub fn known(&self) -> KnownFactory<P>;
    }
}

is_not_send_sync! {
    {P: (?Sized + HintMeta)} MockHintWalker<P>
    where {
        for<'r> WithLt<'r, P::Hint>: Sized
    },
}

impl<'src, P: ?Sized + HintMeta> AnyTrait<'src> for MockHintWalker<P>
where
    P::Env: SsBound<NeedSend = No, NeedSync = No>,
    Self: Hint<'src, P>,
    for<'r> WithLt<'r, P::Hint>: Sized,
    for<'r> WithLt<'r, P::Known>: Sized + DynBind<P::Env>,
{
    fn upcast_by_id_mut(&mut self, id: WithLtTypeId<'src>) -> Option<MutAnyUnsized<'_, 'src>> {
        trait_by_id!(&mut self, id, {
            type Impls = (dyn Hint<P>);
        });

        None
    }
}

// any_trait! {
//     impl['ctx, P][E] MockHintWalker<P> = [
//         HintProto<P>
//     ] where
//         E: Environment,
//         P: HintMeta<Effect = E>,
// }

impl<'ctx, P: ?Sized + HintMeta> Hint<'ctx, P> for MockHintWalker<P>
where
    P::Env: SsBound<NeedSend = No, NeedSync = No>,
    for<'r> WithLt<'r, P::Hint>: Sized,
    for<'r> WithLt<'r, P::Known>: Sized + DynBind<P::Env>,
{
    fn hint<'r>(
        &'r mut self,
        visitor: DynVisitorWith<'r, 'ctx, P>,
        hint: WithLt<'r, <P as HintMeta>::Hint>,
    ) -> Canonical<'r, VisitResult, <P>::Env> {
        P::Env::value(self.hint(visitor, hint)).cast()
    }

    fn known<'a>(
        &'a mut self,
        hint: &'a WithLt<'a, <P as HintMeta>::Hint>,
    ) -> Canonical<'a, Result<WithLt<'a, <P as HintMeta>::Known>, ()>, <P>::Env> {
        todo!()
    }

    // fn hint<'this, 'visitor, 'hint, 'e>(
    //     &'this mut self,
    //     visitor: DynVisitorWith<'visitor, 'ctx, P>,
    //     hint: WithLt<'hint, P>,
    // ) -> Canonical<'e, VisitResult, P::Effect>
    // where
    //     'ctx: 'this + 'visitor + 'hint + 'e,
    // {
    //     P::Effect::value(self.hint(visitor, hint)).cast()
    // }
    //
    // fn known<'a>(
    //     &'a mut self,
    //     hint: &'a WithLt<'a, P::Hint>,
    // ) -> Canonical<'a, Result<WithLt<'a, P::Known>, ()>, P::Effect> {
    //     P::Effect::value(Self::known(self)(&(), hint)).cast()
    // }
}