Skip to content

Commit 24442ff

Browse files
committed
add subregion between borrow region and resulting reference
1 parent af09f72 commit 24442ff

File tree

4 files changed

+113
-8
lines changed

4 files changed

+113
-8
lines changed

src/librustc/mir/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,14 @@ impl fmt::Debug for Location {
16371637
}
16381638

16391639
impl Location {
1640+
/// Returns the location immediately after this one within the enclosing block.
1641+
///
1642+
/// Note that if this location represents a terminator, then the
1643+
/// resulting location would be out of bounds and invalid.
1644+
pub fn successor_within_block(&self) -> Location {
1645+
Location { block: self.block, statement_index: self.statement_index + 1 }
1646+
}
1647+
16401648
pub fn dominates(&self, other: &Location, dominators: &Dominators<BasicBlock>) -> bool {
16411649
if self.block == other.block {
16421650
self.statement_index <= other.statement_index

src/librustc_mir/transform/nll/constraint_generation.rs

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use rustc::mir::{Location, Mir};
11+
use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind};
1212
use rustc::mir::transform::MirSource;
13+
use rustc::mir::visit::Visitor;
1314
use rustc::infer::InferCtxt;
1415
use rustc::traits::{self, ObligationCause};
1516
use rustc::ty::{self, Ty};
@@ -38,18 +39,18 @@ pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
3839
}.add_constraints();
3940
}
4041

41-
struct ConstraintGeneration<'constrain, 'gcx: 'tcx, 'tcx: 'constrain> {
42-
infcx: &'constrain InferCtxt<'constrain, 'gcx, 'tcx>,
43-
regioncx: &'constrain mut RegionInferenceContext,
44-
mir: &'constrain Mir<'tcx>,
45-
liveness: &'constrain LivenessResults,
42+
struct ConstraintGeneration<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
43+
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
44+
regioncx: &'cx mut RegionInferenceContext,
45+
mir: &'cx Mir<'tcx>,
46+
liveness: &'cx LivenessResults,
4647
mir_source: MirSource,
4748
}
4849

49-
impl<'constrain, 'gcx, 'tcx> ConstraintGeneration<'constrain, 'gcx, 'tcx> {
50+
impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
5051
fn add_constraints(&mut self) {
51-
// To start, add the liveness constraints.
5252
self.add_liveness_constraints();
53+
self.add_borrow_constraints();
5354
}
5455

5556
/// Liveness constraints:
@@ -172,4 +173,50 @@ impl<'constrain, 'gcx, 'tcx> ConstraintGeneration<'constrain, 'gcx, 'tcx> {
172173
}
173174
}
174175
}
176+
177+
fn add_borrow_constraints(&mut self) {
178+
self.visit_mir(self.mir);
179+
}
180+
181+
fn add_borrow_constraint(
182+
&mut self,
183+
location: Location,
184+
destination_lv: &Lvalue<'tcx>,
185+
borrow_region: ty::Region<'tcx>,
186+
_borrow_kind: BorrowKind,
187+
_borrowed_lv: &Lvalue<'tcx>,
188+
) {
189+
let tcx = self.infcx.tcx;
190+
let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
191+
192+
let destination_region = match destination_ty.sty {
193+
ty::TyRef(r, _) => r,
194+
_ => bug!()
195+
};
196+
197+
self.regioncx.add_outlives(borrow_region.to_region_index(),
198+
destination_region.to_region_index(),
199+
location.successor_within_block());
200+
}
201+
}
202+
203+
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
204+
fn visit_statement(&mut self,
205+
block: BasicBlock,
206+
statement: &Statement<'tcx>,
207+
location: Location) {
208+
// Look for a statement like:
209+
//
210+
// D = & L
211+
//
212+
// where D is the path to which we are assigning, and
213+
// L is the path that is borrowed.
214+
if let StatementKind::Assign(ref destination_lv, ref rv) = statement.kind {
215+
if let Rvalue::Ref(region, bk, ref borrowed_lv) = *rv {
216+
self.add_borrow_constraint(location, destination_lv, region, bk, borrowed_lv);
217+
}
218+
}
219+
220+
self.super_statement(block, statement, location);
221+
}
175222
}

src/test/mir-opt/nll/region-liveness-basic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ fn main() {
3131

3232
// END RUST SOURCE
3333
// START rustc.node12.nll.0.mir
34+
// | R0: {bb1[1], bb2[0], bb2[1]}
3435
// | R1: {bb1[1], bb2[0], bb2[1]}
3536
// ...
3637
// let _2: &'_#1r usize;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test for the subregion constraints. In this case, the region R3 on
12+
// `p` includes two disjoint regions of the control-flow graph. The
13+
// borrows in `&v[0]` and `&v[1]` each (in theory) have to outlive R3,
14+
// but only at a particular point, and hence they wind up including
15+
// distinct regions.
16+
17+
// compile-flags:-Znll -Zverbose
18+
// ^^^^^^^^^ force compiler to dump more region information
19+
20+
#![allow(warnings)]
21+
22+
fn use_x(_: usize) -> bool { true }
23+
24+
fn main() {
25+
let mut v = [1, 2, 3];
26+
let mut p = &v[0];
27+
if true {
28+
use_x(*p);
29+
} else {
30+
use_x(22);
31+
}
32+
33+
p = &v[1];
34+
use_x(*p);
35+
}
36+
37+
// END RUST SOURCE
38+
// START rustc.node12.nll.0.mir
39+
// | R0: {bb1[1], bb2[0], bb2[1]}
40+
// ...
41+
// | R2: {bb7[2], bb7[3], bb7[4]}
42+
// | R3: {bb1[1], bb2[0], bb2[1], bb7[2], bb7[3], bb7[4]}
43+
// ...
44+
// let mut _2: &'_#3r usize;
45+
// ...
46+
// _2 = &'_#0r _1[_3];
47+
// ...
48+
// _2 = &'_#2r (*_10);
49+
// END rustc.node12.nll.0.mir

0 commit comments

Comments
 (0)