2 AdtExpr
, Arm
, Block
, ClosureExpr
, Expr
, ExprKind
, InlineAsmExpr
, InlineAsmOperand
, Pat
,
3 PatKind
, Stmt
, StmtKind
, Thir
,
6 pub trait Visitor
<'thir
, 'tcx
: 'thir
>: Sized
{
7 fn thir(&self) -> &'thir Thir
<'tcx
>;
9 fn visit_expr(&mut self, expr
: &'thir Expr
<'tcx
>) {
10 walk_expr(self, expr
);
13 fn visit_stmt(&mut self, stmt
: &'thir Stmt
<'tcx
>) {
14 walk_stmt(self, stmt
);
17 fn visit_block(&mut self, block
: &'thir Block
) {
18 walk_block(self, block
);
21 fn visit_arm(&mut self, arm
: &'thir Arm
<'tcx
>) {
25 fn visit_pat(&mut self, pat
: &'thir Pat
<'tcx
>) {
29 // Note: We don't have visitors for `ty::Const` and `mir::Const`
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::Const` 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::Const` through the
36 // other `visit*` functions.
39 pub fn walk_expr
<'thir
, 'tcx
: 'thir
, V
: Visitor
<'thir
, 'tcx
>>(
41 expr
: &'thir Expr
<'tcx
>,
45 Scope { value, region_scope: _, lint_level: _ }
=> {
46 visitor
.visit_expr(&visitor
.thir()[value
])
48 Box { value }
=> visitor
.visit_expr(&visitor
.thir()[value
]),
49 If { cond, then, else_opt, if_then_scope: _ }
=> {
50 visitor
.visit_expr(&visitor
.thir()[cond
]);
51 visitor
.visit_expr(&visitor
.thir()[then
]);
52 if let Some(else_expr
) = else_opt
{
53 visitor
.visit_expr(&visitor
.thir()[else_expr
]);
56 Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ }
=> {
57 visitor
.visit_expr(&visitor
.thir()[fun
]);
59 visitor
.visit_expr(&visitor
.thir()[arg
]);
62 Deref { arg }
=> visitor
.visit_expr(&visitor
.thir()[arg
]),
63 Binary { lhs, rhs, op: _ }
| LogicalOp { lhs, rhs, op: _ }
=> {
64 visitor
.visit_expr(&visitor
.thir()[lhs
]);
65 visitor
.visit_expr(&visitor
.thir()[rhs
]);
67 Unary { arg, op: _ }
=> visitor
.visit_expr(&visitor
.thir()[arg
]),
68 Cast { source }
=> visitor
.visit_expr(&visitor
.thir()[source
]),
69 Use { source }
=> visitor
.visit_expr(&visitor
.thir()[source
]),
70 NeverToAny { source }
=> visitor
.visit_expr(&visitor
.thir()[source
]),
71 PointerCoercion { source, cast: _ }
=> visitor
.visit_expr(&visitor
.thir()[source
]),
72 Let { expr, ref pat }
=> {
73 visitor
.visit_expr(&visitor
.thir()[expr
]);
74 visitor
.visit_pat(pat
);
76 Loop { body }
=> visitor
.visit_expr(&visitor
.thir()[body
]),
77 Match { scrutinee, ref arms, .. }
=> {
78 visitor
.visit_expr(&visitor
.thir()[scrutinee
]);
80 visitor
.visit_arm(&visitor
.thir()[arm
]);
83 Block { block }
=> visitor
.visit_block(&visitor
.thir()[block
]),
84 Assign { lhs, rhs }
| AssignOp { lhs, rhs, op: _ }
=> {
85 visitor
.visit_expr(&visitor
.thir()[lhs
]);
86 visitor
.visit_expr(&visitor
.thir()[rhs
]);
88 Field { lhs, variant_index: _, name: _ }
=> visitor
.visit_expr(&visitor
.thir()[lhs
]),
89 Index { lhs, index }
=> {
90 visitor
.visit_expr(&visitor
.thir()[lhs
]);
91 visitor
.visit_expr(&visitor
.thir()[index
]);
93 VarRef { id: _ }
| UpvarRef { closure_def_id: _, var_hir_id: _ }
=> {}
94 Borrow { arg, borrow_kind: _ }
=> visitor
.visit_expr(&visitor
.thir()[arg
]),
95 AddressOf { arg, mutability: _ }
=> visitor
.visit_expr(&visitor
.thir()[arg
]),
96 Break { value, label: _ }
=> {
97 if let Some(value
) = value
{
98 visitor
.visit_expr(&visitor
.thir()[value
])
101 Continue { label: _ }
=> {}
102 Return { value }
=> {
103 if let Some(value
) = value
{
104 visitor
.visit_expr(&visitor
.thir()[value
])
107 Become { value }
=> visitor
.visit_expr(&visitor
.thir()[value
]),
108 ConstBlock { did: _, args: _ }
=> {}
109 Repeat { value, count: _ }
=> {
110 visitor
.visit_expr(&visitor
.thir()[value
]);
112 Array { ref fields }
| Tuple { ref fields }
=> {
113 for &field
in &**fields
{
114 visitor
.visit_expr(&visitor
.thir()[field
]);
125 for field
in &**fields
{
126 visitor
.visit_expr(&visitor
.thir()[field
.expr
]);
128 if let Some(base
) = base
{
129 visitor
.visit_expr(&visitor
.thir()[base
.base
]);
132 PlaceTypeAscription { source, user_ty: _ }
| ValueTypeAscription { source, user_ty: _ }
=> {
133 visitor
.visit_expr(&visitor
.thir()[source
])
135 Closure(box ClosureExpr
{
142 Literal { lit: _, neg: _ }
=> {}
143 NonHirLiteral { lit: _, user_ty: _ }
=> {}
144 ZstLiteral { user_ty: _ }
=> {}
145 NamedConst { def_id: _, args: _, user_ty: _ }
=> {}
146 ConstParam { param: _, def_id: _ }
=> {}
147 StaticRef { alloc_id: _, ty: _, def_id: _ }
=> {}
148 InlineAsm(box InlineAsmExpr { ref operands, template: _, options: _, line_spans: _ }
) => {
149 for op
in &**operands
{
150 use InlineAsmOperand
::*;
153 | Out { expr: Some(expr), reg: _, late: _ }
154 | InOut { expr, reg: _, late: _ }
=> visitor
.visit_expr(&visitor
.thir()[*expr
]),
155 SplitInOut { in_expr, out_expr, reg: _, late: _ }
=> {
156 visitor
.visit_expr(&visitor
.thir()[*in_expr
]);
157 if let Some(out_expr
) = out_expr
{
158 visitor
.visit_expr(&visitor
.thir()[*out_expr
]);
161 Out { expr: None, reg: _, late: _ }
162 | Const { value: _, span: _ }
163 | SymFn { value: _, span: _ }
164 | SymStatic { def_id: _ }
=> {}
165 Label { block }
=> visitor
.visit_block(&visitor
.thir()[*block
]),
169 OffsetOf { container: _, fields: _ }
=> {}
170 ThreadLocalRef(_
) => {}
171 Yield { value }
=> visitor
.visit_expr(&visitor
.thir()[value
]),
175 pub fn walk_stmt
<'thir
, 'tcx
: 'thir
, V
: Visitor
<'thir
, 'tcx
>>(
177 stmt
: &'thir Stmt
<'tcx
>,
180 StmtKind
::Expr { expr, scope: _ }
=> visitor
.visit_expr(&visitor
.thir()[*expr
]),
190 if let Some(init
) = initializer
{
191 visitor
.visit_expr(&visitor
.thir()[*init
]);
193 visitor
.visit_pat(pattern
);
194 if let Some(block
) = else_block
{
195 visitor
.visit_block(&visitor
.thir()[*block
])
201 pub fn walk_block
<'thir
, 'tcx
: 'thir
, V
: Visitor
<'thir
, 'tcx
>>(
205 for &stmt
in &*block
.stmts
{
206 visitor
.visit_stmt(&visitor
.thir()[stmt
]);
208 if let Some(expr
) = block
.expr
{
209 visitor
.visit_expr(&visitor
.thir()[expr
]);
213 pub fn walk_arm
<'thir
, 'tcx
: 'thir
, V
: Visitor
<'thir
, 'tcx
>>(
215 arm
: &'thir Arm
<'tcx
>,
217 if let Some(expr
) = arm
.guard
{
218 visitor
.visit_expr(&visitor
.thir()[expr
])
220 visitor
.visit_pat(&arm
.pattern
);
221 visitor
.visit_expr(&visitor
.thir()[arm
.body
]);
224 pub fn walk_pat
<'thir
, 'tcx
: 'thir
, V
: Visitor
<'thir
, 'tcx
>>(
226 pat
: &'thir Pat
<'tcx
>,
230 AscribeUserType { subpattern, ascription: _ }
231 | Deref { subpattern }
232 | DerefPattern { subpattern, .. }
233 | Binding { subpattern: Some(subpattern), .. }
=> visitor
.visit_pat(subpattern
),
234 Binding { .. }
| Wild
| Never
| Error(_
) => {}
235 Variant { subpatterns, adt_def: _, args: _, variant_index: _ }
| Leaf { subpatterns }
=> {
236 for subpattern
in subpatterns
{
237 visitor
.visit_pat(&subpattern
.pattern
);
240 Constant { value: _ }
=> {}
241 InlineConstant { def: _, subpattern }
=> visitor
.visit_pat(subpattern
),
243 Slice { prefix, slice, suffix }
| Array { prefix, slice, suffix }
=> {
244 for subpattern
in prefix
.iter() {
245 visitor
.visit_pat(subpattern
);
247 if let Some(pat
) = slice
{
248 visitor
.visit_pat(pat
);
250 for subpattern
in suffix
.iter() {
251 visitor
.visit_pat(subpattern
);
255 for pat
in pats
.iter() {
256 visitor
.visit_pat(pat
);