improve robustness of pat walkers

This commit is contained in:
Mazdak Farrokhzad 2019-12-14 23:43:21 +01:00
parent 5a8baa2876
commit b9aba749cf
3 changed files with 16 additions and 11 deletions

View file

@ -921,6 +921,16 @@ impl Pat {
pub fn walk(&self, mut it: impl FnMut(&Pat) -> bool) {
self.walk_(&mut it)
}
/// Walk the pattern in left-to-right order.
///
/// If you always want to recurse, prefer this method over `walk`.
pub fn walk_always(&self, mut it: impl FnMut(&Pat)) {
self.walk(|p| {
it(p);
true
})
}
}
/// A single field in a struct pattern.

View file

@ -79,11 +79,10 @@ impl hir::Pat {
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident)) {
self.walk(|p| {
self.walk_always(|p| {
if let PatKind::Binding(binding_mode, _, ident, _) = p.kind {
f(binding_mode, p.hir_id, p.span, ident);
}
true
});
}

View file

@ -269,7 +269,7 @@ fn const_not_var(err: &mut DiagnosticBuilder<'_>, tcx: TyCtxt<'_>, pat: &Pat, pa
}
fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pat) {
pat.walk(|p| {
pat.walk_always(|p| {
if let hir::PatKind::Binding(_, _, ident, None) = p.kind {
if let Some(ty::BindByValue(hir::Mutability::Not)) =
cx.tables.extract_binding_mode(cx.tcx.sess, p.hir_id, p.span)
@ -303,7 +303,6 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa
}
}
}
true
});
}
@ -602,7 +601,7 @@ fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: boo
by_move_spans.push(p.span);
}
};
pat.walk(|p| {
pat.walk_always(|p| {
if let hir::PatKind::Binding(.., sub) = &p.kind {
if let Some(ty::BindByValue(_)) = tables.extract_binding_mode(sess, p.hir_id, p.span) {
let pat_ty = tables.node_type(p.hir_id);
@ -611,7 +610,6 @@ fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: boo
}
}
}
true
});
// Found some bad by-move spans, error!
@ -640,16 +638,16 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat) {
ty::BindByValue(_) => None,
ty::BindByReference(m) => Some(m),
};
pat.walk(|pat| {
pat.walk_always(|pat| {
// Extract `sub` in `binding @ sub`.
let (name, sub) = match &pat.kind {
hir::PatKind::Binding(.., name, Some(sub)) => (*name, sub),
_ => return true,
_ => return,
};
// Extract the mutability.
let mut_outer = match extract_binding_mut(pat.hir_id, pat.span) {
None => return true,
None => return,
Some(m) => m,
};
@ -698,8 +696,6 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat) {
}
err.emit();
}
true
});
}