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
//! [`Protocol`] for giving a visitor an owned value.
//!
//! In some sense, this is the most basic protocol.

use core::{marker::PhantomData, ops::ControlFlow};

use crate::{builtins::walker::hint::Meta, protocol::Protocol};

/// [`Protocol`] for giving a visitor an owned value.
///
/// A value of type `T` can be given to the visitor using
/// [`Object::visit()`]. There is a restriction that `T: 'static`.
pub struct Value<T>(PhantomData<fn() -> T>);

/// Trait object for the [`Value`] protocol.
///
/// Types implementing the [`Value`] protocol will implement this trait.
pub trait Object<T> {
    /// Visit a value of type `T`.
    ///
    /// Use this to give a value to a visitor. Its expected that a walker
    /// only calls this once per usage of the trait object, but that is not
    /// forced.
    ///
    /// 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(&mut self, value: T) -> ControlFlow<()>;
}

// This is what makes Value a protocol.
impl<T: 'static> Protocol for Value<T> {
    type Object<'a, 'ctx: 'a> = &'a mut dyn Object<T>;
}

// This enrolls the Value protocol into the walker hint system.
impl<T: 'static> Meta for Value<T> {
    type Known<'a, 'ctx: 'a> = ();

    type Hint<'a, 'ctx: 'a> = ();
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn visit() {
        struct Visitor(Option<i32>);

        impl Object<i32> for Visitor {
            fn visit(&mut self, value: i32) -> ControlFlow<()> {
                self.0 = Some(value);
                ControlFlow::Continue(())
            }
        }

        let mut v = Visitor(None);
        let object: <Value<i32> as Protocol>::Object<'_, '_> = &mut v;
        object.visit(42);

        assert_eq!(v.0, Some(42));
    }
}