1
Fork 0

Make body-visiting logic reusable

This commit is contained in:
Oli Scherer 2024-05-24 09:32:20 +00:00
parent be94ca0bcd
commit 53e3c3271f

View file

@ -782,6 +782,32 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
} }
self.enter_scope(Scope { id, data: ScopeData::Node }); self.enter_scope(Scope { id, data: ScopeData::Node });
} }
fn enter_body(&mut self, hir_id: hir::HirId, f: impl FnOnce(&mut Self)) {
// Save all state that is specific to the outer function
// body. These will be restored once down below, once we've
// visited the body.
let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0);
let outer_cx = self.cx;
let outer_ts = mem::take(&mut self.terminating_scopes);
// The 'pessimistic yield' flag is set to true when we are
// processing a `+=` statement and have to make pessimistic
// control flow assumptions. This doesn't apply to nested
// bodies within the `+=` statements. See #69307.
let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false);
self.terminating_scopes.insert(hir_id.local_id);
self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::CallSite });
self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::Arguments });
f(self);
// Restore context we had at the start.
self.expr_and_pat_count = outer_ec;
self.cx = outer_cx;
self.terminating_scopes = outer_ts;
self.pessimistic_yield = outer_pessimistic_yield;
}
} }
impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
@ -801,32 +827,17 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
self.cx.parent self.cx.parent
); );
// Save all state that is specific to the outer function self.enter_body(body.value.hir_id, |this| {
// body. These will be restored once down below, once we've if this.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
// visited the body.
let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0);
let outer_cx = self.cx;
let outer_ts = mem::take(&mut self.terminating_scopes);
// The 'pessimistic yield' flag is set to true when we are
// processing a `+=` statement and have to make pessimistic
// control flow assumptions. This doesn't apply to nested
// bodies within the `+=` statements. See #69307.
let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false);
self.terminating_scopes.insert(body.value.hir_id.local_id);
self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite });
self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments });
// The arguments and `self` are parented to the fn. // The arguments and `self` are parented to the fn.
self.cx.var_parent = self.cx.parent.take(); this.cx.var_parent = this.cx.parent.take();
for param in body.params { for param in body.params {
self.visit_pat(param.pat); this.visit_pat(param.pat);
} }
// The body of the every fn is a root scope. // The body of the every fn is a root scope.
self.cx.parent = self.cx.var_parent; this.cx.parent = this.cx.var_parent;
if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() { this.visit_expr(body.value)
self.visit_expr(body.value)
} else { } else {
// Only functions have an outer terminating (drop) scope, while // Only functions have an outer terminating (drop) scope, while
// temporaries in constant initializers may be 'static, but only // temporaries in constant initializers may be 'static, but only
@ -846,15 +857,10 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
// would *not* let the `f()` temporary escape into an outer scope // would *not* let the `f()` temporary escape into an outer scope
// (i.e., `'static`), which means that after `g` returns, it drops, // (i.e., `'static`), which means that after `g` returns, it drops,
// and all the associated destruction scope rules apply. // and all the associated destruction scope rules apply.
self.cx.var_parent = None; this.cx.var_parent = None;
resolve_local(self, None, Some(body.value)); resolve_local(this, None, Some(body.value));
} }
})
// Restore context we had at the start.
self.expr_and_pat_count = outer_ec;
self.cx = outer_cx;
self.terminating_scopes = outer_ts;
self.pessimistic_yield = outer_pessimistic_yield;
} }
fn visit_arm(&mut self, a: &'tcx Arm<'tcx>) { fn visit_arm(&mut self, a: &'tcx Arm<'tcx>) {