Skip to content

Commit 0957ede

Browse files
committed
Make causal tracking lazy
1 parent 24f91e8 commit 0957ede

14 files changed

+225
-319
lines changed

src/librustc/mir/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,10 @@ impl<'tcx> Terminator<'tcx> {
10001000
self.kind.successors_mut()
10011001
}
10021002

1003+
pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
1004+
self.kind.unwind()
1005+
}
1006+
10031007
pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
10041008
self.kind.unwind_mut()
10051009
}
@@ -1195,6 +1199,31 @@ impl<'tcx> TerminatorKind<'tcx> {
11951199
}
11961200
}
11971201

1202+
pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
1203+
match *self {
1204+
TerminatorKind::Goto { .. }
1205+
| TerminatorKind::Resume
1206+
| TerminatorKind::Abort
1207+
| TerminatorKind::Return
1208+
| TerminatorKind::Unreachable
1209+
| TerminatorKind::GeneratorDrop
1210+
| TerminatorKind::Yield { .. }
1211+
| TerminatorKind::SwitchInt { .. }
1212+
| TerminatorKind::FalseEdges { .. } => None,
1213+
TerminatorKind::Call {
1214+
cleanup: ref unwind,
1215+
..
1216+
}
1217+
| TerminatorKind::Assert {
1218+
cleanup: ref unwind,
1219+
..
1220+
}
1221+
| TerminatorKind::DropAndReplace { ref unwind, .. }
1222+
| TerminatorKind::Drop { ref unwind, .. }
1223+
| TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind),
1224+
}
1225+
}
1226+
11981227
pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
11991228
match *self {
12001229
TerminatorKind::Goto { .. }

src/librustc_mir/borrow_check/nll/constraint_generation.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet;
1212
use borrow_check::location::LocationTable;
1313
use borrow_check::nll::ToRegionVid;
1414
use borrow_check::nll::facts::AllFacts;
15-
use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
15+
use borrow_check::nll::region_infer::RegionInferenceContext;
1616
use borrow_check::nll::type_check::AtLocation;
1717
use rustc::hir;
1818
use rustc::infer::InferCtxt;
@@ -33,7 +33,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
3333
location_table: &LocationTable,
3434
mir: &Mir<'tcx>,
3535
borrow_set: &BorrowSet<'tcx>,
36-
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location, Cause)],
36+
liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)],
3737
) {
3838
let mut cg = ConstraintGeneration {
3939
borrow_set,
@@ -69,14 +69,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
6969
/// We sometimes have `substs` within an rvalue, or within a
7070
/// call. Make them live at the location where they appear.
7171
fn visit_substs(&mut self, substs: &&'tcx Substs<'tcx>, location: Location) {
72-
self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
72+
self.add_regular_live_constraint(*substs, location);
7373
self.super_substs(substs);
7474
}
7575

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

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

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

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

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

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

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

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

+100-74
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)