]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/thir/visit.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / thir / visit.rs
CommitLineData
c295e0f8
XL
1use super::{
2 Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir,
3};
17df50a5
XL
4
5pub 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
38pub 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
161pub 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
183pub 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
192pub 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
205pub 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}