Skip to content

Commit 4b743da

Browse files
committed
integrate NLL with MIR type-checker
1 parent d9e841e commit 4b743da

File tree

10 files changed

+256
-162
lines changed

10 files changed

+256
-162
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
@@ -112,7 +112,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
112112
let opt_regioncx = if !tcx.sess.opts.debugging_opts.nll {
113113
None
114114
} else {
115-
Some(nll::compute_regions(infcx, def_id, mir))
115+
Some(nll::compute_regions(infcx, def_id, param_env, mir))
116116
};
117117

118118
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::visit::Visitor;
1414
use rustc::mir::Lvalue::Projection;
1515
use rustc::mir::{LvalueProjection, ProjectionElem};
@@ -21,7 +21,6 @@ use rustc::util::common::ErrorReported;
2121
use rustc_data_structures::fx::FxHashSet;
2222
use syntax::codemap::DUMMY_SP;
2323

24-
use super::subtype;
2524
use super::LivenessResults;
2625
use super::ToRegionVid;
2726
use super::region_infer::RegionInferenceContext;
@@ -179,29 +178,6 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
179178
self.visit_mir(self.mir);
180179
}
181180

182-
fn add_borrow_constraint(
183-
&mut self,
184-
location: Location,
185-
destination_lv: &Lvalue<'tcx>,
186-
borrow_region: ty::Region<'tcx>,
187-
_borrow_kind: BorrowKind,
188-
_borrowed_lv: &Lvalue<'tcx>,
189-
) {
190-
let tcx = self.infcx.tcx;
191-
let span = self.mir.source_info(location).span;
192-
let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
193-
194-
let destination_region = match destination_ty.sty {
195-
ty::TyRef(r, _) => r,
196-
_ => bug!()
197-
};
198-
199-
self.regioncx.add_outlives(span,
200-
borrow_region.to_region_vid(),
201-
destination_region.to_region_vid(),
202-
location.successor_within_block());
203-
}
204-
205181
fn add_reborrow_constraint(
206182
&mut self,
207183
location: Location,
@@ -237,35 +213,22 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
237213
}
238214

239215
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
240-
fn visit_statement(&mut self,
241-
block: BasicBlock,
242-
statement: &Statement<'tcx>,
243-
location: Location) {
216+
fn visit_rvalue(&mut self,
217+
rvalue: &Rvalue<'tcx>,
218+
location: Location) {
219+
debug!("visit_rvalue(rvalue={:?}, location={:?})", rvalue, location);
244220

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

269-
self.super_statement(block, statement, location);
232+
self.super_rvalue(rvalue, location);
270233
}
271234
}

src/librustc_mir/transform/nll/free_regions.rs

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

5151
let mut indices = FxHashMap();
5252

53+
// `'static` is always free.
54+
insert_free_region(&mut indices, infcx.tcx.types.re_static);
55+
5356
// Extract the early regions.
5457
let item_substs = Substs::identity_for_item(infcx.tcx, item_def_id);
5558
for item_subst in item_substs {

src/librustc_mir/transform/nll/mod.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ use rustc::ty::{self, RegionKind, RegionVid};
1515
use rustc::util::nodemap::FxHashMap;
1616
use std::collections::BTreeSet;
1717
use transform::MirSource;
18+
use transform::type_check;
1819
use util::liveness::{self, LivenessMode, LivenessResult, LocalSet};
1920

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

2324
mod constraint_generation;
25+
mod subtype_constraint_generation;
2426
mod free_regions;
25-
mod subtype;
2627

2728
pub(crate) mod region_infer;
2829
use self::region_infer::RegionInferenceContext;
@@ -35,6 +36,7 @@ mod renumber;
3536
pub fn compute_regions<'a, 'gcx, 'tcx>(
3637
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
3738
def_id: DefId,
39+
param_env: ty::ParamEnv<'gcx>,
3840
mir: &mut Mir<'tcx>,
3941
) -> RegionInferenceContext<'tcx> {
4042
// Compute named region information.
@@ -43,6 +45,16 @@ pub fn compute_regions<'a, 'gcx, 'tcx>(
4345
// Replace all regions with fresh inference variables.
4446
renumber::renumber_mir(infcx, free_regions, mir);
4547

48+
// Run the MIR type-checker.
49+
let mir_node_id = infcx.tcx.hir.as_local_node_id(def_id).unwrap();
50+
let constraint_sets = &type_check::type_check(infcx, mir_node_id, param_env, mir);
51+
52+
// Create the region inference context, taking ownership of the region inference
53+
// data that was contained in `infcx`.
54+
let var_origins = infcx.take_region_var_origins();
55+
let mut regioncx = RegionInferenceContext::new(var_origins, free_regions, mir);
56+
subtype_constraint_generation::generate(&mut regioncx, free_regions, mir, constraint_sets);
57+
4658
// Compute what is live where.
4759
let liveness = &LivenessResults {
4860
regular: liveness::liveness_of_locals(
@@ -62,12 +74,10 @@ pub fn compute_regions<'a, 'gcx, 'tcx>(
6274
),
6375
};
6476

65-
// Create the region inference context, generate the constraints,
66-
// and then solve them.
67-
let var_origins = infcx.take_region_var_origins();
68-
let mut regioncx = RegionInferenceContext::new(var_origins, free_regions, mir);
69-
let param_env = infcx.tcx.param_env(def_id);
77+
// Generate non-subtyping constraints.
7078
constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, param_env, liveness);
79+
80+
// Solve the region constraints.
7181
regioncx.solve(infcx, &mir);
7282

7383
// Dump MIR results into a file, if that is enabled. This let us
@@ -123,12 +133,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
123133
match pass_where {
124134
// Before the CFG, dump out the values for each region variable.
125135
PassWhere::BeforeCFG => for region in regioncx.regions() {
126-
writeln!(
127-
out,
128-
"| {:?}: {:?}",
129-
region,
130-
regioncx.region_value(region)
131-
)?;
136+
writeln!(out, "| {:?}: {:?}", region, regioncx.region_value(region))?;
132137
},
133138

134139
// Before each basic block, dump out the values

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)