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:
commit
b40b899690
@ -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,
|
||||
|
@ -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
|
||||
|
25
src/test/run-pass/generator/yield-in-initializer.rs
Normal file
25
src/test/run-pass/generator/yield-in-initializer.rs
Normal 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;
|
||||
}
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user