mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +00:00
Don't count MIR locals as borrowed after StorageDead when finding locals live across a yield terminator
This commit is contained in:
parent
f89817997a
commit
0babbf11e6
@ -15,9 +15,9 @@ use rustc::mir::visit::Visitor;
|
|||||||
use dataflow::BitDenotation;
|
use dataflow::BitDenotation;
|
||||||
|
|
||||||
/// This calculates if any part of a MIR local could have previously been borrowed.
|
/// 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
|
/// This means that once a local has been borrowed, its bit will be set
|
||||||
/// from that point and onwards, even if the borrow ends. You could also think of this
|
/// from that point and onwards, until we see a StorageDead statement for the local,
|
||||||
/// as computing the lifetimes of infinite borrows.
|
/// 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
|
/// This is used to compute which locals are live during a yield expression for
|
||||||
/// immovable generators.
|
/// immovable generators.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -50,9 +50,17 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
|
|||||||
fn statement_effect(&self,
|
fn statement_effect(&self,
|
||||||
sets: &mut BlockSets<Local>,
|
sets: &mut BlockSets<Local>,
|
||||||
loc: Location) {
|
loc: Location) {
|
||||||
|
let stmt = &self.mir[loc.block].statements[loc.statement_index];
|
||||||
|
|
||||||
BorrowedLocalsVisitor {
|
BorrowedLocalsVisitor {
|
||||||
sets,
|
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,
|
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.
|
// The `liveness` variable contains the liveness of MIR locals ignoring borrows.
|
||||||
// This is correct for movable generators since borrows cannot live across
|
// This is correct for movable generators since borrows cannot live across
|
||||||
// suspension points. However for immovable generators we need to account for
|
// 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
|
// 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.
|
// 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
|
// 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…
Reference in New Issue
Block a user