]>
Commit | Line | Data |
---|---|---|
c295e0f8 | 1 | use super::{ |
c0240ec0 | 2 | AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, InlineAsmExpr, InlineAsmOperand, Pat, |
f2b60f7d | 3 | PatKind, Stmt, StmtKind, Thir, |
c295e0f8 | 4 | }; |
17df50a5 | 5 | |
c0240ec0 FG |
6 | pub trait Visitor<'thir, 'tcx: 'thir>: Sized { |
7 | fn thir(&self) -> &'thir Thir<'tcx>; | |
17df50a5 | 8 | |
c0240ec0 | 9 | fn visit_expr(&mut self, expr: &'thir Expr<'tcx>) { |
17df50a5 XL |
10 | walk_expr(self, expr); |
11 | } | |
12 | ||
c0240ec0 | 13 | fn visit_stmt(&mut self, stmt: &'thir Stmt<'tcx>) { |
17df50a5 XL |
14 | walk_stmt(self, stmt); |
15 | } | |
16 | ||
c0240ec0 | 17 | fn visit_block(&mut self, block: &'thir Block) { |
17df50a5 XL |
18 | walk_block(self, block); |
19 | } | |
20 | ||
c0240ec0 | 21 | fn visit_arm(&mut self, arm: &'thir Arm<'tcx>) { |
17df50a5 XL |
22 | walk_arm(self, arm); |
23 | } | |
24 | ||
c0240ec0 | 25 | fn visit_pat(&mut self, pat: &'thir Pat<'tcx>) { |
136023e0 XL |
26 | walk_pat(self, pat); |
27 | } | |
04454e1e | 28 | |
781aab86 | 29 | // Note: We don't have visitors for `ty::Const` and `mir::Const` |
04454e1e FG |
30 | // (even though these types occur in THIR) for consistency and to reduce confusion, |
31 | // since the lazy creation of constants during thir construction causes most | |
781aab86 | 32 | // 'constants' to not be of type `ty::Const` or `mir::Const` at that |
04454e1e FG |
33 | // stage (they are mostly still identified by `DefId` or `hir::Lit`, see |
34 | // the variants `Literal`, `NonHirLiteral` and `NamedConst` in `thir::ExprKind`). | |
781aab86 | 35 | // You have to manually visit `ty::Const` and `mir::Const` through the |
04454e1e | 36 | // other `visit*` functions. |
17df50a5 XL |
37 | } |
38 | ||
c0240ec0 FG |
39 | pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( |
40 | visitor: &mut V, | |
41 | expr: &'thir Expr<'tcx>, | |
42 | ) { | |
17df50a5 XL |
43 | use ExprKind::*; |
44 | match expr.kind { | |
45 | Scope { value, region_scope: _, lint_level: _ } => { | |
46 | visitor.visit_expr(&visitor.thir()[value]) | |
47 | } | |
48 | Box { value } => visitor.visit_expr(&visitor.thir()[value]), | |
94222f64 | 49 | If { cond, then, else_opt, if_then_scope: _ } => { |
17df50a5 XL |
50 | visitor.visit_expr(&visitor.thir()[cond]); |
51 | visitor.visit_expr(&visitor.thir()[then]); | |
52 | if let Some(else_expr) = else_opt { | |
53 | visitor.visit_expr(&visitor.thir()[else_expr]); | |
54 | } | |
55 | } | |
56 | Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => { | |
57 | visitor.visit_expr(&visitor.thir()[fun]); | |
58 | for &arg in &**args { | |
59 | visitor.visit_expr(&visitor.thir()[arg]); | |
60 | } | |
61 | } | |
62 | Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]), | |
63 | Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => { | |
64 | visitor.visit_expr(&visitor.thir()[lhs]); | |
65 | visitor.visit_expr(&visitor.thir()[rhs]); | |
66 | } | |
67 | Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]), | |
68 | Cast { source } => visitor.visit_expr(&visitor.thir()[source]), | |
69 | Use { source } => visitor.visit_expr(&visitor.thir()[source]), | |
70 | NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), | |
fe692bf9 | 71 | PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), |
ed00b5ec | 72 | Let { expr, ref pat } => { |
94222f64 | 73 | visitor.visit_expr(&visitor.thir()[expr]); |
ed00b5ec | 74 | visitor.visit_pat(pat); |
94222f64 | 75 | } |
17df50a5 | 76 | Loop { body } => visitor.visit_expr(&visitor.thir()[body]), |
add651ee | 77 | Match { scrutinee, ref arms, .. } => { |
17df50a5 XL |
78 | visitor.visit_expr(&visitor.thir()[scrutinee]); |
79 | for &arm in &**arms { | |
80 | visitor.visit_arm(&visitor.thir()[arm]); | |
81 | } | |
82 | } | |
f2b60f7d | 83 | Block { block } => visitor.visit_block(&visitor.thir()[block]), |
17df50a5 XL |
84 | Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => { |
85 | visitor.visit_expr(&visitor.thir()[lhs]); | |
86 | visitor.visit_expr(&visitor.thir()[rhs]); | |
87 | } | |
923072b8 | 88 | Field { lhs, variant_index: _, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]), |
17df50a5 XL |
89 | Index { lhs, index } => { |
90 | visitor.visit_expr(&visitor.thir()[lhs]); | |
91 | visitor.visit_expr(&visitor.thir()[index]); | |
92 | } | |
93 | VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {} | |
94 | Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]), | |
95 | AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]), | |
96 | Break { value, label: _ } => { | |
97 | if let Some(value) = value { | |
98 | visitor.visit_expr(&visitor.thir()[value]) | |
99 | } | |
100 | } | |
101 | Continue { label: _ } => {} | |
102 | Return { value } => { | |
103 | if let Some(value) = value { | |
104 | visitor.visit_expr(&visitor.thir()[value]) | |
105 | } | |
106 | } | |
fe692bf9 | 107 | Become { value } => visitor.visit_expr(&visitor.thir()[value]), |
add651ee | 108 | ConstBlock { did: _, args: _ } => {} |
5e7ed085 | 109 | Repeat { value, count: _ } => { |
17df50a5 | 110 | visitor.visit_expr(&visitor.thir()[value]); |
17df50a5 XL |
111 | } |
112 | Array { ref fields } | Tuple { ref fields } => { | |
113 | for &field in &**fields { | |
114 | visitor.visit_expr(&visitor.thir()[field]); | |
115 | } | |
116 | } | |
f2b60f7d | 117 | Adt(box AdtExpr { |
136023e0 XL |
118 | ref fields, |
119 | ref base, | |
120 | adt_def: _, | |
121 | variant_index: _, | |
add651ee | 122 | args: _, |
136023e0 XL |
123 | user_ty: _, |
124 | }) => { | |
17df50a5 XL |
125 | for field in &**fields { |
126 | visitor.visit_expr(&visitor.thir()[field.expr]); | |
127 | } | |
128 | if let Some(base) = base { | |
129 | visitor.visit_expr(&visitor.thir()[base.base]); | |
130 | } | |
131 | } | |
132 | PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => { | |
133 | visitor.visit_expr(&visitor.thir()[source]) | |
134 | } | |
f2b60f7d FG |
135 | Closure(box ClosureExpr { |
136 | closure_id: _, | |
add651ee | 137 | args: _, |
f2b60f7d FG |
138 | upvars: _, |
139 | movability: _, | |
140 | fake_reads: _, | |
141 | }) => {} | |
5e7ed085 FG |
142 | Literal { lit: _, neg: _ } => {} |
143 | NonHirLiteral { lit: _, user_ty: _ } => {} | |
064997fb | 144 | ZstLiteral { user_ty: _ } => {} |
add651ee | 145 | NamedConst { def_id: _, args: _, user_ty: _ } => {} |
5e7ed085 FG |
146 | ConstParam { param: _, def_id: _ } => {} |
147 | StaticRef { alloc_id: _, ty: _, def_id: _ } => {} | |
f2b60f7d | 148 | InlineAsm(box InlineAsmExpr { ref operands, template: _, options: _, line_spans: _ }) => { |
17df50a5 XL |
149 | for op in &**operands { |
150 | use InlineAsmOperand::*; | |
151 | match op { | |
152 | In { expr, reg: _ } | |
153 | | Out { expr: Some(expr), reg: _, late: _ } | |
04454e1e | 154 | | InOut { expr, reg: _, late: _ } => visitor.visit_expr(&visitor.thir()[*expr]), |
17df50a5 XL |
155 | SplitInOut { in_expr, out_expr, reg: _, late: _ } => { |
156 | visitor.visit_expr(&visitor.thir()[*in_expr]); | |
157 | if let Some(out_expr) = out_expr { | |
158 | visitor.visit_expr(&visitor.thir()[*out_expr]); | |
159 | } | |
160 | } | |
161 | Out { expr: None, reg: _, late: _ } | |
162 | | Const { value: _, span: _ } | |
04454e1e | 163 | | SymFn { value: _, span: _ } |
17df50a5 | 164 | | SymStatic { def_id: _ } => {} |
c620b35d | 165 | Label { block } => visitor.visit_block(&visitor.thir()[*block]), |
17df50a5 XL |
166 | } |
167 | } | |
168 | } | |
49aad941 | 169 | OffsetOf { container: _, fields: _ } => {} |
17df50a5 | 170 | ThreadLocalRef(_) => {} |
17df50a5 XL |
171 | Yield { value } => visitor.visit_expr(&visitor.thir()[value]), |
172 | } | |
173 | } | |
174 | ||
c0240ec0 FG |
175 | pub fn walk_stmt<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( |
176 | visitor: &mut V, | |
177 | stmt: &'thir Stmt<'tcx>, | |
178 | ) { | |
136023e0 XL |
179 | match &stmt.kind { |
180 | StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]), | |
17df50a5 XL |
181 | StmtKind::Let { |
182 | initializer, | |
183 | remainder_scope: _, | |
184 | init_scope: _, | |
136023e0 | 185 | ref pattern, |
17df50a5 | 186 | lint_level: _, |
064997fb | 187 | else_block, |
353b0b11 | 188 | span: _, |
17df50a5 XL |
189 | } => { |
190 | if let Some(init) = initializer { | |
136023e0 | 191 | visitor.visit_expr(&visitor.thir()[*init]); |
17df50a5 | 192 | } |
136023e0 | 193 | visitor.visit_pat(pattern); |
064997fb | 194 | if let Some(block) = else_block { |
f2b60f7d | 195 | visitor.visit_block(&visitor.thir()[*block]) |
064997fb | 196 | } |
17df50a5 XL |
197 | } |
198 | } | |
199 | } | |
200 | ||
c0240ec0 FG |
201 | pub fn walk_block<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( |
202 | visitor: &mut V, | |
203 | block: &'thir Block, | |
204 | ) { | |
17df50a5 XL |
205 | for &stmt in &*block.stmts { |
206 | visitor.visit_stmt(&visitor.thir()[stmt]); | |
207 | } | |
208 | if let Some(expr) = block.expr { | |
209 | visitor.visit_expr(&visitor.thir()[expr]); | |
210 | } | |
211 | } | |
212 | ||
c0240ec0 FG |
213 | pub fn walk_arm<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( |
214 | visitor: &mut V, | |
215 | arm: &'thir Arm<'tcx>, | |
216 | ) { | |
217 | if let Some(expr) = arm.guard { | |
218 | visitor.visit_expr(&visitor.thir()[expr]) | |
17df50a5 | 219 | } |
136023e0 | 220 | visitor.visit_pat(&arm.pattern); |
17df50a5 XL |
221 | visitor.visit_expr(&visitor.thir()[arm.body]); |
222 | } | |
136023e0 | 223 | |
c0240ec0 FG |
224 | pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( |
225 | visitor: &mut V, | |
226 | pat: &'thir Pat<'tcx>, | |
227 | ) { | |
136023e0 | 228 | use PatKind::*; |
f2b60f7d | 229 | match &pat.kind { |
136023e0 XL |
230 | AscribeUserType { subpattern, ascription: _ } |
231 | | Deref { subpattern } | |
e8be2606 FG |
232 | | DerefPattern { subpattern, .. } |
233 | | Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(subpattern), | |
4b012472 | 234 | Binding { .. } | Wild | Never | Error(_) => {} |
add651ee | 235 | Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => { |
136023e0 XL |
236 | for subpattern in subpatterns { |
237 | visitor.visit_pat(&subpattern.pattern); | |
238 | } | |
239 | } | |
5e7ed085 | 240 | Constant { value: _ } => {} |
ed00b5ec | 241 | InlineConstant { def: _, subpattern } => visitor.visit_pat(subpattern), |
5e7ed085 | 242 | Range(_) => {} |
136023e0 | 243 | Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { |
f2b60f7d | 244 | for subpattern in prefix.iter() { |
ed00b5ec | 245 | visitor.visit_pat(subpattern); |
136023e0 XL |
246 | } |
247 | if let Some(pat) = slice { | |
ed00b5ec | 248 | visitor.visit_pat(pat); |
136023e0 | 249 | } |
f2b60f7d | 250 | for subpattern in suffix.iter() { |
ed00b5ec | 251 | visitor.visit_pat(subpattern); |
136023e0 XL |
252 | } |
253 | } | |
254 | Or { pats } => { | |
f2b60f7d | 255 | for pat in pats.iter() { |
4b012472 | 256 | visitor.visit_pat(pat); |
136023e0 XL |
257 | } |
258 | } | |
259 | }; | |
260 | } |