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