Skip to content

Commit 53e3c32

Browse files
committed
Make body-visiting logic reusable
1 parent be94ca0 commit 53e3c32

File tree

1 file changed

+59
-53
lines changed
  • compiler/rustc_hir_analysis/src/check

1 file changed

+59
-53
lines changed

compiler/rustc_hir_analysis/src/check/region.rs

+59-53
Original file line numberDiff line numberDiff line change
@@ -782,25 +782,8 @@ impl<'tcx> RegionResolutionVisitor<'tcx> {
782782
}
783783
self.enter_scope(Scope { id, data: ScopeData::Node });
784784
}
785-
}
786-
787-
impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
788-
fn visit_block(&mut self, b: &'tcx Block<'tcx>) {
789-
resolve_block(self, b);
790-
}
791-
792-
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
793-
let body_id = body.id();
794-
let owner_id = self.tcx.hir().body_owner_def_id(body_id);
795-
796-
debug!(
797-
"visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})",
798-
owner_id,
799-
self.tcx.sess.source_map().span_to_diagnostic_string(body.value.span),
800-
body_id,
801-
self.cx.parent
802-
);
803785

786+
fn enter_body(&mut self, hir_id: hir::HirId, f: impl FnOnce(&mut Self)) {
804787
// Save all state that is specific to the outer function
805788
// body. These will be restored once down below, once we've
806789
// visited the body.
@@ -812,50 +795,73 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
812795
// control flow assumptions. This doesn't apply to nested
813796
// bodies within the `+=` statements. See #69307.
814797
let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false);
815-
self.terminating_scopes.insert(body.value.hir_id.local_id);
816-
817-
self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite });
818-
self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments });
798+
self.terminating_scopes.insert(hir_id.local_id);
819799

820-
// The arguments and `self` are parented to the fn.
821-
self.cx.var_parent = self.cx.parent.take();
822-
for param in body.params {
823-
self.visit_pat(param.pat);
824-
}
800+
self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::CallSite });
801+
self.enter_scope(Scope { id: hir_id.local_id, data: ScopeData::Arguments });
825802

826-
// The body of the every fn is a root scope.
827-
self.cx.parent = self.cx.var_parent;
828-
if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
829-
self.visit_expr(body.value)
830-
} else {
831-
// Only functions have an outer terminating (drop) scope, while
832-
// temporaries in constant initializers may be 'static, but only
833-
// according to rvalue lifetime semantics, using the same
834-
// syntactical rules used for let initializers.
835-
//
836-
// e.g., in `let x = &f();`, the temporary holding the result from
837-
// the `f()` call lives for the entirety of the surrounding block.
838-
//
839-
// Similarly, `const X: ... = &f();` would have the result of `f()`
840-
// live for `'static`, implying (if Drop restrictions on constants
841-
// ever get lifted) that the value *could* have a destructor, but
842-
// it'd get leaked instead of the destructor running during the
843-
// evaluation of `X` (if at all allowed by CTFE).
844-
//
845-
// However, `const Y: ... = g(&f());`, like `let y = g(&f());`,
846-
// would *not* let the `f()` temporary escape into an outer scope
847-
// (i.e., `'static`), which means that after `g` returns, it drops,
848-
// and all the associated destruction scope rules apply.
849-
self.cx.var_parent = None;
850-
resolve_local(self, None, Some(body.value));
851-
}
803+
f(self);
852804

853805
// Restore context we had at the start.
854806
self.expr_and_pat_count = outer_ec;
855807
self.cx = outer_cx;
856808
self.terminating_scopes = outer_ts;
857809
self.pessimistic_yield = outer_pessimistic_yield;
858810
}
811+
}
812+
813+
impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
814+
fn visit_block(&mut self, b: &'tcx Block<'tcx>) {
815+
resolve_block(self, b);
816+
}
817+
818+
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
819+
let body_id = body.id();
820+
let owner_id = self.tcx.hir().body_owner_def_id(body_id);
821+
822+
debug!(
823+
"visit_body(id={:?}, span={:?}, body.id={:?}, cx.parent={:?})",
824+
owner_id,
825+
self.tcx.sess.source_map().span_to_diagnostic_string(body.value.span),
826+
body_id,
827+
self.cx.parent
828+
);
829+
830+
self.enter_body(body.value.hir_id, |this| {
831+
if this.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
832+
// The arguments and `self` are parented to the fn.
833+
this.cx.var_parent = this.cx.parent.take();
834+
for param in body.params {
835+
this.visit_pat(param.pat);
836+
}
837+
838+
// The body of the every fn is a root scope.
839+
this.cx.parent = this.cx.var_parent;
840+
this.visit_expr(body.value)
841+
} else {
842+
// Only functions have an outer terminating (drop) scope, while
843+
// temporaries in constant initializers may be 'static, but only
844+
// according to rvalue lifetime semantics, using the same
845+
// syntactical rules used for let initializers.
846+
//
847+
// e.g., in `let x = &f();`, the temporary holding the result from
848+
// the `f()` call lives for the entirety of the surrounding block.
849+
//
850+
// Similarly, `const X: ... = &f();` would have the result of `f()`
851+
// live for `'static`, implying (if Drop restrictions on constants
852+
// ever get lifted) that the value *could* have a destructor, but
853+
// it'd get leaked instead of the destructor running during the
854+
// evaluation of `X` (if at all allowed by CTFE).
855+
//
856+
// However, `const Y: ... = g(&f());`, like `let y = g(&f());`,
857+
// would *not* let the `f()` temporary escape into an outer scope
858+
// (i.e., `'static`), which means that after `g` returns, it drops,
859+
// and all the associated destruction scope rules apply.
860+
this.cx.var_parent = None;
861+
resolve_local(this, None, Some(body.value));
862+
}
863+
})
864+
}
859865

860866
fn visit_arm(&mut self, a: &'tcx Arm<'tcx>) {
861867
resolve_arm(self, a);

0 commit comments

Comments
 (0)