Add pattern walking support to THIR walker

This commit is contained in:
Smitty 2021-06-16 16:36:43 -04:00
parent 9fef8d91b4
commit 210e46bf24

View file

@ -20,6 +20,10 @@ pub trait Visitor<'a, 'tcx: 'a>: Sized {
walk_arm(self, arm);
}
fn visit_pat(&mut self, pat: &Pat<'tcx>) {
walk_pat(self, pat);
}
fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
}
@ -142,18 +146,19 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
}
pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
match stmt.kind {
StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]),
match &stmt.kind {
StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
StmtKind::Let {
initializer,
remainder_scope: _,
init_scope: _,
pattern: _,
pattern,
lint_level: _,
} => {
if let Some(init) = initializer {
visitor.visit_expr(&visitor.thir()[init]);
visitor.visit_expr(&visitor.thir()[*init]);
}
visitor.visit_pat(&pattern);
}
}
}
@ -170,10 +175,48 @@ pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &B
pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
match arm.guard {
Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
Some(Guard::IfLet(ref _pat, expr)) => {
Some(Guard::IfLet(ref pat, expr)) => {
visitor.visit_pat(pat);
visitor.visit_expr(&visitor.thir()[expr]);
}
None => {}
}
visitor.visit_pat(&arm.pattern);
visitor.visit_expr(&visitor.thir()[arm.body]);
}
pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
use PatKind::*;
match pat.kind.as_ref() {
AscribeUserType { subpattern, .. }
| Deref { subpattern, .. }
| Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(&subpattern),
Binding { .. } | Wild => {}
Variant { subpatterns, .. } | Leaf { subpatterns } => {
for subpattern in subpatterns {
visitor.visit_pat(&subpattern.pattern);
}
}
Constant { value } => visitor.visit_const(value),
Range(range) => {
visitor.visit_const(range.lo);
visitor.visit_const(range.hi);
}
Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
for subpattern in prefix {
visitor.visit_pat(&subpattern);
}
if let Some(pat) = slice {
visitor.visit_pat(pat);
}
for subpattern in suffix {
visitor.visit_pat(&subpattern);
}
}
Or { pats } => {
for pat in pats {
visitor.visit_pat(&pat);
}
}
};
}