Skip to content

Commit f3375ed

Browse files
committed
Auto merge of #51889 - spastorino:make-causal-tracking-lazy, r=<try>
Make causal tracking lazy Closes #51710 r? @nikomatsakis
2 parents 57dd722 + 5233a12 commit f3375ed

13 files changed

+308
-410
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

Lines changed: 168 additions & 0 deletions
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)