From b9aba749cfc192422d879b12c7a5c3674f5ad110 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 14 Dec 2019 23:43:21 +0100 Subject: [PATCH] improve robustness of pat walkers --- src/librustc/hir/mod.rs | 10 ++++++++++ src/librustc/hir/pat_util.rs | 3 +-- src/librustc_mir/hair/pattern/check_match.rs | 14 +++++--------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 4aa8c12a219..a85685caf7d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -921,6 +921,16 @@ fn walk_(&self, it: &mut impl FnMut(&Pat) -> bool) { 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. diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index c0aa54beac2..8d3b464a8ff 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -79,11 +79,10 @@ pub fn is_refutable(&self) -> bool { /// 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 }); } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 3cfafaf1806..30501e4504d 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -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 }); } -- 2.44.0