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