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
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)] 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 } }