]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_build/src/thir/visit.rs
fix(rustfmt): load nested out-of-line mods correctly
[rust.git] / compiler / rustc_mir_build / src / thir / visit.rs
1 use rustc_middle::thir::{self, *};
2 use rustc_middle::ty::Const;
3
4 pub trait Visitor<'a, 'tcx: 'a>: Sized {
5     fn thir(&self) -> &'a Thir<'tcx>;
6
7     fn visit_expr(&mut self, expr: &Expr<'tcx>) {
8         walk_expr(self, expr);
9     }
10
11     fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
12         walk_stmt(self, stmt);
13     }
14
15     fn visit_block(&mut self, block: &Block) {
16         walk_block(self, block);
17     }
18
19     fn visit_arm(&mut self, arm: &Arm<'tcx>) {
20         walk_arm(self, arm);
21     }
22
23     fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
24 }
25
26 pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
27     use ExprKind::*;
28     match expr.kind {
29         Scope { value, region_scope: _, lint_level: _ } => {
30             visitor.visit_expr(&visitor.thir()[value])
31         }
32         Box { value } => visitor.visit_expr(&visitor.thir()[value]),
33         If { cond, then, else_opt } => {
34             visitor.visit_expr(&visitor.thir()[cond]);
35             visitor.visit_expr(&visitor.thir()[then]);
36             if let Some(else_expr) = else_opt {
37                 visitor.visit_expr(&visitor.thir()[else_expr]);
38             }
39         }
40         Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
41             visitor.visit_expr(&visitor.thir()[fun]);
42             for &arg in &**args {
43                 visitor.visit_expr(&visitor.thir()[arg]);
44             }
45         }
46         Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
47         Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
48             visitor.visit_expr(&visitor.thir()[lhs]);
49             visitor.visit_expr(&visitor.thir()[rhs]);
50         }
51         Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
52         Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
53         Use { source } => visitor.visit_expr(&visitor.thir()[source]),
54         NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
55         Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
56         Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
57         Match { scrutinee, ref arms } => {
58             visitor.visit_expr(&visitor.thir()[scrutinee]);
59             for &arm in &**arms {
60                 visitor.visit_arm(&visitor.thir()[arm]);
61             }
62         }
63         Block { ref body } => visitor.visit_block(body),
64         Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
65             visitor.visit_expr(&visitor.thir()[lhs]);
66             visitor.visit_expr(&visitor.thir()[rhs]);
67         }
68         Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
69         Index { lhs, index } => {
70             visitor.visit_expr(&visitor.thir()[lhs]);
71             visitor.visit_expr(&visitor.thir()[index]);
72         }
73         VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
74         Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
75         AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
76         Break { value, label: _ } => {
77             if let Some(value) = value {
78                 visitor.visit_expr(&visitor.thir()[value])
79             }
80         }
81         Continue { label: _ } => {}
82         Return { value } => {
83             if let Some(value) = value {
84                 visitor.visit_expr(&visitor.thir()[value])
85             }
86         }
87         ConstBlock { value } => visitor.visit_const(value),
88         Repeat { value, count } => {
89             visitor.visit_expr(&visitor.thir()[value]);
90             visitor.visit_const(count);
91         }
92         Array { ref fields } | Tuple { ref fields } => {
93             for &field in &**fields {
94                 visitor.visit_expr(&visitor.thir()[field]);
95             }
96         }
97         Adt(box thir::Adt {
98             ref fields,
99             ref base,
100             adt_def: _,
101             variant_index: _,
102             substs: _,
103             user_ty: _,
104         }) => {
105             for field in &**fields {
106                 visitor.visit_expr(&visitor.thir()[field.expr]);
107             }
108             if let Some(base) = base {
109                 visitor.visit_expr(&visitor.thir()[base.base]);
110             }
111         }
112         PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
113             visitor.visit_expr(&visitor.thir()[source])
114         }
115         Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
116         Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
117         StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
118         InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
119             for op in &**operands {
120                 use InlineAsmOperand::*;
121                 match op {
122                     In { expr, reg: _ }
123                     | Out { expr: Some(expr), reg: _, late: _ }
124                     | InOut { expr, reg: _, late: _ }
125                     | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
126                     SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
127                         visitor.visit_expr(&visitor.thir()[*in_expr]);
128                         if let Some(out_expr) = out_expr {
129                             visitor.visit_expr(&visitor.thir()[*out_expr]);
130                         }
131                     }
132                     Out { expr: None, reg: _, late: _ }
133                     | Const { value: _, span: _ }
134                     | SymStatic { def_id: _ } => {}
135                 }
136             }
137         }
138         ThreadLocalRef(_) => {}
139         LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
140             for &out_expr in &**outputs {
141                 visitor.visit_expr(&visitor.thir()[out_expr]);
142             }
143             for &in_expr in &**inputs {
144                 visitor.visit_expr(&visitor.thir()[in_expr]);
145             }
146         }
147         Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
148     }
149 }
150
151 pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
152     match stmt.kind {
153         StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]),
154         StmtKind::Let {
155             initializer,
156             remainder_scope: _,
157             init_scope: _,
158             pattern: _,
159             lint_level: _,
160         } => {
161             if let Some(init) = initializer {
162                 visitor.visit_expr(&visitor.thir()[init]);
163             }
164         }
165     }
166 }
167
168 pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
169     for &stmt in &*block.stmts {
170         visitor.visit_stmt(&visitor.thir()[stmt]);
171     }
172     if let Some(expr) = block.expr {
173         visitor.visit_expr(&visitor.thir()[expr]);
174     }
175 }
176
177 pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
178     match arm.guard {
179         Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
180         Some(Guard::IfLet(ref _pat, expr)) => {
181             visitor.visit_expr(&visitor.thir()[expr]);
182         }
183         None => {}
184     }
185     visitor.visit_expr(&visitor.thir()[arm.body]);
186 }