Skip to content

Commit b8615f3

Browse files
spastorinonikomatsakis
authored andcommitted
add reborrow constraints
1 parent f700728 commit b8615f3

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

src/librustc_mir/transform/nll/constraint_generation.rs

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

11+
use rustc::hir;
1112
use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind};
1213
use rustc::mir::transform::MirSource;
1314
use rustc::mir::visit::Visitor;
15+
use rustc::mir::Lvalue::Projection;
16+
use rustc::mir::{LvalueProjection, ProjectionElem};
1417
use rustc::infer::InferCtxt;
1518
use rustc::traits::{self, ObligationCause};
1619
use rustc::ty::{self, Ty};
@@ -198,6 +201,37 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
198201
destination_region.to_region_index(),
199202
location.successor_within_block());
200203
}
204+
205+
fn add_reborrow_constraint(
206+
&mut self,
207+
location: Location,
208+
borrow_region: ty::Region<'tcx>,
209+
borrowed_lv: &Lvalue<'tcx>,
210+
) {
211+
if let Projection(ref proj) = *borrowed_lv {
212+
let LvalueProjection { ref base, ref elem } = **proj;
213+
214+
if let ProjectionElem::Deref = *elem {
215+
let tcx = self.infcx.tcx;
216+
let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
217+
let base_sty = &base_ty.sty;
218+
219+
if let ty::TyRef(base_region, ty::TypeAndMut{ ty: _, mutbl }) = *base_sty {
220+
match mutbl {
221+
hir::Mutability::MutImmutable => { },
222+
223+
hir::Mutability::MutMutable => {
224+
self.add_reborrow_constraint(location, borrow_region, base);
225+
},
226+
}
227+
228+
self.regioncx.add_outlives(base_region.to_region_index(),
229+
borrow_region.to_region_index(),
230+
location.successor_within_block());
231+
}
232+
}
233+
}
234+
}
201235
}
202236

203237
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
@@ -214,6 +248,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
214248
if let StatementKind::Assign(ref destination_lv, ref rv) = statement.kind {
215249
if let Rvalue::Ref(region, bk, ref borrowed_lv) = *rv {
216250
self.add_borrow_constraint(location, destination_lv, region, bk, borrowed_lv);
251+
self.add_reborrow_constraint(location, region, borrowed_lv);
217252
}
218253
}
219254

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
// Basic test for reborrow constraints: the region (`R5`) that appears
12+
// in the type of `r_a` must outlive the region (`R7`) that appears in
13+
// the type of `r_b`
14+
15+
// compile-flags:-Znll -Zverbose
16+
// ^^^^^^^^^ force compiler to dump more region information
17+
18+
#![allow(warnings)]
19+
20+
fn use_x(_: &mut i32) -> bool { true }
21+
22+
fn main() {
23+
let mut foo: i32 = 22;
24+
let r_a: &mut i32 = &mut foo;
25+
let r_b: &mut i32 = &mut *r_a;
26+
use_x(r_b);
27+
}
28+
29+
// END RUST SOURCE
30+
// START rustc.node13.nll.0.mir
31+
// | R5: {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
32+
// ...
33+
// | R7: {bb0[11], bb0[12], bb0[13], bb0[14]}
34+
// END rustc.node13.nll.0.mir
35+
// START rustc.node13.nll.0.mir
36+
// let _2: &'_#5r mut i32;
37+
// ...
38+
// let _4: &'_#7r mut i32;
39+
// END rustc.node13.nll.0.mir

0 commit comments

Comments
 (0)