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
use crate::{BoundVar, DebruijnIndex, Interner, Visit, VisitResult, Visitor};
pub trait VisitExt<I: Interner>: Visit<I> {
fn has_free_vars(&self, interner: &I) -> bool {
self.visit_with(
&mut FindFreeVarsVisitor { interner },
DebruijnIndex::INNERMOST,
)
.to_bool()
}
}
impl<T, I: Interner> VisitExt<I> for T where T: Visit<I> {}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct FindAny {
pub found: bool,
}
impl FindAny {
pub const FOUND: FindAny = FindAny { found: true };
pub fn to_bool(&self) -> bool {
self.found
}
}
impl VisitResult for FindAny {
fn new() -> Self {
FindAny { found: false }
}
fn return_early(&self) -> bool {
self.found
}
fn combine(self, other: Self) -> Self {
FindAny {
found: self.found || other.found,
}
}
}
struct FindFreeVarsVisitor<'i, I: Interner> {
interner: &'i I,
}
impl<'i, I: Interner> Visitor<'i, I> for FindFreeVarsVisitor<'i, I> {
type Result = FindAny;
fn as_dyn(&mut self) -> &mut dyn Visitor<'i, I, Result = Self::Result> {
self
}
fn interner(&self) -> &'i I {
self.interner
}
fn visit_free_var(
&mut self,
_bound_var: BoundVar,
_outer_binder: DebruijnIndex,
) -> Self::Result {
FindAny::FOUND
}
}