add subregion between borrow region and resulting reference
This commit is contained in:
parent
af09f720d6
commit
24442ffa66
4 changed files with 113 additions and 8 deletions
|
@ -1637,6 +1637,14 @@ impl fmt::Debug for Location {
|
|||
}
|
||||
|
||||
impl Location {
|
||||
/// Returns the location immediately after this one within the enclosing block.
|
||||
///
|
||||
/// Note that if this location represents a terminator, then the
|
||||
/// resulting location would be out of bounds and invalid.
|
||||
pub fn successor_within_block(&self) -> Location {
|
||||
Location { block: self.block, statement_index: self.statement_index + 1 }
|
||||
}
|
||||
|
||||
pub fn dominates(&self, other: &Location, dominators: &Dominators<BasicBlock>) -> bool {
|
||||
if self.block == other.block {
|
||||
self.statement_index <= other.statement_index
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::mir::{Location, Mir};
|
||||
use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::Visitor;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::traits::{self, ObligationCause};
|
||||
use rustc::ty::{self, Ty};
|
||||
|
@ -38,18 +39,18 @@ pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
|
|||
}.add_constraints();
|
||||
}
|
||||
|
||||
struct ConstraintGeneration<'constrain, 'gcx: 'tcx, 'tcx: 'constrain> {
|
||||
infcx: &'constrain InferCtxt<'constrain, 'gcx, 'tcx>,
|
||||
regioncx: &'constrain mut RegionInferenceContext,
|
||||
mir: &'constrain Mir<'tcx>,
|
||||
liveness: &'constrain LivenessResults,
|
||||
struct ConstraintGeneration<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
regioncx: &'cx mut RegionInferenceContext,
|
||||
mir: &'cx Mir<'tcx>,
|
||||
liveness: &'cx LivenessResults,
|
||||
mir_source: MirSource,
|
||||
}
|
||||
|
||||
impl<'constrain, 'gcx, 'tcx> ConstraintGeneration<'constrain, 'gcx, 'tcx> {
|
||||
impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
|
||||
fn add_constraints(&mut self) {
|
||||
// To start, add the liveness constraints.
|
||||
self.add_liveness_constraints();
|
||||
self.add_borrow_constraints();
|
||||
}
|
||||
|
||||
/// Liveness constraints:
|
||||
|
@ -172,4 +173,50 @@ impl<'constrain, 'gcx, 'tcx> ConstraintGeneration<'constrain, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_borrow_constraints(&mut self) {
|
||||
self.visit_mir(self.mir);
|
||||
}
|
||||
|
||||
fn add_borrow_constraint(
|
||||
&mut self,
|
||||
location: Location,
|
||||
destination_lv: &Lvalue<'tcx>,
|
||||
borrow_region: ty::Region<'tcx>,
|
||||
_borrow_kind: BorrowKind,
|
||||
_borrowed_lv: &Lvalue<'tcx>,
|
||||
) {
|
||||
let tcx = self.infcx.tcx;
|
||||
let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
|
||||
|
||||
let destination_region = match destination_ty.sty {
|
||||
ty::TyRef(r, _) => r,
|
||||
_ => bug!()
|
||||
};
|
||||
|
||||
self.regioncx.add_outlives(borrow_region.to_region_index(),
|
||||
destination_region.to_region_index(),
|
||||
location.successor_within_block());
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
|
||||
fn visit_statement(&mut self,
|
||||
block: BasicBlock,
|
||||
statement: &Statement<'tcx>,
|
||||
location: Location) {
|
||||
// Look for a statement like:
|
||||
//
|
||||
// D = & L
|
||||
//
|
||||
// where D is the path to which we are assigning, and
|
||||
// L is the path that is borrowed.
|
||||
if let StatementKind::Assign(ref destination_lv, ref rv) = statement.kind {
|
||||
if let Rvalue::Ref(region, bk, ref borrowed_lv) = *rv {
|
||||
self.add_borrow_constraint(location, destination_lv, region, bk, borrowed_lv);
|
||||
}
|
||||
}
|
||||
|
||||
self.super_statement(block, statement, location);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ fn main() {
|
|||
|
||||
// END RUST SOURCE
|
||||
// START rustc.node12.nll.0.mir
|
||||
// | R0: {bb1[1], bb2[0], bb2[1]}
|
||||
// | R1: {bb1[1], bb2[0], bb2[1]}
|
||||
// ...
|
||||
// let _2: &'_#1r usize;
|
||||
|
|
49
src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
Normal file
49
src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2012-2016 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.
|
||||
|
||||
// Test for the subregion constraints. In this case, the region R3 on
|
||||
// `p` includes two disjoint regions of the control-flow graph. The
|
||||
// borrows in `&v[0]` and `&v[1]` each (in theory) have to outlive R3,
|
||||
// but only at a particular point, and hence they wind up including
|
||||
// distinct regions.
|
||||
|
||||
// compile-flags:-Znll -Zverbose
|
||||
// ^^^^^^^^^ force compiler to dump more region information
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
fn use_x(_: usize) -> bool { true }
|
||||
|
||||
fn main() {
|
||||
let mut v = [1, 2, 3];
|
||||
let mut p = &v[0];
|
||||
if true {
|
||||
use_x(*p);
|
||||
} else {
|
||||
use_x(22);
|
||||
}
|
||||
|
||||
p = &v[1];
|
||||
use_x(*p);
|
||||
}
|
||||
|
||||
// END RUST SOURCE
|
||||
// START rustc.node12.nll.0.mir
|
||||
// | R0: {bb1[1], bb2[0], bb2[1]}
|
||||
// ...
|
||||
// | R2: {bb7[2], bb7[3], bb7[4]}
|
||||
// | R3: {bb1[1], bb2[0], bb2[1], bb7[2], bb7[3], bb7[4]}
|
||||
// ...
|
||||
// let mut _2: &'_#3r usize;
|
||||
// ...
|
||||
// _2 = &'_#0r _1[_3];
|
||||
// ...
|
||||
// _2 = &'_#2r (*_10);
|
||||
// END rustc.node12.nll.0.mir
|
Loading…
Add table
Add a link
Reference in a new issue