rustc_smir/stable_mir/
visitor.rs

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