mirror of https://github.com/rust-lang/rust.git
Make body-visiting logic reusable
This commit is contained in:
parent
be94ca0bcd
commit
53e3c3271f
|
@ -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,60 +827,40 @@ 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.
|
// The arguments and `self` are parented to the fn.
|
||||||
let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0);
|
this.cx.var_parent = this.cx.parent.take();
|
||||||
let outer_cx = self.cx;
|
for param in body.params {
|
||||||
let outer_ts = mem::take(&mut self.terminating_scopes);
|
this.visit_pat(param.pat);
|
||||||
// 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 });
|
// The body of the every fn is a root scope.
|
||||||
self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments });
|
this.cx.parent = this.cx.var_parent;
|
||||||
|
this.visit_expr(body.value)
|
||||||
// The arguments and `self` are parented to the fn.
|
} else {
|
||||||
self.cx.var_parent = self.cx.parent.take();
|
// Only functions have an outer terminating (drop) scope, while
|
||||||
for param in body.params {
|
// temporaries in constant initializers may be 'static, but only
|
||||||
self.visit_pat(param.pat);
|
// according to rvalue lifetime semantics, using the same
|
||||||
}
|
// syntactical rules used for let initializers.
|
||||||
|
//
|
||||||
// The body of the every fn is a root scope.
|
// e.g., in `let x = &f();`, the temporary holding the result from
|
||||||
self.cx.parent = self.cx.var_parent;
|
// the `f()` call lives for the entirety of the surrounding block.
|
||||||
if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
|
//
|
||||||
self.visit_expr(body.value)
|
// Similarly, `const X: ... = &f();` would have the result of `f()`
|
||||||
} else {
|
// live for `'static`, implying (if Drop restrictions on constants
|
||||||
// Only functions have an outer terminating (drop) scope, while
|
// ever get lifted) that the value *could* have a destructor, but
|
||||||
// temporaries in constant initializers may be 'static, but only
|
// it'd get leaked instead of the destructor running during the
|
||||||
// according to rvalue lifetime semantics, using the same
|
// evaluation of `X` (if at all allowed by CTFE).
|
||||||
// syntactical rules used for let initializers.
|
//
|
||||||
//
|
// However, `const Y: ... = g(&f());`, like `let y = g(&f());`,
|
||||||
// e.g., in `let x = &f();`, the temporary holding the result from
|
// would *not* let the `f()` temporary escape into an outer scope
|
||||||
// the `f()` call lives for the entirety of the surrounding block.
|
// (i.e., `'static`), which means that after `g` returns, it drops,
|
||||||
//
|
// and all the associated destruction scope rules apply.
|
||||||
// Similarly, `const X: ... = &f();` would have the result of `f()`
|
this.cx.var_parent = None;
|
||||||
// live for `'static`, implying (if Drop restrictions on constants
|
resolve_local(this, None, Some(body.value));
|
||||||
// ever get lifted) that the value *could* have a destructor, but
|
}
|
||||||
// it'd get leaked instead of the destructor running during the
|
})
|
||||||
// evaluation of `X` (if at all allowed by CTFE).
|
|
||||||
//
|
|
||||||
// However, `const Y: ... = g(&f());`, like `let y = g(&f());`,
|
|
||||||
// would *not* let the `f()` temporary escape into an outer scope
|
|
||||||
// (i.e., `'static`), which means that after `g` returns, it drops,
|
|
||||||
// and all the associated destruction scope rules apply.
|
|
||||||
self.cx.var_parent = None;
|
|
||||||
resolve_local(self, 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>) {
|
||||||
|
|
Loading…
Reference in New Issue