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