1
Fork 0

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); 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>) {} 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>) { pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
match stmt.kind { match &stmt.kind {
StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]), StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
StmtKind::Let { StmtKind::Let {
initializer, initializer,
remainder_scope: _, remainder_scope: _,
init_scope: _, init_scope: _,
pattern: _, pattern,
lint_level: _, lint_level: _,
} => { } => {
if let Some(init) = initializer { 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>) { pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
match arm.guard { match arm.guard {
Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]), 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]); visitor.visit_expr(&visitor.thir()[expr]);
} }
None => {} None => {}
} }
visitor.visit_pat(&arm.pattern);
visitor.visit_expr(&visitor.thir()[arm.body]); 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);
}
}
};
}