Skip to content

Commit 69833ab

Browse files
committed
integrate NLL with MIR type-checker
1 parent 71ef306 commit 69833ab

File tree

10 files changed

+255
-155
lines changed

10 files changed

+255
-155
lines changed

src/librustc/middle/free_region.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl<'tcx> FreeRegionMap<'tcx> {
192192
///
193193
/// if `r_a` represents `'a`, this function would return `{'b, 'c}`.
194194
pub fn regions_that_outlive<'a, 'gcx>(&self, r_a: Region<'tcx>) -> Vec<&Region<'tcx>> {
195-
assert!(is_free(r_a));
195+
assert!(is_free(r_a) || *r_a == ty::ReStatic);
196196
self.relation.greater_than(&r_a)
197197
}
198198
}

src/librustc_mir/borrow_check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
115115
let opt_regioncx = if !tcx.sess.opts.debugging_opts.nll {
116116
None
117117
} else {
118-
Some(nll::compute_regions(infcx, src, mir))
118+
Some(nll::compute_regions(infcx, src, param_env, mir))
119119
};
120120

121121
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };

src/librustc_mir/transform/nll/constraint_generation.rs

Lines changed: 13 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use rustc::hir;
12-
use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind};
12+
use rustc::mir::{Location, Lvalue, Mir, Rvalue};
1313
use rustc::mir::transform::MirSource;
1414
use rustc::mir::visit::Visitor;
1515
use rustc::mir::Lvalue::Projection;
@@ -22,7 +22,6 @@ use rustc::util::common::ErrorReported;
2222
use rustc_data_structures::fx::FxHashSet;
2323
use syntax::codemap::DUMMY_SP;
2424

25-
use super::subtype;
2625
use super::LivenessResults;
2726
use super::ToRegionVid;
2827
use super::region_infer::RegionInferenceContext;
@@ -182,29 +181,6 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
182181
self.visit_mir(self.mir);
183182
}
184183

185-
fn add_borrow_constraint(
186-
&mut self,
187-
location: Location,
188-
destination_lv: &Lvalue<'tcx>,
189-
borrow_region: ty::Region<'tcx>,
190-
_borrow_kind: BorrowKind,
191-
_borrowed_lv: &Lvalue<'tcx>,
192-
) {
193-
let tcx = self.infcx.tcx;
194-
let span = self.mir.source_info(location).span;
195-
let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
196-
197-
let destination_region = match destination_ty.sty {
198-
ty::TyRef(r, _) => r,
199-
_ => bug!()
200-
};
201-
202-
self.regioncx.add_outlives(span,
203-
borrow_region.to_region_vid(),
204-
destination_region.to_region_vid(),
205-
location.successor_within_block());
206-
}
207-
208184
fn add_reborrow_constraint(
209185
&mut self,
210186
location: Location,
@@ -240,35 +216,22 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
240216
}
241217

242218
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
243-
fn visit_statement(&mut self,
244-
block: BasicBlock,
245-
statement: &Statement<'tcx>,
246-
location: Location) {
219+
fn visit_rvalue(&mut self,
220+
rvalue: &Rvalue<'tcx>,
221+
location: Location) {
222+
debug!("visit_rvalue(rvalue={:?}, location={:?})", rvalue, location);
247223

248-
debug!("visit_statement(statement={:?}, location={:?})", statement, location);
249-
250-
// Look for a statement like:
224+
// Look for an rvalue like:
251225
//
252-
// D = & L
226+
// & L
253227
//
254-
// where D is the path to which we are assigning, and
255-
// L is the path that is borrowed.
256-
if let StatementKind::Assign(ref destination_lv, ref rv) = statement.kind {
257-
if let Rvalue::Ref(region, bk, ref borrowed_lv) = *rv {
258-
self.add_borrow_constraint(location, destination_lv, region, bk, borrowed_lv);
259-
self.add_reborrow_constraint(location, region, borrowed_lv);
260-
}
261-
262-
let tcx = self.infcx.tcx;
263-
let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
264-
let rv_ty = rv.ty(self.mir, tcx);
265-
266-
let span = self.mir.source_info(location).span;
267-
for (a, b) in subtype::outlives_pairs(tcx, rv_ty, destination_ty) {
268-
self.regioncx.add_outlives(span, a, b, location.successor_within_block());
269-
}
228+
// where L is the path that is borrowed. In that case, we have
229+
// to add the reborrow constraints (which don't fall out
230+
// naturally from the type-checker).
231+
if let Rvalue::Ref(region, _bk, ref borrowed_lv) = *rvalue {
232+
self.add_reborrow_constraint(location, region, borrowed_lv);
270233
}
271234

272-
self.super_statement(block, statement, location);
235+
self.super_rvalue(rvalue, location);
273236
}
274237
}

src/librustc_mir/transform/nll/free_regions.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ pub fn free_regions<'a, 'gcx, 'tcx>(
5353

5454
let mut indices = FxHashMap();
5555

56+
// `'static` is always free.
57+
insert_free_region(&mut indices, infcx.tcx.types.re_static);
58+
5659
// Extract the early regions.
5760
let item_substs = Substs::identity_for_item(infcx.tcx, item_def_id);
5861
for item_subst in item_substs {

src/librustc_mir/transform/nll/mod.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ use rustc::mir::transform::MirSource;
1414
use rustc::infer::InferCtxt;
1515
use rustc::util::nodemap::FxHashMap;
1616
use std::collections::BTreeSet;
17+
use transform::type_check;
1718
use util::liveness::{self, LivenessMode, LivenessResult, LocalSet};
1819

1920
use util as mir_util;
2021
use self::mir_util::PassWhere;
2122

2223
mod constraint_generation;
24+
mod subtype_constraint_generation;
2325
mod free_regions;
24-
mod subtype;
2526

2627
pub(crate) mod region_infer;
2728
use self::region_infer::RegionInferenceContext;
@@ -34,6 +35,7 @@ mod renumber;
3435
pub fn compute_regions<'a, 'gcx, 'tcx>(
3536
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
3637
source: MirSource,
38+
param_env: ty::ParamEnv<'gcx>,
3739
mir: &mut Mir<'tcx>,
3840
) -> RegionInferenceContext<'tcx> {
3941
// Compute named region information.
@@ -42,6 +44,16 @@ pub fn compute_regions<'a, 'gcx, 'tcx>(
4244
// Replace all regions with fresh inference variables.
4345
renumber::renumber_mir(infcx, free_regions, mir);
4446

47+
// Run the MIR type-checker.
48+
let body_id = source.item_id();
49+
let constraint_sets = &type_check::type_check(infcx, body_id, param_env, mir);
50+
51+
// Create the region inference context, taking ownership of the region inference
52+
// data that was contained in `infcx`.
53+
let var_origins = infcx.take_region_var_origins();
54+
let mut regioncx = RegionInferenceContext::new(var_origins, free_regions, mir);
55+
subtype_constraint_generation::generate(&mut regioncx, free_regions, mir, constraint_sets);
56+
4557
// Compute what is live where.
4658
let liveness = &LivenessResults {
4759
regular: liveness::liveness_of_locals(
@@ -61,11 +73,10 @@ pub fn compute_regions<'a, 'gcx, 'tcx>(
6173
),
6274
};
6375

64-
// Create the region inference context, generate the constraints,
65-
// and then solve them.
66-
let var_origins = infcx.take_region_var_origins();
67-
let mut regioncx = RegionInferenceContext::new(var_origins, free_regions, mir);
76+
// Generate non-subtyping constraints.
6877
constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, source, liveness);
78+
79+
// Solve the region constraints.
6980
regioncx.solve(infcx, &mir);
7081

7182
// Dump MIR results into a file, if that is enabled. This let us

src/librustc_mir/transform/nll/region_infer.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,15 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
183183
// Add `end(X)` into the set for X.
184184
self.definitions[variable].value.add_free_region(variable);
185185

186+
// `'static` outlives all other free regions as well.
187+
if let ty::ReStatic = free_region {
188+
for &other_variable in indices.values() {
189+
self.definitions[variable]
190+
.value
191+
.add_free_region(other_variable);
192+
}
193+
}
194+
186195
// Go through each region Y that outlives X (i.e., where
187196
// Y: X is true). Add `end(X)` into the set for `Y`.
188197
for superregion in free_region_map.regions_that_outlive(&free_region) {

src/librustc_mir/transform/nll/subtype.rs

Lines changed: 0 additions & 98 deletions
This file was deleted.

0 commit comments

Comments
 (0)