1
Fork 0

dedicated visitor for arm patterns

This commit is contained in:
Ding Xiang Fei 2020-10-07 12:58:02 +08:00
parent df127b86cb
commit 4a8ba7b031
No known key found for this signature in database
GPG key ID: 3CD748647EEF6359

View file

@ -28,9 +28,8 @@ struct InteriorVisitor<'a, 'tcx> {
/// such borrows can span across this yield point. /// such borrows can span across this yield point.
/// As such, we need to track these borrows and record them despite of the fact /// As such, we need to track these borrows and record them despite of the fact
/// that they may succeed the said yield point in the post-order. /// that they may succeed the said yield point in the post-order.
nested_scope_of_guards: SmallVec<[SmallVec<[HirId; 4]>; 4]>, guard_bindings: SmallVec<[SmallVec<[HirId; 4]>; 1]>,
current_scope_of_guards: HirIdSet, guard_bindings_set: HirIdSet,
arm_has_guard: bool,
} }
impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
@ -147,9 +146,8 @@ pub fn resolve_interior<'a, 'tcx>(
expr_count: 0, expr_count: 0,
kind, kind,
prev_unresolved_span: None, prev_unresolved_span: None,
nested_scope_of_guards: <_>::default(), guard_bindings: <_>::default(),
current_scope_of_guards: <_>::default(), guard_bindings_set: <_>::default(),
arm_has_guard: false,
}; };
intravisit::walk_body(&mut visitor, body); intravisit::walk_body(&mut visitor, body);
@ -228,25 +226,34 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
fn visit_arm(&mut self, arm: &'tcx Arm<'tcx>) { fn visit_arm(&mut self, arm: &'tcx Arm<'tcx>) {
if arm.guard.is_some() { if arm.guard.is_some() {
self.nested_scope_of_guards.push(<_>::default()); self.guard_bindings.push(<_>::default());
self.arm_has_guard = true;
} }
self.visit_pat(&arm.pat); self.visit_pat(&arm.pat);
if let Some(ref g) = arm.guard { if let Some(ref g) = arm.guard {
self.guard_bindings.push(<_>::default());
ArmPatCollector {
guard_bindings_set: &mut self.guard_bindings_set,
guard_bindings: self
.guard_bindings
.last_mut()
.expect("should have pushed at least one earlier"),
}
.visit_pat(&arm.pat);
match g { match g {
Guard::If(ref e) => { Guard::If(ref e) => {
self.visit_expr(e); self.visit_expr(e);
} }
} }
let mut scope_var_ids = let mut scope_var_ids =
self.nested_scope_of_guards.pop().expect("should have pushed at least one earlier"); self.guard_bindings.pop().expect("should have pushed at least one earlier");
for var_id in scope_var_ids.drain(..) { for var_id in scope_var_ids.drain(..) {
assert!( assert!(
self.current_scope_of_guards.remove(&var_id), self.guard_bindings_set.remove(&var_id),
"variable should be placed in scope earlier" "variable should be placed in scope earlier"
); );
} }
self.arm_has_guard = false;
} }
self.visit_expr(&arm.body); self.visit_expr(&arm.body);
} }
@ -256,14 +263,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
self.expr_count += 1; self.expr_count += 1;
if let PatKind::Binding(_, id, ..) = pat.kind { if let PatKind::Binding(..) = pat.kind {
let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id); let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id);
let ty = self.fcx.typeck_results.borrow().pat_ty(pat); let ty = self.fcx.typeck_results.borrow().pat_ty(pat);
self.record(ty, Some(scope), None, pat.span, false); self.record(ty, Some(scope), None, pat.span, false);
if self.arm_has_guard {
self.nested_scope_of_guards.as_mut_slice().last_mut().unwrap().push(id);
self.current_scope_of_guards.insert(id);
}
} }
} }
@ -299,8 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
intravisit::walk_expr(self, expr); intravisit::walk_expr(self, expr);
let res = self.fcx.typeck_results.borrow().qpath_res(qpath, expr.hir_id); let res = self.fcx.typeck_results.borrow().qpath_res(qpath, expr.hir_id);
match res { match res {
Res::Local(id) if self.current_scope_of_guards.contains(&id) => { Res::Local(id) if self.guard_bindings_set.contains(&id) => {
debug!("a borrow in guard from pattern local is detected");
guard_borrowing_from_pattern = true; guard_borrowing_from_pattern = true;
} }
_ => {} _ => {}
@ -350,3 +352,24 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
} }
} }
} }
struct ArmPatCollector<'a> {
guard_bindings_set: &'a mut HirIdSet,
guard_bindings: &'a mut SmallVec<[HirId; 4]>,
}
impl<'a, 'tcx> Visitor<'tcx> for ArmPatCollector<'a> {
type Map = intravisit::ErasedMap<'tcx>;
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
NestedVisitorMap::None
}
fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
intravisit::walk_pat(self, pat);
if let PatKind::Binding(_, id, ..) = pat.kind {
self.guard_bindings.push(id);
self.guard_bindings_set.insert(id);
}
}
}