2 AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, Guard, InlineAsmExpr, InlineAsmOperand, Pat,
3 PatKind, Stmt, StmtKind, Thir,
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 // Note: We don't have visitors for `ty::Const` and `mir::ConstantKind`
30 // (even though these types occur in THIR) for consistency and to reduce confusion,
31 // since the lazy creation of constants during thir construction causes most
32 // 'constants' to not be of type `ty::Const` or `mir::ConstantKind` at that
33 // stage (they are mostly still identified by `DefId` or `hir::Lit`, see
34 // the variants `Literal`, `NonHirLiteral` and `NamedConst` in `thir::ExprKind`).
35 // You have to manually visit `ty::Const` and `mir::ConstantKind` through the
36 // other `visit*` functions.
39 pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
42 Scope { value, region_scope: _, lint_level: _ } => {
43 visitor.visit_expr(&visitor.thir()[value])
45 Box { value } => visitor.visit_expr(&visitor.thir()[value]),
46 If { cond, then, else_opt, if_then_scope: _ } => {
47 visitor.visit_expr(&visitor.thir()[cond]);
48 visitor.visit_expr(&visitor.thir()[then]);
49 if let Some(else_expr) = else_opt {
50 visitor.visit_expr(&visitor.thir()[else_expr]);
53 Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
54 visitor.visit_expr(&visitor.thir()[fun]);
56 visitor.visit_expr(&visitor.thir()[arg]);
59 Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
60 Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
61 visitor.visit_expr(&visitor.thir()[lhs]);
62 visitor.visit_expr(&visitor.thir()[rhs]);
64 Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
65 Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
66 Use { source } => visitor.visit_expr(&visitor.thir()[source]),
67 NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
68 Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
70 visitor.visit_expr(&visitor.thir()[expr]);
72 Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
73 Match { scrutinee, ref arms } => {
74 visitor.visit_expr(&visitor.thir()[scrutinee]);
76 visitor.visit_arm(&visitor.thir()[arm]);
79 Block { block } => visitor.visit_block(&visitor.thir()[block]),
80 Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
81 visitor.visit_expr(&visitor.thir()[lhs]);
82 visitor.visit_expr(&visitor.thir()[rhs]);
84 Field { lhs, variant_index: _, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
85 Index { lhs, index } => {
86 visitor.visit_expr(&visitor.thir()[lhs]);
87 visitor.visit_expr(&visitor.thir()[index]);
89 VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
90 Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
91 AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
92 Break { value, label: _ } => {
93 if let Some(value) = value {
94 visitor.visit_expr(&visitor.thir()[value])
97 Continue { label: _ } => {}
99 if let Some(value) = value {
100 visitor.visit_expr(&visitor.thir()[value])
103 ConstBlock { did: _, substs: _ } => {}
104 Repeat { value, count: _ } => {
105 visitor.visit_expr(&visitor.thir()[value]);
107 Array { ref fields } | Tuple { ref fields } => {
108 for &field in &**fields {
109 visitor.visit_expr(&visitor.thir()[field]);
120 for field in &**fields {
121 visitor.visit_expr(&visitor.thir()[field.expr]);
123 if let Some(base) = base {
124 visitor.visit_expr(&visitor.thir()[base.base]);
127 PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
128 visitor.visit_expr(&visitor.thir()[source])
130 Closure(box ClosureExpr {
137 Literal { lit: _, neg: _ } => {}
138 NonHirLiteral { lit: _, user_ty: _ } => {}
139 ZstLiteral { user_ty: _ } => {}
140 NamedConst { def_id: _, substs: _, user_ty: _ } => {}
141 ConstParam { param: _, def_id: _ } => {}
142 StaticRef { alloc_id: _, ty: _, def_id: _ } => {}
143 InlineAsm(box InlineAsmExpr { ref operands, template: _, options: _, line_spans: _ }) => {
144 for op in &**operands {
145 use InlineAsmOperand::*;
148 | Out { expr: Some(expr), reg: _, late: _ }
149 | InOut { expr, reg: _, late: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
150 SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
151 visitor.visit_expr(&visitor.thir()[*in_expr]);
152 if let Some(out_expr) = out_expr {
153 visitor.visit_expr(&visitor.thir()[*out_expr]);
156 Out { expr: None, reg: _, late: _ }
157 | Const { value: _, span: _ }
158 | SymFn { value: _, span: _ }
159 | SymStatic { def_id: _ } => {}
163 ThreadLocalRef(_) => {}
164 Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
168 pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
170 StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
179 if let Some(init) = initializer {
180 visitor.visit_expr(&visitor.thir()[*init]);
182 visitor.visit_pat(pattern);
183 if let Some(block) = else_block {
184 visitor.visit_block(&visitor.thir()[*block])
190 pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
191 for &stmt in &*block.stmts {
192 visitor.visit_stmt(&visitor.thir()[stmt]);
194 if let Some(expr) = block.expr {
195 visitor.visit_expr(&visitor.thir()[expr]);
199 pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
201 Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
202 Some(Guard::IfLet(ref pat, expr)) => {
203 visitor.visit_pat(pat);
204 visitor.visit_expr(&visitor.thir()[expr]);
208 visitor.visit_pat(&arm.pattern);
209 visitor.visit_expr(&visitor.thir()[arm.body]);
212 pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
215 AscribeUserType { subpattern, ascription: _ }
216 | Deref { subpattern }
218 subpattern: Some(subpattern),
225 } => visitor.visit_pat(&subpattern),
226 Binding { .. } | Wild => {}
227 Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
228 for subpattern in subpatterns {
229 visitor.visit_pat(&subpattern.pattern);
232 Constant { value: _ } => {}
234 Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
235 for subpattern in prefix.iter() {
236 visitor.visit_pat(&subpattern);
238 if let Some(pat) = slice {
239 visitor.visit_pat(&pat);
241 for subpattern in suffix.iter() {
242 visitor.visit_pat(&subpattern);
246 for pat in pats.iter() {
247 visitor.visit_pat(&pat);