Rollup merge of #52915 - Zoxc:refine-gen-borrow-analysis, r=eddyb

Don't count MIR locals as borrowed after StorageDead when finding locals live across a yield terminator

This should fix https://github.com/rust-lang/rust/issues/52792.

r? @eddyb
This commit is contained in:
Pietro Albini 2018-08-01 21:46:32 +02:00 committed by GitHub
commit b40b899690
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 5 deletions

View File

@ -15,9 +15,9 @@ use rustc::mir::visit::Visitor;
use dataflow::BitDenotation;
/// This calculates if any part of a MIR local could have previously been borrowed.
/// This means that once a local has been borrowed, its bit will always be set
/// from that point and onwards, even if the borrow ends. You could also think of this
/// as computing the lifetimes of infinite borrows.
/// This means that once a local has been borrowed, its bit will be set
/// from that point and onwards, until we see a StorageDead statement for the local,
/// at which points there is no memory associated with the local, so it cannot be borrowed.
/// This is used to compute which locals are live during a yield expression for
/// immovable generators.
#[derive(Copy, Clone)]
@ -50,9 +50,17 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
fn statement_effect(&self,
sets: &mut BlockSets<Local>,
loc: Location) {
let stmt = &self.mir[loc.block].statements[loc.statement_index];
BorrowedLocalsVisitor {
sets,
}.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc);
}.visit_statement(loc.block, stmt, loc);
// StorageDead invalidates all borrows and raw pointers to a local
match stmt.kind {
StatementKind::StorageDead(l) => sets.kill(&l),
_ => (),
}
}
fn terminator_effect(&self,

View File

@ -433,7 +433,8 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// The `liveness` variable contains the liveness of MIR locals ignoring borrows.
// This is correct for movable generators since borrows cannot live across
// suspension points. However for immovable generators we need to account for
// borrows, so we conseratively assume that all borrowed locals live forever.
// borrows, so we conseratively assume that all borrowed locals are live until
// we find a StorageDead statement referencing the locals.
// To do this we just union our `liveness` result with `borrowed_locals`, which
// contains all the locals which has been borrowed before this suspension point.
// If a borrow is converted to a raw reference, we must also assume that it lives

View File

@ -0,0 +1,25 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(generators)]
fn main() {
static || {
loop {
// Test that `opt` is not live across the yield, even when borrowed in a loop
// See https://github.com/rust-lang/rust/issues/52792
let opt = {
yield;
true
};
&opt;
}
};
}