]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_mir_build/src/thir/visit.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / compiler / rustc_mir_build / src / thir / visit.rs
CommitLineData
136023e0 1use rustc_middle::thir::{self, *};
17df50a5
XL
2use rustc_middle::ty::Const;
3
4pub 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
30pub 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
155pub 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
173pub 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
182pub 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
195pub 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}