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
//! Implement [`Referrer`] for standard types.

use std::{collections, hash};

use super::*;

impl<T: Referrer> Referrer for Option<T> {
    fn visit_type(arg: &mut VisitTypeArg) {
        if arg.mark::<Self>().is_continue() {
            T::visit_type(arg);
        }
    }

    fn visit_mut<U: VisitMutArg>(&mut self, arg: &mut U) {
        if let Some(value) = self {
            value.visit_mut(arg);
        }
    }
}

impl<T: Referrer> Referrer for Box<T> {
    fn visit_type(arg: &mut VisitTypeArg) {
        if arg.mark::<Self>().is_continue() {
            T::visit_type(arg);
        }
    }

    fn visit_mut<U: VisitMutArg>(&mut self, arg: &mut U) { T::visit_mut(&mut **self, arg); }
}

impl<T: Referrer> Referrer for Vec<T> {
    fn visit_type(arg: &mut VisitTypeArg) {
        if arg.mark::<Self>().is_continue() {
            T::visit_type(arg);
        }
    }

    fn visit_mut<U: VisitMutArg>(&mut self, arg: &mut U) {
        self.iter_mut().for_each(|value| value.visit_mut(arg))
    }
}

impl<T: Referrer> Referrer for collections::VecDeque<T> {
    fn visit_type(arg: &mut VisitTypeArg) {
        if arg.mark::<Self>().is_continue() {
            T::visit_type(arg);
        }
    }

    fn visit_mut<U: VisitMutArg>(&mut self, arg: &mut U) {
        self.iter_mut().for_each(|value| value.visit_mut(arg))
    }
}

// for whatever reason someone wants to use a linked list...
impl<T: Referrer> Referrer for collections::LinkedList<T> {
    fn visit_type(arg: &mut VisitTypeArg) {
        if arg.mark::<Self>().is_continue() {
            T::visit_type(arg);
        }
    }

    fn visit_mut<U: VisitMutArg>(&mut self, arg: &mut U) {
        self.iter_mut().for_each(|value| value.visit_mut(arg))
    }
}

impl<T: Referrer, const N: usize> Referrer for [T; N] {
    fn visit_type(arg: &mut VisitTypeArg) {
        if arg.mark::<Self>().is_continue() {
            T::visit_type(arg);
        }
    }

    fn visit_mut<U: VisitMutArg>(&mut self, arg: &mut U) {
        self.iter_mut().for_each(|value| value.visit_mut(arg))
    }
}

impl<K: Eq + Ord + 'static, V: Referrer> Referrer for collections::BTreeMap<K, V> {
    fn visit_type(arg: &mut VisitTypeArg) {
        if arg.mark::<Self>().is_continue() {
            V::visit_type(arg);
        }
    }

    fn visit_mut<U: VisitMutArg>(&mut self, arg: &mut U) {
        self.values_mut().for_each(|value| value.visit_mut(arg))
    }
}

impl<K: Eq + hash::Hash + 'static, V: Referrer> Referrer for collections::HashMap<K, V> {
    fn visit_type(arg: &mut VisitTypeArg) {
        if arg.mark::<Self>().is_continue() {
            V::visit_type(arg);
        }
    }

    fn visit_mut<U: VisitMutArg>(&mut self, arg: &mut U) {
        self.values_mut().for_each(|value| value.visit_mut(arg))
    }
}

// no implementation for Arc because we cannot guarantee each is only called once.

// no implementation for PhantomData because it is unclear what the actual intention is.

// no implementation for tuples because they are usually not all Referrer.