add reborrow constraints
This commit is contained in:
parent
f700728a3b
commit
b8615f3bea
@ -8,9 +8,12 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind};
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::Visitor;
|
||||
use rustc::mir::Lvalue::Projection;
|
||||
use rustc::mir::{LvalueProjection, ProjectionElem};
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::traits::{self, ObligationCause};
|
||||
use rustc::ty::{self, Ty};
|
||||
@ -198,6 +201,37 @@ fn add_borrow_constraint(
|
||||
destination_region.to_region_index(),
|
||||
location.successor_within_block());
|
||||
}
|
||||
|
||||
fn add_reborrow_constraint(
|
||||
&mut self,
|
||||
location: Location,
|
||||
borrow_region: ty::Region<'tcx>,
|
||||
borrowed_lv: &Lvalue<'tcx>,
|
||||
) {
|
||||
if let Projection(ref proj) = *borrowed_lv {
|
||||
let LvalueProjection { ref base, ref elem } = **proj;
|
||||
|
||||
if let ProjectionElem::Deref = *elem {
|
||||
let tcx = self.infcx.tcx;
|
||||
let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
|
||||
let base_sty = &base_ty.sty;
|
||||
|
||||
if let ty::TyRef(base_region, ty::TypeAndMut{ ty: _, mutbl }) = *base_sty {
|
||||
match mutbl {
|
||||
hir::Mutability::MutImmutable => { },
|
||||
|
||||
hir::Mutability::MutMutable => {
|
||||
self.add_reborrow_constraint(location, borrow_region, base);
|
||||
},
|
||||
}
|
||||
|
||||
self.regioncx.add_outlives(base_region.to_region_index(),
|
||||
borrow_region.to_region_index(),
|
||||
location.successor_within_block());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
|
||||
@ -214,6 +248,7 @@ fn visit_statement(&mut self,
|
||||
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.add_reborrow_constraint(location, region, borrowed_lv);
|
||||
}
|
||||
}
|
||||
|
||||
|
39
src/test/mir-opt/nll/reborrow-basic.rs
Normal file
39
src/test/mir-opt/nll/reborrow-basic.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// 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.
|
||||
|
||||
// Basic test for reborrow constraints: the region (`R5`) that appears
|
||||
// in the type of `r_a` must outlive the region (`R7`) that appears in
|
||||
// the type of `r_b`
|
||||
|
||||
// compile-flags:-Znll -Zverbose
|
||||
// ^^^^^^^^^ force compiler to dump more region information
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
fn use_x(_: &mut i32) -> bool { true }
|
||||
|
||||
fn main() {
|
||||
let mut foo: i32 = 22;
|
||||
let r_a: &mut i32 = &mut foo;
|
||||
let r_b: &mut i32 = &mut *r_a;
|
||||
use_x(r_b);
|
||||
}
|
||||
|
||||
// END RUST SOURCE
|
||||
// START rustc.node13.nll.0.mir
|
||||
// | R5: {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
|
||||
// ...
|
||||
// | R7: {bb0[11], bb0[12], bb0[13], bb0[14]}
|
||||
// END rustc.node13.nll.0.mir
|
||||
// START rustc.node13.nll.0.mir
|
||||
// let _2: &'_#5r mut i32;
|
||||
// ...
|
||||
// let _4: &'_#7r mut i32;
|
||||
// END rustc.node13.nll.0.mir
|
Loading…
Reference in New Issue
Block a user