From b8615f3bea67f12db7a84687923d62d5aabc22c1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 25 Oct 2017 15:10:48 -0400 Subject: [PATCH] add reborrow constraints --- .../transform/nll/constraint_generation.rs | 35 +++++++++++++++++ src/test/mir-opt/nll/reborrow-basic.rs | 39 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/test/mir-opt/nll/reborrow-basic.rs diff --git a/src/librustc_mir/transform/nll/constraint_generation.rs b/src/librustc_mir/transform/nll/constraint_generation.rs index 1acbd72a47d..1fc7dbd5bd0 100644 --- a/src/librustc_mir/transform/nll/constraint_generation.rs +++ b/src/librustc_mir/transform/nll/constraint_generation.rs @@ -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 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> { 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 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> { 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); } } diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs new file mode 100644 index 00000000000..1983478a4e1 --- /dev/null +++ b/src/test/mir-opt/nll/reborrow-basic.rs @@ -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 or the MIT license +// , 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