1 use rustc_middle
::thir
::{self, *}
;
2 use rustc_middle
::ty
::Const
;
4 pub trait Visitor
<'a
, 'tcx
: 'a
>: Sized
{
5 fn thir(&self) -> &'a Thir
<'tcx
>;
7 fn visit_expr(&mut self, expr
: &Expr
<'tcx
>) {
11 fn visit_stmt(&mut self, stmt
: &Stmt
<'tcx
>) {
12 walk_stmt(self, stmt
);
15 fn visit_block(&mut self, block
: &Block
) {
16 walk_block(self, block
);
19 fn visit_arm(&mut self, arm
: &Arm
<'tcx
>) {
23 fn visit_pat(&mut self, pat
: &Pat
<'tcx
>) {
27 fn visit_const(&mut self, _cnst
: &'tcx Const
<'tcx
>) {}
30 pub fn walk_expr
<'a
, 'tcx
: 'a
, V
: Visitor
<'a
, 'tcx
>>(visitor
: &mut V
, expr
: &Expr
<'tcx
>) {
33 Scope { value, region_scope: _, lint_level: _ }
=> {
34 visitor
.visit_expr(&visitor
.thir()[value
])
36 Box { value }
=> visitor
.visit_expr(&visitor
.thir()[value
]),
37 If { cond, then, else_opt, if_then_scope: _ }
=> {
38 visitor
.visit_expr(&visitor
.thir()[cond
]);
39 visitor
.visit_expr(&visitor
.thir()[then
]);
40 if let Some(else_expr
) = else_opt
{
41 visitor
.visit_expr(&visitor
.thir()[else_expr
]);
44 Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ }
=> {
45 visitor
.visit_expr(&visitor
.thir()[fun
]);
47 visitor
.visit_expr(&visitor
.thir()[arg
]);
50 Deref { arg }
=> visitor
.visit_expr(&visitor
.thir()[arg
]),
51 Binary { lhs, rhs, op: _ }
| LogicalOp { lhs, rhs, op: _ }
=> {
52 visitor
.visit_expr(&visitor
.thir()[lhs
]);
53 visitor
.visit_expr(&visitor
.thir()[rhs
]);
55 Unary { arg, op: _ }
=> visitor
.visit_expr(&visitor
.thir()[arg
]),
56 Cast { source }
=> visitor
.visit_expr(&visitor
.thir()[source
]),
57 Use { source }
=> visitor
.visit_expr(&visitor
.thir()[source
]),
58 NeverToAny { source }
=> visitor
.visit_expr(&visitor
.thir()[source
]),
59 Pointer { source, cast: _ }
=> visitor
.visit_expr(&visitor
.thir()[source
]),
61 visitor
.visit_expr(&visitor
.thir()[expr
]);
63 Loop { body }
=> visitor
.visit_expr(&visitor
.thir()[body
]),
64 Match { scrutinee, ref arms }
=> {
65 visitor
.visit_expr(&visitor
.thir()[scrutinee
]);
67 visitor
.visit_arm(&visitor
.thir()[arm
]);
70 Block { ref body }
=> visitor
.visit_block(body
),
71 Assign { lhs, rhs }
| AssignOp { lhs, rhs, op: _ }
=> {
72 visitor
.visit_expr(&visitor
.thir()[lhs
]);
73 visitor
.visit_expr(&visitor
.thir()[rhs
]);
75 Field { lhs, name: _ }
=> visitor
.visit_expr(&visitor
.thir()[lhs
]),
76 Index { lhs, index }
=> {
77 visitor
.visit_expr(&visitor
.thir()[lhs
]);
78 visitor
.visit_expr(&visitor
.thir()[index
]);
80 VarRef { id: _ }
| UpvarRef { closure_def_id: _, var_hir_id: _ }
=> {}
81 Borrow { arg, borrow_kind: _ }
=> visitor
.visit_expr(&visitor
.thir()[arg
]),
82 AddressOf { arg, mutability: _ }
=> visitor
.visit_expr(&visitor
.thir()[arg
]),
83 Break { value, label: _ }
=> {
84 if let Some(value
) = value
{
85 visitor
.visit_expr(&visitor
.thir()[value
])
88 Continue { label: _ }
=> {}
90 if let Some(value
) = value
{
91 visitor
.visit_expr(&visitor
.thir()[value
])
94 ConstBlock { value }
=> visitor
.visit_const(value
),
95 Repeat { value, count }
=> {
96 visitor
.visit_expr(&visitor
.thir()[value
]);
97 visitor
.visit_const(count
);
99 Array { ref fields }
| Tuple { ref fields }
=> {
100 for &field
in &**fields
{
101 visitor
.visit_expr(&visitor
.thir()[field
]);
112 for field
in &**fields
{
113 visitor
.visit_expr(&visitor
.thir()[field
.expr
]);
115 if let Some(base
) = base
{
116 visitor
.visit_expr(&visitor
.thir()[base
.base
]);
119 PlaceTypeAscription { source, user_ty: _ }
| ValueTypeAscription { source, user_ty: _ }
=> {
120 visitor
.visit_expr(&visitor
.thir()[source
])
122 Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ }
=> {}
123 Literal { literal, user_ty: _, const_id: _ }
=> visitor
.visit_const(literal
),
124 StaticRef { literal, def_id: _ }
=> visitor
.visit_const(literal
),
125 InlineAsm { ref operands, template: _, options: _, line_spans: _ }
=> {
126 for op
in &**operands
{
127 use InlineAsmOperand
::*;
130 | Out { expr: Some(expr), reg: _, late: _ }
131 | InOut { expr, reg: _, late: _ }
132 | SymFn { expr }
=> visitor
.visit_expr(&visitor
.thir()[*expr
]),
133 SplitInOut { in_expr, out_expr, reg: _, late: _ }
=> {
134 visitor
.visit_expr(&visitor
.thir()[*in_expr
]);
135 if let Some(out_expr
) = out_expr
{
136 visitor
.visit_expr(&visitor
.thir()[*out_expr
]);
139 Out { expr: None, reg: _, late: _ }
140 | Const { value: _, span: _ }
141 | SymStatic { def_id: _ }
=> {}
145 ThreadLocalRef(_
) => {}
146 LlvmInlineAsm { ref outputs, ref inputs, asm: _ }
=> {
147 for &out_expr
in &**outputs
{
148 visitor
.visit_expr(&visitor
.thir()[out_expr
]);
150 for &in_expr
in &**inputs
{
151 visitor
.visit_expr(&visitor
.thir()[in_expr
]);
154 Yield { value }
=> visitor
.visit_expr(&visitor
.thir()[value
]),
158 pub fn walk_stmt
<'a
, 'tcx
: 'a
, V
: Visitor
<'a
, 'tcx
>>(visitor
: &mut V
, stmt
: &Stmt
<'tcx
>) {
160 StmtKind
::Expr { expr, scope: _ }
=> visitor
.visit_expr(&visitor
.thir()[*expr
]),
168 if let Some(init
) = initializer
{
169 visitor
.visit_expr(&visitor
.thir()[*init
]);
171 visitor
.visit_pat(pattern
);
176 pub fn walk_block
<'a
, 'tcx
: 'a
, V
: Visitor
<'a
, 'tcx
>>(visitor
: &mut V
, block
: &Block
) {
177 for &stmt
in &*block
.stmts
{
178 visitor
.visit_stmt(&visitor
.thir()[stmt
]);
180 if let Some(expr
) = block
.expr
{
181 visitor
.visit_expr(&visitor
.thir()[expr
]);
185 pub fn walk_arm
<'a
, 'tcx
: 'a
, V
: Visitor
<'a
, 'tcx
>>(visitor
: &mut V
, arm
: &Arm
<'tcx
>) {
187 Some(Guard
::If(expr
)) => visitor
.visit_expr(&visitor
.thir()[expr
]),
188 Some(Guard
::IfLet(ref pat
, expr
)) => {
189 visitor
.visit_pat(pat
);
190 visitor
.visit_expr(&visitor
.thir()[expr
]);
194 visitor
.visit_pat(&arm
.pattern
);
195 visitor
.visit_expr(&visitor
.thir()[arm
.body
]);
198 pub fn walk_pat
<'a
, 'tcx
: 'a
, V
: Visitor
<'a
, 'tcx
>>(visitor
: &mut V
, pat
: &Pat
<'tcx
>) {
200 match pat
.kind
.as_ref() {
201 AscribeUserType { subpattern, ascription: _ }
202 | Deref { subpattern }
204 subpattern
: Some(subpattern
),
211 } => visitor
.visit_pat(&subpattern
),
212 Binding { .. }
| Wild
=> {}
213 Variant { subpatterns, adt_def: _, substs: _, variant_index: _ }
| Leaf { subpatterns }
=> {
214 for subpattern
in subpatterns
{
215 visitor
.visit_pat(&subpattern
.pattern
);
218 Constant { value }
=> visitor
.visit_const(value
),
220 visitor
.visit_const(range
.lo
);
221 visitor
.visit_const(range
.hi
);
223 Slice { prefix, slice, suffix }
| Array { prefix, slice, suffix }
=> {
224 for subpattern
in prefix
{
225 visitor
.visit_pat(&subpattern
);
227 if let Some(pat
) = slice
{
228 visitor
.visit_pat(pat
);
230 for subpattern
in suffix
{
231 visitor
.visit_pat(&subpattern
);
236 visitor
.visit_pat(&pat
);