3 pub trait Visitor<'a, 'tcx: 'a>: Sized {
4 fn thir(&self) -> &'a Thir<'tcx>;
6 fn visit_expr(&mut self, expr: &Expr<'tcx>) {
10 fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
11 walk_stmt(self, stmt);
14 fn visit_block(&mut self, block: &Block) {
15 walk_block(self, block);
18 fn visit_arm(&mut self, arm: &Arm<'tcx>) {
22 fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
25 pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
28 Scope { value, region_scope: _, lint_level: _ } => {
29 visitor.visit_expr(&visitor.thir()[value])
31 Box { value } => visitor.visit_expr(&visitor.thir()[value]),
32 If { cond, then, else_opt } => {
33 visitor.visit_expr(&visitor.thir()[cond]);
34 visitor.visit_expr(&visitor.thir()[then]);
35 if let Some(else_expr) = else_opt {
36 visitor.visit_expr(&visitor.thir()[else_expr]);
39 Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
40 visitor.visit_expr(&visitor.thir()[fun]);
42 visitor.visit_expr(&visitor.thir()[arg]);
45 Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
46 Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
47 visitor.visit_expr(&visitor.thir()[lhs]);
48 visitor.visit_expr(&visitor.thir()[rhs]);
50 Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
51 Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
52 Use { source } => visitor.visit_expr(&visitor.thir()[source]),
53 NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
54 Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
55 Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
56 Match { scrutinee, ref arms } => {
57 visitor.visit_expr(&visitor.thir()[scrutinee]);
59 visitor.visit_arm(&visitor.thir()[arm]);
62 Block { ref body } => visitor.visit_block(body),
63 Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
64 visitor.visit_expr(&visitor.thir()[lhs]);
65 visitor.visit_expr(&visitor.thir()[rhs]);
67 Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
68 Index { lhs, index } => {
69 visitor.visit_expr(&visitor.thir()[lhs]);
70 visitor.visit_expr(&visitor.thir()[index]);
72 VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
73 Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
74 AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
75 Break { value, label: _ } => {
76 if let Some(value) = value {
77 visitor.visit_expr(&visitor.thir()[value])
80 Continue { label: _ } => {}
82 if let Some(value) = value {
83 visitor.visit_expr(&visitor.thir()[value])
86 ConstBlock { value } => visitor.visit_const(value),
87 Repeat { value, count } => {
88 visitor.visit_expr(&visitor.thir()[value]);
89 visitor.visit_const(count);
91 Array { ref fields } | Tuple { ref fields } => {
92 for &field in &**fields {
93 visitor.visit_expr(&visitor.thir()[field]);
96 Adt { ref fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => {
97 for field in &**fields {
98 visitor.visit_expr(&visitor.thir()[field.expr]);
100 if let Some(base) = base {
101 visitor.visit_expr(&visitor.thir()[base.base]);
104 PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
105 visitor.visit_expr(&visitor.thir()[source])
107 Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
108 Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
109 StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
110 InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
111 for op in &**operands {
112 use InlineAsmOperand::*;
115 | Out { expr: Some(expr), reg: _, late: _ }
116 | InOut { expr, reg: _, late: _ }
117 | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
118 SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
119 visitor.visit_expr(&visitor.thir()[*in_expr]);
120 if let Some(out_expr) = out_expr {
121 visitor.visit_expr(&visitor.thir()[*out_expr]);
124 Out { expr: None, reg: _, late: _ }
125 | Const { value: _, span: _ }
126 | SymStatic { def_id: _ } => {}
130 ThreadLocalRef(_) => {}
131 LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
132 for &out_expr in &**outputs {
133 visitor.visit_expr(&visitor.thir()[out_expr]);
135 for &in_expr in &**inputs {
136 visitor.visit_expr(&visitor.thir()[in_expr]);
139 Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
143 pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
145 StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]),
153 if let Some(init) = initializer {
154 visitor.visit_expr(&visitor.thir()[init]);
160 pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
161 for &stmt in &*block.stmts {
162 visitor.visit_stmt(&visitor.thir()[stmt]);
164 if let Some(expr) = block.expr {
165 visitor.visit_expr(&visitor.thir()[expr]);
169 pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
171 Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
172 Some(Guard::IfLet(ref _pat, expr)) => {
173 visitor.visit_expr(&visitor.thir()[expr]);
177 visitor.visit_expr(&visitor.thir()[arm.body]);