Skip to content

Commit 64f8ae0

Browse files
committed
Auto merge of #51889 - spastorino:make-causal-tracking-lazy, r=nikomatsakis
Make causal tracking lazy Closes #51710 r? @nikomatsakis
2 parents 8fa9bfe + 71f25b4 commit 64f8ae0

14 files changed

+336
-437
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

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// Copyright 2017 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 std::collections::VecDeque;
12+
use std::rc::Rc;
13+
14+
use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
15+
use borrow_check::nll::ToRegionVid;
16+
use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
17+
use rustc::mir::{Local, Location, Mir};
18+
use rustc::ty::{RegionVid, TyCtxt};
19+
use rustc_data_structures::fx::FxHashSet;
20+
use util::liveness::{self, DefUse, LivenessMode};
21+
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,
27+
start_point: Location,
28+
) -> Option<Cause> {
29+
let mut uf = UseFinder {
30+
mir,
31+
regioncx,
32+
tcx,
33+
region_vid,
34+
start_point,
35+
liveness_mode: LivenessMode {
36+
include_regular_use: true,
37+
include_drops: true,
38+
},
39+
};
40+
41+
uf.find()
42+
}
43+
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,
49+
start_point: Location,
50+
liveness_mode: LivenessMode,
51+
}
52+
53+
impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
54+
fn find(&mut self) -> Option<Cause> {
55+
let mut queue = VecDeque::new();
56+
let mut visited = FxHashSet();
57+
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) {
61+
continue;
62+
}
63+
64+
if !visited.insert(p) {
65+
continue;
66+
}
67+
68+
let block_data = &self.mir[p.block];
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+
}
99+
}
100+
}
101+
}
102+
103+
None
104+
}
105+
106+
fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
107+
let mut visitor = DefUseVisitor {
108+
mir: self.mir,
109+
tcx: self.tcx,
110+
region_vid: self.region_vid,
111+
liveness_mode: self.liveness_mode,
112+
def_use_result: None,
113+
};
114+
115+
thing.apply(location, &mut visitor);
116+
117+
visitor.def_use_result
118+
}
119+
}
120+
121+
struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
122+
mir: &'cx Mir<'tcx>,
123+
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
124+
region_vid: RegionVid,
125+
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 },
135+
}
136+
137+
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
138+
fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
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 {
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+
}
166+
}
167+
}
168+
}

0 commit comments

Comments
 (0)