]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_build/src/thir/visit.rs
Rollup merge of #85288 - Geal:clarify-std-io-read, r=dtolnay
[rust.git] / compiler / rustc_mir_build / src / thir / visit.rs
1 use crate::thir::*;
2
3 pub trait Visitor<'a, 'tcx: 'a>: Sized {
4     fn thir(&self) -> &'a Thir<'tcx>;
5
6     fn visit_expr(&mut self, expr: &Expr<'tcx>) {
7         walk_expr(self, expr);
8     }
9
10     fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
11         walk_stmt(self, stmt);
12     }
13
14     fn visit_block(&mut self, block: &Block) {
15         walk_block(self, block);
16     }
17
18     fn visit_arm(&mut self, arm: &Arm<'tcx>) {
19         walk_arm(self, arm);
20     }
21
22     fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
23 }
24
25 pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
26     use ExprKind::*;
27     match expr.kind {
28         Scope { value, region_scope: _, lint_level: _ } => {
29             visitor.visit_expr(&visitor.thir()[value])
30         }
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]);
37             }
38         }
39         Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
40             visitor.visit_expr(&visitor.thir()[fun]);
41             for &arg in &**args {
42                 visitor.visit_expr(&visitor.thir()[arg]);
43             }
44         }
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]);
49         }
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]);
58             for &arm in &**arms {
59                 visitor.visit_arm(&visitor.thir()[arm]);
60             }
61         }
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]);
66         }
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]);
71         }
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])
78             }
79         }
80         Continue { label: _ } => {}
81         Return { value } => {
82             if let Some(value) = value {
83                 visitor.visit_expr(&visitor.thir()[value])
84             }
85         }
86         ConstBlock { value } => visitor.visit_const(value),
87         Repeat { value, count } => {
88             visitor.visit_expr(&visitor.thir()[value]);
89             visitor.visit_const(count);
90         }
91         Array { ref fields } | Tuple { ref fields } => {
92             for &field in &**fields {
93                 visitor.visit_expr(&visitor.thir()[field]);
94             }
95         }
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]);
99             }
100             if let Some(base) = base {
101                 visitor.visit_expr(&visitor.thir()[base.base]);
102             }
103         }
104         PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
105             visitor.visit_expr(&visitor.thir()[source])
106         }
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::*;
113                 match op {
114                     In { expr, reg: _ }
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]);
122                         }
123                     }
124                     Out { expr: None, reg: _, late: _ }
125                     | Const { value: _, span: _ }
126                     | SymStatic { def_id: _ } => {}
127                 }
128             }
129         }
130         ThreadLocalRef(_) => {}
131         LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
132             for &out_expr in &**outputs {
133                 visitor.visit_expr(&visitor.thir()[out_expr]);
134             }
135             for &in_expr in &**inputs {
136                 visitor.visit_expr(&visitor.thir()[in_expr]);
137             }
138         }
139         Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
140     }
141 }
142
143 pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
144     match stmt.kind {
145         StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]),
146         StmtKind::Let {
147             initializer,
148             remainder_scope: _,
149             init_scope: _,
150             pattern: _,
151             lint_level: _,
152         } => {
153             if let Some(init) = initializer {
154                 visitor.visit_expr(&visitor.thir()[init]);
155             }
156         }
157     }
158 }
159
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]);
163     }
164     if let Some(expr) = block.expr {
165         visitor.visit_expr(&visitor.thir()[expr]);
166     }
167 }
168
169 pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
170     match arm.guard {
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]);
174         }
175         None => {}
176     }
177     visitor.visit_expr(&visitor.thir()[arm.body]);
178 }