Skip to content

Commit 874dec2

Browse files
committedJul 21, 2018
Auto merge of #52115 - Dylan-DPC:feature/nll-liveness-regions, r=nikomatsakis
only compute liveness for variables whose types include regions Closes #52034 r? @nikomatsakis
2 parents d941658 + 0770ff0 commit 874dec2

11 files changed

+302
-357
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2018 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+
//! For the NLL computation, we need to compute liveness, but only for those
12+
//! local variables whose types contain regions. The others are not of interest
13+
//! to us. This file defines a new index type (LocalWithRegion) that indexes into
14+
//! a list of "variables whose type contain regions". It also defines a map from
15+
//! Local to LocalWithRegion and vice versa -- this map can be given to the
16+
//! liveness code so that it only operates over variables with regions in their
17+
//! types, instead of all variables.
18+
19+
use rustc::ty::TypeFoldable;
20+
use rustc_data_structures::indexed_vec::IndexVec;
21+
use rustc::mir::{Mir, Local};
22+
use util::liveness::LiveVariableMap;
23+
24+
use rustc_data_structures::indexed_vec::Idx;
25+
26+
/// Map between Local and LocalWithRegion indices: this map is supplied to the
27+
/// liveness code so that it will only analyze those variables whose types
28+
/// contain regions.
29+
crate struct NllLivenessMap {
30+
/// For each local variable, contains either None (if the type has no regions)
31+
/// or Some(i) with a suitable index.
32+
pub from_local: IndexVec<Local, Option<LocalWithRegion>>,
33+
/// For each LocalWithRegion, maps back to the original Local index.
34+
pub to_local: IndexVec<LocalWithRegion, Local>,
35+
36+
}
37+
38+
impl LiveVariableMap for NllLivenessMap {
39+
40+
fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
41+
self.from_local[local]
42+
}
43+
44+
type LiveVar = LocalWithRegion;
45+
46+
fn from_live_var(&self, local: Self::LiveVar) -> Local {
47+
self.to_local[local]
48+
}
49+
50+
fn num_variables(&self) -> usize {
51+
self.to_local.len()
52+
}
53+
}
54+
55+
impl NllLivenessMap {
56+
/// Iterates over the variables in Mir and assigns each Local whose type contains
57+
/// regions a LocalWithRegion index. Returns a map for converting back and forth.
58+
pub fn compute(mir: &Mir) -> Self {
59+
let mut to_local = IndexVec::default();
60+
let from_local: IndexVec<Local,Option<_>> = mir
61+
.local_decls
62+
.iter_enumerated()
63+
.map(|(local, local_decl)| {
64+
if local_decl.ty.has_free_regions() {
65+
Some(to_local.push(local))
66+
}
67+
else {
68+
None
69+
}
70+
}).collect();
71+
72+
Self { from_local, to_local }
73+
}
74+
}
75+
76+
/// Index given to each local variable whose type contains a region.
77+
newtype_index!(LocalWithRegion);

‎src/librustc_mir/borrow_check/nll/mod.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use borrow_check::location::{LocationIndex, LocationTable};
1313
use borrow_check::nll::facts::AllFactsExt;
1414
use borrow_check::nll::type_check::MirTypeckRegionConstraints;
1515
use borrow_check::nll::region_infer::values::RegionValueElements;
16+
use borrow_check::nll::liveness_map::{NllLivenessMap, LocalWithRegion};
1617
use dataflow::indexes::BorrowIndex;
1718
use dataflow::move_paths::MoveData;
1819
use dataflow::FlowAtLocation;
@@ -30,7 +31,7 @@ use std::path::PathBuf;
3031
use std::rc::Rc;
3132
use std::str::FromStr;
3233
use transform::MirSource;
33-
use util::liveness::{LivenessResults, LocalSet};
34+
use util::liveness::{LivenessResults, LiveVarSet};
3435

3536
use self::mir_util::PassWhere;
3637
use polonius_engine::{Algorithm, Output};
@@ -45,6 +46,7 @@ crate mod region_infer;
4546
mod renumber;
4647
crate mod type_check;
4748
mod universal_regions;
49+
crate mod liveness_map;
4850

4951
mod constraints;
5052

@@ -103,7 +105,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
103105
let elements = &Rc::new(RegionValueElements::new(mir, universal_regions.len()));
104106

105107
// Run the MIR type-checker.
106-
let liveness = &LivenessResults::compute(mir);
108+
let liveness_map = NllLivenessMap::compute(&mir);
109+
let liveness = LivenessResults::compute(mir, &liveness_map);
107110
let constraint_sets = type_check::type_check(
108111
infcx,
109112
param_env,
@@ -193,7 +196,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
193196
// write unit-tests, as well as helping with debugging.
194197
dump_mir_results(
195198
infcx,
196-
liveness,
199+
&liveness,
197200
MirSource::item(def_id),
198201
&mir,
199202
&regioncx,
@@ -209,7 +212,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
209212

210213
fn dump_mir_results<'a, 'gcx, 'tcx>(
211214
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
212-
liveness: &LivenessResults,
215+
liveness: &LivenessResults<LocalWithRegion>,
213216
source: MirSource,
214217
mir: &Mir<'tcx>,
215218
regioncx: &RegionInferenceContext,
@@ -219,14 +222,16 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
219222
return;
220223
}
221224

225+
let map = &NllLivenessMap::compute(mir);
226+
222227
let regular_liveness_per_location: FxHashMap<_, _> = mir
223228
.basic_blocks()
224229
.indices()
225230
.flat_map(|bb| {
226231
let mut results = vec![];
227232
liveness
228233
.regular
229-
.simulate_block(&mir, bb, |location, local_set| {
234+
.simulate_block(&mir, bb, map, |location, local_set| {
230235
results.push((location, local_set.clone()));
231236
});
232237
results
@@ -240,7 +245,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
240245
let mut results = vec![];
241246
liveness
242247
.drop
243-
.simulate_block(&mir, bb, |location, local_set| {
248+
.simulate_block(&mir, bb, map, |location, local_set| {
244249
results.push((location, local_set.clone()));
245250
});
246251
results
@@ -405,7 +410,10 @@ impl ToRegionVid for RegionVid {
405410
}
406411
}
407412

408-
fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String {
413+
fn live_variable_set(
414+
regular: &LiveVarSet<LocalWithRegion>,
415+
drops: &LiveVarSet<LocalWithRegion>
416+
) -> String {
409417
// sort and deduplicate:
410418
let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect();
411419

‎src/librustc_mir/borrow_check/nll/type_check/liveness.rs

+16-11
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use borrow_check::nll::{NllLivenessMap, LocalWithRegion};
1112
use borrow_check::nll::type_check::AtLocation;
1213
use dataflow::move_paths::{HasMoveData, MoveData};
1314
use dataflow::MaybeInitializedPlaces;
1415
use dataflow::{FlowAtLocation, FlowsAtLocation};
1516
use rustc::infer::canonical::QueryRegionConstraint;
16-
use rustc::mir::Local;
1717
use rustc::mir::{BasicBlock, Location, Mir};
1818
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
1919
use rustc::traits::query::type_op::outlives::DropckOutlives;
2020
use rustc::traits::query::type_op::TypeOp;
2121
use rustc::ty::{Ty, TypeFoldable};
2222
use rustc_data_structures::fx::FxHashMap;
2323
use std::rc::Rc;
24-
use util::liveness::LivenessResults;
24+
use util::liveness::{LivenessResults, LiveVariableMap };
2525

2626
use super::TypeChecker;
2727

@@ -36,7 +36,7 @@ use super::TypeChecker;
3636
pub(super) fn generate<'gcx, 'tcx>(
3737
cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
3838
mir: &Mir<'tcx>,
39-
liveness: &LivenessResults,
39+
liveness: &LivenessResults<LocalWithRegion>,
4040
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
4141
move_data: &MoveData<'tcx>,
4242
) {
@@ -47,6 +47,7 @@ pub(super) fn generate<'gcx, 'tcx>(
4747
flow_inits,
4848
move_data,
4949
drop_data: FxHashMap(),
50+
map: &NllLivenessMap::compute(mir),
5051
};
5152

5253
for bb in mir.basic_blocks().indices() {
@@ -63,10 +64,11 @@ where
6364
{
6465
cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>,
6566
mir: &'gen Mir<'tcx>,
66-
liveness: &'gen LivenessResults,
67+
liveness: &'gen LivenessResults<LocalWithRegion>,
6768
flow_inits: &'gen mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>,
6869
move_data: &'gen MoveData<'tcx>,
6970
drop_data: FxHashMap<Ty<'tcx>, DropData<'tcx>>,
71+
map: &'gen NllLivenessMap,
7072
}
7173

7274
struct DropData<'tcx> {
@@ -84,17 +86,18 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
8486

8587
self.liveness
8688
.regular
87-
.simulate_block(self.mir, bb, |location, live_locals| {
89+
.simulate_block(self.mir, bb, self.map, |location, live_locals| {
8890
for live_local in live_locals.iter() {
89-
let live_local_ty = self.mir.local_decls[live_local].ty;
91+
let local = self.map.from_live_var(live_local);
92+
let live_local_ty = self.mir.local_decls[local].ty;
9093
Self::push_type_live_constraint(&mut self.cx, live_local_ty, location);
9194
}
9295
});
9396

94-
let mut all_live_locals: Vec<(Location, Vec<Local>)> = vec![];
97+
let mut all_live_locals: Vec<(Location, Vec<LocalWithRegion>)> = vec![];
9598
self.liveness
9699
.drop
97-
.simulate_block(self.mir, bb, |location, live_locals| {
100+
.simulate_block(self.mir, bb, self.map, |location, live_locals| {
98101
all_live_locals.push((location, live_locals.iter().collect()));
99102
});
100103
debug!(
@@ -121,15 +124,17 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
121124
});
122125
}
123126

124-
let mpi = self.move_data.rev_lookup.find_local(live_local);
127+
let local = self.map.from_live_var(live_local);
128+
let mpi = self.move_data.rev_lookup.find_local(local);
125129
if let Some(initialized_child) = self.flow_inits.has_any_child_of(mpi) {
126130
debug!(
127131
"add_liveness_constraints: mpi={:?} has initialized child {:?}",
128132
self.move_data.move_paths[mpi],
129133
self.move_data.move_paths[initialized_child]
130134
);
131135

132-
let live_local_ty = self.mir.local_decls[live_local].ty;
136+
let local = self.map.from_live_var(live_local);
137+
let live_local_ty = self.mir.local_decls[local].ty;
133138
self.add_drop_live_constraint(live_local, live_local_ty, location);
134139
}
135140
}
@@ -190,7 +195,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
190195
/// particular this takes `#[may_dangle]` into account.
191196
fn add_drop_live_constraint(
192197
&mut self,
193-
dropped_local: Local,
198+
dropped_local: LocalWithRegion,
194199
dropped_ty: Ty<'tcx>,
195200
location: Location,
196201
) {

‎src/librustc_mir/borrow_check/nll/type_check/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
1919
use borrow_check::nll::region_infer::values::{RegionValues, RegionValueElements};
2020
use borrow_check::nll::universal_regions::UniversalRegions;
2121
use borrow_check::nll::ToRegionVid;
22+
use borrow_check::nll::LocalWithRegion;
2223
use dataflow::move_paths::MoveData;
2324
use dataflow::FlowAtLocation;
2425
use dataflow::MaybeInitializedPlaces;
@@ -109,7 +110,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
109110
universal_regions: &UniversalRegions<'tcx>,
110111
location_table: &LocationTable,
111112
borrow_set: &BorrowSet<'tcx>,
112-
liveness: &LivenessResults,
113+
liveness: &LivenessResults<LocalWithRegion>,
113114
all_facts: &mut Option<AllFacts>,
114115
flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
115116
move_data: &MoveData<'tcx>,

‎src/librustc_mir/transform/generator.rs

+26-15
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
6666
use rustc::ty::{self, TyCtxt, AdtDef, Ty};
6767
use rustc::ty::subst::Substs;
6868
use util::dump_mir;
69-
use util::liveness::{self, LivenessMode};
69+
use util::liveness::{self, IdentityMap, LivenessMode};
7070
use rustc_data_structures::indexed_vec::Idx;
7171
use rustc_data_structures::indexed_set::IdxSetBuf;
7272
use std::collections::HashMap;
@@ -130,7 +130,7 @@ struct SuspensionPoint {
130130
state: u32,
131131
resume: BasicBlock,
132132
drop: Option<BasicBlock>,
133-
storage_liveness: liveness::LocalSet,
133+
storage_liveness: liveness::LiveVarSet<Local>,
134134
}
135135

136136
struct TransformVisitor<'a, 'tcx: 'a> {
@@ -145,7 +145,7 @@ struct TransformVisitor<'a, 'tcx: 'a> {
145145
remap: HashMap<Local, (Ty<'tcx>, usize)>,
146146

147147
// A map from a suspension point in a block to the locals which have live storage at that point
148-
storage_liveness: HashMap<BasicBlock, liveness::LocalSet>,
148+
storage_liveness: HashMap<BasicBlock, liveness::LiveVarSet<Local>>,
149149

150150
// A list of suspension points, generated during the transform
151151
suspension_points: Vec<SuspensionPoint>,
@@ -317,7 +317,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
317317
new_ret_local
318318
}
319319

320-
struct StorageIgnored(liveness::LocalSet);
320+
struct StorageIgnored(liveness::LiveVarSet<Local>);
321321

322322
impl<'tcx> Visitor<'tcx> for StorageIgnored {
323323
fn visit_statement(&mut self,
@@ -332,7 +332,7 @@ impl<'tcx> Visitor<'tcx> for StorageIgnored {
332332
}
333333
}
334334

335-
struct BorrowedLocals(liveness::LocalSet);
335+
struct BorrowedLocals(liveness::LiveVarSet<Local>);
336336

337337
fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) {
338338
match *place {
@@ -361,12 +361,12 @@ impl<'tcx> Visitor<'tcx> for BorrowedLocals {
361361
}
362362
}
363363

364-
fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
364+
fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
365365
mir: &Mir<'tcx>,
366366
source: MirSource,
367367
movable: bool) ->
368-
(liveness::LocalSet,
369-
HashMap<BasicBlock, liveness::LocalSet>) {
368+
(liveness::LiveVarSet<Local>,
369+
HashMap<BasicBlock, liveness::LiveVarSet<Local>>) {
370370
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
371371
let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
372372

@@ -396,12 +396,23 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
396396
};
397397

398398
// Calculate the liveness of MIR locals ignoring borrows.
399-
let mut set = liveness::LocalSet::new_empty(mir.local_decls.len());
400-
let mut liveness = liveness::liveness_of_locals(mir, LivenessMode {
401-
include_regular_use: true,
402-
include_drops: true,
403-
});
404-
liveness::dump_mir(tcx, "generator_liveness", source, mir, &liveness);
399+
let mut set = liveness::LiveVarSet::new_empty(mir.local_decls.len());
400+
let mut liveness = liveness::liveness_of_locals(
401+
mir,
402+
LivenessMode {
403+
include_regular_use: true,
404+
include_drops: true,
405+
},
406+
&IdentityMap::new(mir),
407+
);
408+
liveness::dump_mir(
409+
tcx,
410+
"generator_liveness",
411+
source,
412+
mir,
413+
&IdentityMap::new(mir),
414+
&liveness,
415+
);
405416

406417
let mut storage_liveness_map = HashMap::new();
407418

@@ -468,7 +479,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
468479
mir: &mut Mir<'tcx>)
469480
-> (HashMap<Local, (Ty<'tcx>, usize)>,
470481
GeneratorLayout<'tcx>,
471-
HashMap<BasicBlock, liveness::LocalSet>)
482+
HashMap<BasicBlock, liveness::LiveVarSet<Local>>)
472483
{
473484
// Use a liveness analysis to compute locals which are live across a suspension point
474485
let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx,

‎src/librustc_mir/util/liveness.rs

+166-79
Large diffs are not rendered by default.

‎src/test/mir-opt/nll/liveness-call-subtlety.rs

-45
This file was deleted.

‎src/test/mir-opt/nll/liveness-drop-intra-block.rs

-41
This file was deleted.

‎src/test/mir-opt/nll/liveness-interblock.rs

-48
This file was deleted.

‎src/test/mir-opt/nll/region-liveness-basic.rs

-58
This file was deleted.

‎src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs

-52
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.