Skip to content

Commit 83ddc33

Browse files
committed
Auto merge of #53314 - nikomatsakis:nll-invert-liveness, r=pnkfelix
NLL: experiment with inverting liveness I got inspired to see what would happen here. Fixes #52460 r? @pnkfelix
2 parents 59e52b1 + 8d231ec commit 83ddc33

File tree

21 files changed

+1001
-608
lines changed

21 files changed

+1001
-608
lines changed

src/librustc/mir/mod.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,12 @@ impl<'tcx> Mir<'tcx> {
194194
}
195195

196196
#[inline]
197-
pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
197+
pub fn predecessors(&self) -> ReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
198198
self.cache.predecessors(self)
199199
}
200200

201201
#[inline]
202-
pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
202+
pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<'_, Vec<BasicBlock>> {
203203
ReadGuard::map(self.predecessors(), |p| &p[bb])
204204
}
205205

@@ -328,6 +328,14 @@ impl<'tcx> Mir<'tcx> {
328328
pub fn return_ty(&self) -> Ty<'tcx> {
329329
self.local_decls[RETURN_PLACE].ty
330330
}
331+
332+
/// Get the location of the terminator for the given block
333+
pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
334+
Location {
335+
block: bb,
336+
statement_index: self[bb].statements.len(),
337+
}
338+
}
331339
}
332340

333341
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]

src/librustc_data_structures/graph/dominators/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(
3838

3939
// compute the post order index (rank) for each node
4040
let mut post_order_rank: IndexVec<G::Node, usize> =
41-
IndexVec::from_elem_n(usize::default(), graph.num_nodes());
41+
(0..graph.num_nodes()).map(|_| 0).collect();
4242
for (index, node) in rpo.iter().rev().cloned().enumerate() {
4343
post_order_rank[node] = index;
4444
}
4545

4646
let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
47-
IndexVec::from_elem_n(Option::default(), graph.num_nodes());
47+
(0..graph.num_nodes()).map(|_| None).collect();
4848
immediate_dominators[start_node] = Some(start_node);
4949

5050
let mut changed = true;

src/librustc_data_structures/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
2121
html_root_url = "https://doc.rust-lang.org/nightly/")]
2222

23+
#![feature(in_band_lifetimes)]
24+
#![feature(impl_header_lifetime_elision)]
2325
#![feature(unboxed_closures)]
2426
#![feature(fn_traits)]
2527
#![feature(unsize)]
@@ -86,6 +88,7 @@ pub mod thin_vec;
8688
pub mod transitive_relation;
8789
pub mod tuple_slice;
8890
pub use ena::unify;
91+
pub mod vec_linked_list;
8992
pub mod work_queue;
9093
pub mod fingerprint;
9194

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2014 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+
use indexed_vec::{Idx, IndexVec};
12+
13+
pub fn iter<Ls>(
14+
first: Option<Ls::LinkIndex>,
15+
links: &'a Ls,
16+
) -> impl Iterator<Item = Ls::LinkIndex> + 'a
17+
where
18+
Ls: Links,
19+
{
20+
VecLinkedListIterator {
21+
links: links,
22+
current: first,
23+
}
24+
}
25+
26+
pub struct VecLinkedListIterator<Ls>
27+
where
28+
Ls: Links,
29+
{
30+
links: Ls,
31+
current: Option<Ls::LinkIndex>,
32+
}
33+
34+
impl<Ls> Iterator for VecLinkedListIterator<Ls>
35+
where
36+
Ls: Links,
37+
{
38+
type Item = Ls::LinkIndex;
39+
40+
fn next(&mut self) -> Option<Ls::LinkIndex> {
41+
if let Some(c) = self.current {
42+
self.current = <Ls as Links>::next(&self.links, c);
43+
Some(c)
44+
} else {
45+
None
46+
}
47+
}
48+
}
49+
50+
pub trait Links {
51+
type LinkIndex: Copy;
52+
53+
fn next(links: &Self, index: Self::LinkIndex) -> Option<Self::LinkIndex>;
54+
}
55+
56+
impl<Ls> Links for &Ls
57+
where
58+
Ls: Links,
59+
{
60+
type LinkIndex = Ls::LinkIndex;
61+
62+
fn next(links: &Self, index: Ls::LinkIndex) -> Option<Ls::LinkIndex> {
63+
<Ls as Links>::next(links, index)
64+
}
65+
}
66+
67+
pub trait LinkElem {
68+
type LinkIndex: Copy;
69+
70+
fn next(elem: &Self) -> Option<Self::LinkIndex>;
71+
}
72+
73+
impl<L, E> Links for IndexVec<L, E>
74+
where
75+
E: LinkElem<LinkIndex = L>,
76+
L: Idx,
77+
{
78+
type LinkIndex = L;
79+
80+
fn next(links: &Self, index: L) -> Option<L> {
81+
<E as LinkElem>::next(&links[index])
82+
}
83+
}

src/librustc_mir/borrow_check/flows.rs

+4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ impl<'b, 'gcx, 'tcx> FlowsAtLocation for Flows<'b, 'gcx, 'tcx> {
8989
each_flow!(self, reset_to_entry_of(bb));
9090
}
9191

92+
fn reset_to_exit_of(&mut self, bb: BasicBlock) {
93+
each_flow!(self, reset_to_exit_of(bb));
94+
}
95+
9296
fn reconstruct_statement_effect(&mut self, location: Location) {
9397
each_flow!(self, reconstruct_statement_effect(location));
9498
}

src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs

+7-25
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
1717
use rustc::mir::{Local, Location, Mir};
1818
use rustc::ty::{RegionVid, TyCtxt};
1919
use rustc_data_structures::fx::FxHashSet;
20-
use util::liveness::{self, DefUse, LivenessMode};
20+
use util::liveness::{self, DefUse};
2121

2222
crate fn find<'tcx>(
2323
mir: &Mir<'tcx>,
@@ -32,10 +32,6 @@ crate fn find<'tcx>(
3232
tcx,
3333
region_vid,
3434
start_point,
35-
liveness_mode: LivenessMode {
36-
include_regular_use: true,
37-
include_drops: true,
38-
},
3935
};
4036

4137
uf.find()
@@ -47,7 +43,6 @@ struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
4743
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
4844
region_vid: RegionVid,
4945
start_point: Location,
50-
liveness_mode: LivenessMode,
5146
}
5247

5348
impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
@@ -108,7 +103,6 @@ impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
108103
mir: self.mir,
109104
tcx: self.tcx,
110105
region_vid: self.region_vid,
111-
liveness_mode: self.liveness_mode,
112106
def_use_result: None,
113107
};
114108

@@ -122,7 +116,6 @@ struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
122116
mir: &'cx Mir<'tcx>,
123117
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
124118
region_vid: RegionVid,
125-
liveness_mode: LivenessMode,
126119
def_use_result: Option<DefUseResult>,
127120
}
128121

@@ -146,23 +139,12 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
146139
});
147140

148141
if found_it {
149-
match liveness::categorize(context, self.liveness_mode) {
150-
Some(DefUse::Def) => {
151-
self.def_use_result = Some(DefUseResult::Def);
152-
}
153-
154-
Some(DefUse::Use) => {
155-
self.def_use_result = if context.is_drop() {
156-
Some(DefUseResult::UseDrop { local })
157-
} else {
158-
Some(DefUseResult::UseLive { local })
159-
};
160-
}
161-
162-
None => {
163-
self.def_use_result = None;
164-
}
165-
}
142+
self.def_use_result = match liveness::categorize(context) {
143+
Some(DefUse::Def) => Some(DefUseResult::Def),
144+
Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
145+
Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),
146+
None => None,
147+
};
166148
}
167149
}
168150
}

src/librustc_mir/borrow_check/nll/mod.rs

+4-87
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
1212
use borrow_check::location::{LocationIndex, LocationTable};
1313
use borrow_check::nll::facts::AllFactsExt;
1414
use borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
15-
use borrow_check::nll::type_check::liveness::liveness_map::{NllLivenessMap, LocalWithRegion};
15+
use borrow_check::nll::type_check::liveness::liveness_map::NllLivenessMap;
1616
use borrow_check::nll::region_infer::values::RegionValueElements;
1717
use dataflow::indexes::BorrowIndex;
1818
use dataflow::move_paths::MoveData;
@@ -22,22 +22,19 @@ use rustc::hir::def_id::DefId;
2222
use rustc::infer::InferCtxt;
2323
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
2424
use rustc::ty::{self, RegionKind, RegionVid};
25-
use rustc::util::nodemap::FxHashMap;
2625
use rustc_errors::Diagnostic;
27-
use std::collections::BTreeSet;
2826
use std::fmt::Debug;
2927
use std::env;
3028
use std::io;
3129
use std::path::PathBuf;
3230
use std::rc::Rc;
3331
use std::str::FromStr;
3432
use transform::MirSource;
35-
use util::liveness::{LivenessResults, LiveVarSet};
3633

3734
use self::mir_util::PassWhere;
3835
use polonius_engine::{Algorithm, Output};
3936
use util as mir_util;
40-
use util::pretty::{self, ALIGN};
37+
use util::pretty;
4138

4239
mod constraint_generation;
4340
pub mod explain_borrow;
@@ -111,8 +108,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
111108
let MirTypeckResults {
112109
constraints,
113110
universal_region_relations,
114-
liveness,
115-
liveness_map,
116111
} = type_check::type_check(
117112
infcx,
118113
param_env,
@@ -205,8 +200,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
205200
// write unit-tests, as well as helping with debugging.
206201
dump_mir_results(
207202
infcx,
208-
&liveness,
209-
&liveness_map,
210203
MirSource::item(def_id),
211204
&mir,
212205
&regioncx,
@@ -222,8 +215,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
222215

223216
fn dump_mir_results<'a, 'gcx, 'tcx>(
224217
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
225-
liveness: &LivenessResults<LocalWithRegion>,
226-
liveness_map: &NllLivenessMap,
227218
source: MirSource,
228219
mir: &Mir<'tcx>,
229220
regioncx: &RegionInferenceContext,
@@ -233,34 +224,6 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
233224
return;
234225
}
235226

236-
let regular_liveness_per_location: FxHashMap<_, _> = mir
237-
.basic_blocks()
238-
.indices()
239-
.flat_map(|bb| {
240-
let mut results = vec![];
241-
liveness
242-
.regular
243-
.simulate_block(&mir, bb, liveness_map, |location, local_set| {
244-
results.push((location, local_set.clone()));
245-
});
246-
results
247-
})
248-
.collect();
249-
250-
let drop_liveness_per_location: FxHashMap<_, _> = mir
251-
.basic_blocks()
252-
.indices()
253-
.flat_map(|bb| {
254-
let mut results = vec![];
255-
liveness
256-
.drop
257-
.simulate_block(&mir, bb, liveness_map, |location, local_set| {
258-
results.push((location, local_set.clone()));
259-
});
260-
results
261-
})
262-
.collect();
263-
264227
mir_util::dump_mir(
265228
infcx.tcx,
266229
None,
@@ -283,26 +246,10 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
283246
}
284247
}
285248

286-
PassWhere::BeforeLocation(location) => {
287-
let s = live_variable_set(
288-
&regular_liveness_per_location[&location],
289-
&drop_liveness_per_location[&location],
290-
);
291-
writeln!(
292-
out,
293-
"{:ALIGN$} | Live variables on entry to {:?}: {}",
294-
"",
295-
location,
296-
s,
297-
ALIGN = ALIGN
298-
)?;
249+
PassWhere::BeforeLocation(_) => {
299250
}
300251

301-
// After each basic block, dump out the values
302-
// that are live on exit from the basic block.
303-
PassWhere::AfterTerminator(bb) => {
304-
let s = live_variable_set(&liveness.regular.outs[bb], &liveness.drop.outs[bb]);
305-
writeln!(out, " | Live variables on exit from {:?}: {}", bb, s)?;
252+
PassWhere::AfterTerminator(_) => {
306253
}
307254

308255
PassWhere::BeforeBlock(_) | PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
@@ -420,33 +367,3 @@ impl ToRegionVid for RegionVid {
420367
self
421368
}
422369
}
423-
424-
fn live_variable_set(
425-
regular: &LiveVarSet<LocalWithRegion>,
426-
drops: &LiveVarSet<LocalWithRegion>
427-
) -> String {
428-
// sort and deduplicate:
429-
let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect();
430-
431-
// construct a string with each local, including `(drop)` if it is
432-
// only dropped, versus a regular use.
433-
let mut string = String::new();
434-
for local in all_locals {
435-
string.push_str(&format!("{:?}", local));
436-
437-
if !regular.contains(&local) {
438-
assert!(drops.contains(&local));
439-
string.push_str(" (drop)");
440-
}
441-
442-
string.push_str(", ");
443-
}
444-
445-
let len = if string.is_empty() {
446-
0
447-
} else {
448-
string.len() - 2
449-
};
450-
451-
format!("[{}]", &string[..len])
452-
}

0 commit comments

Comments
 (0)