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