Skip to content

Commit fcb58ab

Browse files
committed
Make causal tracking lazy
1 parent d3a90e7 commit fcb58ab

13 files changed

+224
-318
lines changed

src/librustc/mir/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,10 @@ impl<'tcx> Terminator<'tcx> {
970970
self.kind.successors_mut()
971971
}
972972

973+
pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
974+
self.kind.unwind()
975+
}
976+
973977
pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
974978
self.kind.unwind_mut()
975979
}
@@ -1165,6 +1169,31 @@ impl<'tcx> TerminatorKind<'tcx> {
11651169
}
11661170
}
11671171

1172+
pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
1173+
match *self {
1174+
TerminatorKind::Goto { .. }
1175+
| TerminatorKind::Resume
1176+
| TerminatorKind::Abort
1177+
| TerminatorKind::Return
1178+
| TerminatorKind::Unreachable
1179+
| TerminatorKind::GeneratorDrop
1180+
| TerminatorKind::Yield { .. }
1181+
| TerminatorKind::SwitchInt { .. }
1182+
| TerminatorKind::FalseEdges { .. } => None,
1183+
TerminatorKind::Call {
1184+
cleanup: ref unwind,
1185+
..
1186+
}
1187+
| TerminatorKind::Assert {
1188+
cleanup: ref unwind,
1189+
..
1190+
}
1191+
| TerminatorKind::DropAndReplace { ref unwind, .. }
1192+
| TerminatorKind::Drop { ref unwind, .. }
1193+
| TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
1194+
}
1195+
}
1196+
11681197
pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
11691198
match *self {
11701199
TerminatorKind::Goto { .. }

src/librustc_mir/borrow_check/nll/constraint_generation.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use borrow_check::borrow_set::BorrowSet;
1212
use borrow_check::location::LocationTable;
1313
use borrow_check::nll::facts::AllFacts;
14-
use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
14+
use borrow_check::nll::region_infer::RegionInferenceContext;
1515
use borrow_check::nll::ToRegionVid;
1616
use rustc::hir;
1717
use rustc::infer::InferCtxt;
@@ -32,7 +32,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
3232
location_table: &LocationTable,
3333
mir: &Mir<'tcx>,
3434
borrow_set: &BorrowSet<'tcx>,
35-
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location, Cause)],
35+
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)],
3636
) {
3737
let mut cg = ConstraintGeneration {
3838
borrow_set,
@@ -68,14 +68,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
6868
/// We sometimes have `substs` within an rvalue, or within a
6969
/// call. Make them live at the location where they appear.
7070
fn visit_substs(&mut self, substs: &&'tcx Substs<'tcx>, location: Location) {
71-
self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
71+
self.add_regular_live_constraint(*substs, location);
7272
self.super_substs(substs);
7373
}
7474

7575
/// We sometimes have `region` within an rvalue, or within a
7676
/// call. Make them live at the location where they appear.
7777
fn visit_region(&mut self, region: &ty::Region<'tcx>, location: Location) {
78-
self.add_regular_live_constraint(*region, location, Cause::LiveOther(location));
78+
self.add_regular_live_constraint(*region, location);
7979
self.super_region(region);
8080
}
8181

@@ -93,7 +93,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
9393
);
9494
}
9595
TyContext::Location(location) => {
96-
self.add_regular_live_constraint(*ty, location, Cause::LiveOther(location));
96+
self.add_regular_live_constraint(*ty, location);
9797
}
9898
}
9999

@@ -103,14 +103,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
103103
/// We sometimes have `generator_substs` within an rvalue, or within a
104104
/// call. Make them live at the location where they appear.
105105
fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) {
106-
self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
106+
self.add_regular_live_constraint(*substs, location);
107107
self.super_generator_substs(substs);
108108
}
109109

110110
/// We sometimes have `closure_substs` within an rvalue, or within a
111111
/// call. Make them live at the location where they appear.
112112
fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) {
113-
self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
113+
self.add_regular_live_constraint(*substs, location);
114114
self.super_closure_substs(substs);
115115
}
116116

@@ -232,7 +232,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
232232
/// that we also have to respect.
233233
fn add_region_liveness_constraints_from_type_check(
234234
&mut self,
235-
liveness_set: &[(ty::Region<'tcx>, Location, Cause)],
235+
liveness_set: &[(ty::Region<'tcx>, Location)],
236236
) {
237237
debug!(
238238
"add_region_liveness_constraints_from_type_check(liveness_set={} items)",
@@ -246,16 +246,16 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
246246
..
247247
} = self;
248248

249-
for (region, location, cause) in liveness_set {
249+
for (region, location) in liveness_set {
250250
debug!("generate: {:#?} is live at {:#?}", region, location);
251251
let region_vid = regioncx.to_region_vid(region);
252-
regioncx.add_live_point(region_vid, *location, &cause);
252+
regioncx.add_live_point(region_vid, *location);
253253
}
254254

255255
if let Some(all_facts) = all_facts {
256256
all_facts
257257
.region_live_at
258-
.extend(liveness_set.into_iter().flat_map(|(region, location, _)| {
258+
.extend(liveness_set.into_iter().flat_map(|(region, location)| {
259259
let r = regioncx.to_region_vid(region);
260260
let p1 = location_table.start_index(*location);
261261
let p2 = location_table.mid_index(*location);
@@ -268,7 +268,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
268268
/// `location` -- i.e., it may be used later. This means that all
269269
/// regions appearing in the type `live_ty` must be live at
270270
/// `location`.
271-
fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location, cause: Cause)
271+
fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
272272
where
273273
T: TypeFoldable<'tcx>,
274274
{
@@ -281,7 +281,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
281281
.tcx
282282
.for_each_free_region(&live_ty, |live_region| {
283283
let vid = live_region.to_region_vid();
284-
self.regioncx.add_live_point(vid, location, &cause);
284+
self.regioncx.add_live_point(vid, location);
285285
});
286286
}
287287

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

Lines changed: 100 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -8,74 +8,56 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow_check::borrow_set::BorrowData;
12-
use borrow_check::nll::region_infer::RegionInferenceContext;
11+
use std::collections::VecDeque;
12+
use std::rc::Rc;
13+
14+
use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
15+
use borrow_check::nll::ToRegionVid;
1316
use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
1417
use rustc::mir::{Local, Location, Mir};
18+
use rustc::ty::{RegionVid, TyCtxt};
1519
use rustc_data_structures::fx::FxHashSet;
1620
use util::liveness::{self, DefUse, LivenessMode};
1721

18-
crate fn regular_use<'gcx, 'tcx>(
19-
mir: &'gcx Mir,
20-
regioncx: &'tcx RegionInferenceContext,
21-
borrow: &'tcx BorrowData,
22+
crate fn find<'cx, 'gcx: 'tcx, 'tcx: 'cx>(
23+
mir: &'cx Mir<'tcx>,
24+
regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
25+
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
26+
region_vid: RegionVid,
2227
start_point: Location,
23-
local: Local,
24-
) -> Option<Location> {
28+
) -> Option<Cause> {
2529
let mut uf = UseFinder {
2630
mir,
2731
regioncx,
28-
borrow,
32+
tcx,
33+
region_vid,
2934
start_point,
30-
local,
3135
liveness_mode: LivenessMode {
3236
include_regular_use: true,
33-
include_drops: false,
34-
},
35-
};
36-
37-
uf.find()
38-
}
39-
40-
crate fn drop_use<'gcx, 'tcx>(
41-
mir: &'gcx Mir,
42-
regioncx: &'tcx RegionInferenceContext,
43-
borrow: &'tcx BorrowData,
44-
start_point: Location,
45-
local: Local,
46-
) -> Option<Location> {
47-
let mut uf = UseFinder {
48-
mir,
49-
regioncx,
50-
borrow,
51-
start_point,
52-
local,
53-
liveness_mode: LivenessMode {
54-
include_regular_use: false,
5537
include_drops: true,
5638
},
5739
};
5840

5941
uf.find()
6042
}
6143

62-
struct UseFinder<'gcx, 'tcx> {
63-
mir: &'gcx Mir<'gcx>,
64-
regioncx: &'tcx RegionInferenceContext<'tcx>,
65-
borrow: &'tcx BorrowData<'tcx>,
44+
struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
45+
mir: &'cx Mir<'tcx>,
46+
regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
47+
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
48+
region_vid: RegionVid,
6649
start_point: Location,
67-
local: Local,
6850
liveness_mode: LivenessMode,
6951
}
7052

71-
impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
72-
fn find(&mut self) -> Option<Location> {
73-
let mut stack = vec![];
53+
impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
54+
fn find(&mut self) -> Option<Cause> {
55+
let mut queue = VecDeque::new();
7456
let mut visited = FxHashSet();
7557

76-
stack.push(self.start_point);
77-
while let Some(p) = stack.pop() {
78-
if !self.regioncx.region_contains_point(self.borrow.region, p) {
58+
queue.push_back(self.start_point);
59+
while let Some(p) = queue.pop_front() {
60+
if !self.regioncx.region_contains_point(self.region_vid, p) {
7961
continue;
8062
}
8163

@@ -84,58 +66,102 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
8466
}
8567

8668
let block_data = &self.mir[p.block];
87-
let (defined, used) = self.def_use(p, block_data.visitable(p.statement_index));
88-
89-
if used {
90-
return Some(p);
91-
} else if !defined {
92-
if p.statement_index < block_data.statements.len() {
93-
stack.push(Location {
94-
statement_index: p.statement_index + 1,
95-
..p
96-
});
97-
} else {
98-
stack.extend(block_data.terminator().successors().map(|&basic_block| {
99-
Location {
100-
statement_index: 0,
101-
block: basic_block,
102-
}
103-
}));
69+
70+
match self.def_use(p, block_data.visitable(p.statement_index)) {
71+
Some(DefUseResult::Def) => {}
72+
73+
Some(DefUseResult::UseLive { local }) => {
74+
return Some(Cause::LiveVar(local, p));
75+
}
76+
77+
Some(DefUseResult::UseDrop { local }) => {
78+
return Some(Cause::DropVar(local, p));
79+
}
80+
81+
None => {
82+
if p.statement_index < block_data.statements.len() {
83+
queue.push_back(Location {
84+
statement_index: p.statement_index + 1,
85+
..p
86+
});
87+
} else {
88+
queue.extend(
89+
block_data
90+
.terminator()
91+
.successors()
92+
.filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind())
93+
.map(|&bb| Location {
94+
statement_index: 0,
95+
block: bb,
96+
}),
97+
);
98+
}
10499
}
105100
}
106101
}
107102

108103
None
109104
}
110105

111-
fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> (bool, bool) {
106+
fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
112107
let mut visitor = DefUseVisitor {
113-
defined: false,
114-
used: false,
115-
local: self.local,
108+
mir: self.mir,
109+
tcx: self.tcx,
110+
region_vid: self.region_vid,
116111
liveness_mode: self.liveness_mode,
112+
def_use_result: None,
117113
};
118114

119115
thing.apply(location, &mut visitor);
120116

121-
(visitor.defined, visitor.used)
117+
visitor.def_use_result
122118
}
123119
}
124120

125-
struct DefUseVisitor {
126-
defined: bool,
127-
used: bool,
128-
local: Local,
121+
struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
122+
mir: &'cx Mir<'tcx>,
123+
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
124+
region_vid: RegionVid,
129125
liveness_mode: LivenessMode,
126+
def_use_result: Option<DefUseResult>,
127+
}
128+
129+
enum DefUseResult {
130+
Def,
131+
132+
UseLive { local: Local },
133+
134+
UseDrop { local: Local },
130135
}
131136

132-
impl<'tcx> Visitor<'tcx> for DefUseVisitor {
137+
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
133138
fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
134-
if local == self.local {
139+
let local_ty = self.mir.local_decls[local].ty;
140+
141+
let mut found_it = false;
142+
self.tcx.for_each_free_region(&local_ty, |r| {
143+
if r.to_region_vid() == self.region_vid {
144+
found_it = true;
145+
}
146+
});
147+
148+
if found_it {
135149
match liveness::categorize(context, self.liveness_mode) {
136-
Some(DefUse::Def) => self.defined = true,
137-
Some(DefUse::Use) => self.used = true,
138-
None => (),
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+
}
139165
}
140166
}
141167
}

0 commit comments

Comments
 (0)