[drop tracking] Use parent expression for scope

Previously we were just using the parent node as the scope for a
temporary value, but it turns out this is too narrow. For example, in
an expression like

    Foo {
        b: &42,
        a: async { 0 }.await,
    }

the scope for the &42 was set to the ExprField node for `b: &42`, when
we actually want to use the Foo struct expression.

We fix this by recursively searching through parent nodes until we find
a Node::Expr. It may be that we don't find one, and if so that's okay,
we will just fall back on the enclosing temporary scope which is always
sufficient.
This commit is contained in:
Eric Holk 2022-08-30 15:17:45 -07:00
parent 230a8ee364
commit b9d3f65412
3 changed files with 20 additions and 4 deletions

View File

@ -387,6 +387,18 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
ty.needs_drop(self.fcx.tcx, self.fcx.param_env)
};
let find_parent_expr = |mut hir_id| {
let hir = self.fcx.tcx.hir();
hir_id = hir.find_parent_node(hir_id)?;
loop {
if let hir::Node::Expr(_) = self.fcx.tcx.hir().find(hir_id)? {
return Some(hir_id);
} else {
hir_id = hir.find_parent_node(hir_id)?;
}
}
};
// Typically, the value produced by an expression is consumed by its parent in some way,
// so we only have to check if the parent contains a yield (note that the parent may, for
// example, store the value into a local variable, but then we already consider local
@ -409,8 +421,9 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
}) {
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
} else {
debug!("parent_node: {:?}", self.fcx.tcx.hir().find_parent_node(expr.hir_id));
match self.fcx.tcx.hir().find_parent_node(expr.hir_id) {
let parent_expr = find_parent_expr(expr.hir_id);
debug!("parent_expr: {:?}", parent_expr);
match parent_expr {
Some(parent) => Some(Scope { id: parent.local_id, data: ScopeData::Node }),
None => {
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)

View File

@ -159,8 +159,8 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
bk: rustc_middle::ty::BorrowKind,
) {
debug!(
"borrow: place_with_id = {place_with_id:?}, diag_expr_id={diag_expr_id:?}, \
borrow_kind={bk:?}"
"borrow: place_with_id = {place_with_id:#?}, diag_expr_id={diag_expr_id:#?}, \
borrow_kind={bk:#?}"
);
self.borrow_place(place_with_id);

View File

@ -2,6 +2,9 @@
// run-pass
// edition:2018
// revisions: normal drop-tracking
// [normal]compile-flags: -Zdrop-tracking=no
// [drop-tracking]compile-flags: -Zdrop-tracking
#![allow(dead_code)]
use std::future::Future;