2 Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir,
4 use rustc_middle::ty::Const;
6 pub trait Visitor<'a, 'tcx: 'a>: Sized {
7 fn thir(&self) -> &'a Thir<'tcx>;
9 fn visit_expr(&mut self, expr: &Expr<'tcx>) {
10 walk_expr(self, expr);
13 fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
14 walk_stmt(self, stmt);
17 fn visit_block(&mut self, block: &Block) {
18 walk_block(self, block);
21 fn visit_arm(&mut self, arm: &Arm<'tcx>) {
25 fn visit_pat(&mut self, pat: &Pat<'tcx>) {
29 fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
32 pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
35 Scope { value, region_scope: _, lint_level: _ } => {
36 visitor.visit_expr(&visitor.thir()[value])
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]);
46 Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
47 visitor.visit_expr(&visitor.thir()[fun]);
49 visitor.visit_expr(&visitor.thir()[arg]);
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]);
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]),
63 visitor.visit_expr(&visitor.thir()[expr]);
65 Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
66 Match { scrutinee, ref arms } => {
67 visitor.visit_expr(&visitor.thir()[scrutinee]);
69 visitor.visit_arm(&visitor.thir()[arm]);
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]);
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]);
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])
90 Continue { label: _ } => {}
92 if let Some(value) = value {
93 visitor.visit_expr(&visitor.thir()[value])
96 ConstBlock { value } => visitor.visit_const(value),
97 Repeat { value, count } => {
98 visitor.visit_expr(&visitor.thir()[value]);
99 visitor.visit_const(count);
101 Array { ref fields } | Tuple { ref fields } => {
102 for &field in &**fields {
103 visitor.visit_expr(&visitor.thir()[field]);
106 Adt(box crate::thir::Adt {
114 for field in &**fields {
115 visitor.visit_expr(&visitor.thir()[field.expr]);
117 if let Some(base) = base {
118 visitor.visit_expr(&visitor.thir()[base.base]);
121 PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
122 visitor.visit_expr(&visitor.thir()[source])
124 Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
125 Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
126 StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
127 InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
128 for op in &**operands {
129 use InlineAsmOperand::*;
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]);
141 Out { expr: None, reg: _, late: _ }
142 | Const { value: _, span: _ }
143 | SymStatic { def_id: _ } => {}
147 ThreadLocalRef(_) => {}
148 LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
149 for &out_expr in &**outputs {
150 visitor.visit_expr(&visitor.thir()[out_expr]);
152 for &in_expr in &**inputs {
153 visitor.visit_expr(&visitor.thir()[in_expr]);
156 Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
160 pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
162 StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
170 if let Some(init) = initializer {
171 visitor.visit_expr(&visitor.thir()[*init]);
173 visitor.visit_pat(pattern);
178 pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
179 for &stmt in &*block.stmts {
180 visitor.visit_stmt(&visitor.thir()[stmt]);
182 if let Some(expr) = block.expr {
183 visitor.visit_expr(&visitor.thir()[expr]);
187 pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
189 Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
190 Some(Guard::IfLet(ref pat, expr)) => {
191 visitor.visit_pat(pat);
192 visitor.visit_expr(&visitor.thir()[expr]);
196 visitor.visit_pat(&arm.pattern);
197 visitor.visit_expr(&visitor.thir()[arm.body]);
200 pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
202 match pat.kind.as_ref() {
203 AscribeUserType { subpattern, ascription: _ }
204 | Deref { subpattern }
206 subpattern: Some(subpattern),
213 } => visitor.visit_pat(&subpattern),
214 Binding { .. } | Wild => {}
215 Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
216 for subpattern in subpatterns {
217 visitor.visit_pat(&subpattern.pattern);
220 Constant { value } => visitor.visit_const(value),
222 visitor.visit_const(range.lo);
223 visitor.visit_const(range.hi);
225 Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
226 for subpattern in prefix {
227 visitor.visit_pat(&subpattern);
229 if let Some(pat) = slice {
230 visitor.visit_pat(pat);
232 for subpattern in suffix {
233 visitor.visit_pat(&subpattern);
238 visitor.visit_pat(&pat);