stable_mir/
visitor.rs

1use std::ops::ControlFlow;
2
3use super::ty::{
4    Allocation, Binder, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs,
5    MirConst, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst,
6};
7use crate::Opaque;
8use crate::ty::TyConst;
9
10pub trait Visitor: Sized {
11    type Break;
12    fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break> {
13        ty.super_visit(self)
14    }
15    fn visit_const(&mut self, c: &TyConst) -> ControlFlow<Self::Break> {
16        c.super_visit(self)
17    }
18    fn visit_reg(&mut self, reg: &Region) -> ControlFlow<Self::Break> {
19        reg.super_visit(self)
20    }
21}
22
23pub trait Visitable {
24    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
25        self.super_visit(visitor)
26    }
27    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break>;
28}
29
30impl Visitable for Ty {
31    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
32        visitor.visit_ty(self)
33    }
34    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
35        match self.kind() {
36            super::ty::TyKind::RigidTy(ty) => ty.visit(visitor)?,
37            super::ty::TyKind::Alias(_, alias) => alias.args.visit(visitor)?,
38            super::ty::TyKind::Param(_) | super::ty::TyKind::Bound(_, _) => {}
39        }
40        ControlFlow::Continue(())
41    }
42}
43
44impl Visitable for TyConst {
45    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
46        visitor.visit_const(self)
47    }
48    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
49        match &self.kind {
50            crate::ty::TyConstKind::Param(_) | crate::ty::TyConstKind::Bound(_, _) => {}
51            crate::ty::TyConstKind::Unevaluated(_, args) => args.visit(visitor)?,
52            crate::ty::TyConstKind::Value(ty, alloc) => {
53                alloc.visit(visitor)?;
54                ty.visit(visitor)?;
55            }
56            crate::ty::TyConstKind::ZSTValue(ty) => ty.visit(visitor)?,
57        }
58        ControlFlow::Continue(())
59    }
60}
61
62impl Visitable for MirConst {
63    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
64        self.super_visit(visitor)
65    }
66    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
67        match &self.kind() {
68            super::ty::ConstantKind::Ty(ct) => ct.visit(visitor)?,
69            super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?,
70            super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?,
71            super::ty::ConstantKind::Param(_) | super::ty::ConstantKind::ZeroSized => {}
72        }
73        self.ty().visit(visitor)
74    }
75}
76
77impl Visitable for Opaque {
78    fn super_visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> {
79        ControlFlow::Continue(())
80    }
81}
82
83impl Visitable for Allocation {
84    fn super_visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> {
85        ControlFlow::Continue(())
86    }
87}
88
89impl Visitable for UnevaluatedConst {
90    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
91        let UnevaluatedConst { def, args, promoted } = self;
92        def.visit(visitor)?;
93        args.visit(visitor)?;
94        promoted.visit(visitor)
95    }
96}
97
98impl Visitable for ConstDef {
99    fn super_visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> {
100        ControlFlow::Continue(())
101    }
102}
103
104impl<T: Visitable> Visitable for Option<T> {
105    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
106        match self {
107            Some(val) => val.visit(visitor),
108            None => ControlFlow::Continue(()),
109        }
110    }
111}
112
113impl Visitable for Promoted {
114    fn super_visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> {
115        ControlFlow::Continue(())
116    }
117}
118
119impl Visitable for GenericArgs {
120    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
121        self.0.visit(visitor)
122    }
123}
124
125impl Visitable for Region {
126    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
127        visitor.visit_reg(self)
128    }
129
130    fn super_visit<V: Visitor>(&self, _: &mut V) -> ControlFlow<V::Break> {
131        ControlFlow::Continue(())
132    }
133}
134
135impl Visitable for GenericArgKind {
136    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
137        match self {
138            GenericArgKind::Lifetime(lt) => lt.visit(visitor),
139            GenericArgKind::Type(t) => t.visit(visitor),
140            GenericArgKind::Const(c) => c.visit(visitor),
141        }
142    }
143}
144
145impl Visitable for RigidTy {
146    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
147        match self {
148            RigidTy::Bool
149            | RigidTy::Char
150            | RigidTy::Int(_)
151            | RigidTy::Uint(_)
152            | RigidTy::Float(_)
153            | RigidTy::Never
154            | RigidTy::Foreign(_)
155            | RigidTy::Str => ControlFlow::Continue(()),
156            RigidTy::Array(t, c) => {
157                t.visit(visitor)?;
158                c.visit(visitor)
159            }
160            RigidTy::Pat(t, _p) => t.visit(visitor),
161            RigidTy::Slice(inner) => inner.visit(visitor),
162            RigidTy::RawPtr(ty, _) => ty.visit(visitor),
163            RigidTy::Ref(reg, ty, _) => {
164                reg.visit(visitor);
165                ty.visit(visitor)
166            }
167            RigidTy::Adt(_, args)
168            | RigidTy::Closure(_, args)
169            | RigidTy::Coroutine(_, args, _)
170            | RigidTy::CoroutineWitness(_, args)
171            | RigidTy::CoroutineClosure(_, args)
172            | RigidTy::FnDef(_, args) => args.visit(visitor),
173            RigidTy::FnPtr(sig) => sig.visit(visitor),
174            RigidTy::Dynamic(pred, r, _) => {
175                pred.visit(visitor)?;
176                r.visit(visitor)
177            }
178            RigidTy::Tuple(fields) => fields.visit(visitor),
179        }
180    }
181}
182
183impl<T: Visitable> Visitable for Vec<T> {
184    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
185        for arg in self {
186            arg.visit(visitor)?;
187        }
188        ControlFlow::Continue(())
189    }
190}
191
192impl<T: Visitable> Visitable for Binder<T> {
193    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
194        self.value.visit(visitor)
195    }
196}
197
198impl Visitable for ExistentialPredicate {
199    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
200        match self {
201            ExistentialPredicate::Trait(tr) => tr.generic_args.visit(visitor),
202            ExistentialPredicate::Projection(p) => {
203                p.term.visit(visitor)?;
204                p.generic_args.visit(visitor)
205            }
206            ExistentialPredicate::AutoTrait(_) => ControlFlow::Continue(()),
207        }
208    }
209}
210
211impl Visitable for TermKind {
212    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
213        match self {
214            TermKind::Type(t) => t.visit(visitor),
215            TermKind::Const(c) => c.visit(visitor),
216        }
217    }
218}
219
220impl Visitable for FnSig {
221    fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
222        self.inputs_and_output.visit(visitor)
223    }
224}