Skip to content

Commit a9cb25b

Browse files
Nashenas88nikomatsakis
authored andcommitted
inform constraint generation using maybe-init
In particular, if we see a variable is DROP-LIVE, but it is not MAYBE-INIT, then we can ignore the drop. This leavess attempt to use more complex refinements of the idea (e.g., for subpaths or subfields) to future work.
1 parent 08c8d7e commit a9cb25b

20 files changed

+374
-78
lines changed

src/librustc_mir/borrow_check.rs renamed to src/librustc_mir/borrow_check/mod.rs

Lines changed: 67 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use rustc::ty::maps::Providers;
1818
use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Local, Location, Place};
1919
use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
2020
use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
21-
use transform::nll;
2221

2322
use rustc_data_structures::fx::FxHashSet;
2423
use rustc_data_structures::indexed_set::{self, IdxSetBuf};
@@ -39,6 +38,7 @@ use util::borrowck_errors::{BorrowckErrors, Origin};
3938

4039
use self::MutateMode::{JustWrite, WriteAndRead};
4140

41+
pub(crate) mod nll;
4242

4343
pub fn provide(providers: &mut Providers) {
4444
*providers = Providers {
@@ -77,7 +77,21 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
7777
.as_local_node_id(def_id)
7878
.expect("do_mir_borrowck: non-local DefId");
7979

80-
let move_data: MoveData<'tcx> = match MoveData::gather_moves(input_mir, tcx) {
80+
// Make our own copy of the MIR. This copy will be modified (in place) to
81+
// contain non-lexical lifetimes. It will have a lifetime tied
82+
// to the inference context.
83+
let mut mir: Mir<'tcx> = input_mir.clone();
84+
let free_regions = if !tcx.sess.opts.debugging_opts.nll {
85+
None
86+
} else {
87+
let mir = &mut mir;
88+
89+
// Replace all regions with fresh inference variables.
90+
Some(nll::replace_regions_in_mir(infcx, def_id, mir))
91+
};
92+
let mir = &mir;
93+
94+
let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx) {
8195
Ok(move_data) => move_data,
8296
Err((move_data, move_errors)) => {
8397
for move_error in move_errors {
@@ -110,69 +124,64 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
110124
}
111125
};
112126

113-
// Make our own copy of the MIR. This copy will be modified (in place) to
114-
// contain non-lexical lifetimes. It will have a lifetime tied
115-
// to the inference context.
116-
let mut mir: Mir<'tcx> = input_mir.clone();
117-
let mir = &mut mir;
118-
119-
// If we are in non-lexical mode, compute the non-lexical lifetimes.
120-
let opt_regioncx = if !tcx.sess.opts.debugging_opts.nll {
121-
None
122-
} else {
123-
Some(nll::compute_regions(infcx, def_id, param_env, mir))
124-
};
125-
126127
let mdpe = MoveDataParamEnv {
127128
move_data: move_data,
128129
param_env: param_env,
129130
};
130131
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
131-
let flow_borrows = do_dataflow(
132-
tcx,
133-
mir,
134-
id,
135-
&attributes,
136-
&dead_unwinds,
137-
Borrows::new(tcx, mir, opt_regioncx.as_ref()),
138-
|bd, i| bd.location(i),
139-
);
140-
let flow_inits = do_dataflow(
132+
let mut flow_inits = FlowInProgress::new(do_dataflow(
141133
tcx,
142134
mir,
143135
id,
144136
&attributes,
145137
&dead_unwinds,
146138
MaybeInitializedLvals::new(tcx, mir, &mdpe),
147139
|bd, i| &bd.move_data().move_paths[i],
148-
);
149-
let flow_uninits = do_dataflow(
140+
));
141+
let flow_uninits = FlowInProgress::new(do_dataflow(
150142
tcx,
151143
mir,
152144
id,
153145
&attributes,
154146
&dead_unwinds,
155147
MaybeUninitializedLvals::new(tcx, mir, &mdpe),
156148
|bd, i| &bd.move_data().move_paths[i],
157-
);
158-
let flow_move_outs = do_dataflow(
149+
));
150+
let flow_move_outs = FlowInProgress::new(do_dataflow(
159151
tcx,
160152
mir,
161153
id,
162154
&attributes,
163155
&dead_unwinds,
164156
MovingOutStatements::new(tcx, mir, &mdpe),
165157
|bd, i| &bd.move_data().moves[i],
166-
);
167-
let flow_ever_inits = do_dataflow(
158+
));
159+
let flow_ever_inits = FlowInProgress::new(do_dataflow(
168160
tcx,
169161
mir,
170162
id,
171163
&attributes,
172164
&dead_unwinds,
173165
EverInitializedLvals::new(tcx, mir, &mdpe),
174166
|bd, i| &bd.move_data().inits[i],
175-
);
167+
));
168+
169+
// If we are in non-lexical mode, compute the non-lexical lifetimes.
170+
let opt_regioncx = if let Some(free_regions) = free_regions {
171+
Some(nll::compute_regions(
172+
infcx,
173+
def_id,
174+
free_regions,
175+
mir,
176+
param_env,
177+
&mut flow_inits,
178+
&mdpe.move_data,
179+
))
180+
} else {
181+
assert!(!tcx.sess.opts.debugging_opts.nll);
182+
None
183+
};
184+
let flow_inits = flow_inits; // remove mut
176185

177186
let mut mbcx = MirBorrowckCtxt {
178187
tcx: tcx,
@@ -183,6 +192,16 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
183192
storage_dead_or_drop_error_reported: FxHashSet(),
184193
};
185194

195+
let flow_borrows = FlowInProgress::new(do_dataflow(
196+
tcx,
197+
mir,
198+
id,
199+
&attributes,
200+
&dead_unwinds,
201+
Borrows::new(tcx, mir, opt_regioncx),
202+
|bd, i| bd.location(i),
203+
));
204+
186205
let mut state = InProgress::new(
187206
flow_borrows,
188207
flow_inits,
@@ -2318,19 +2337,19 @@ impl ContextKind {
23182337
}
23192338

23202339
impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
2321-
pub(super) fn new(
2322-
borrows: DataflowResults<Borrows<'b, 'gcx, 'tcx>>,
2323-
inits: DataflowResults<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
2324-
uninits: DataflowResults<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
2325-
move_out: DataflowResults<MovingOutStatements<'b, 'gcx, 'tcx>>,
2326-
ever_inits: DataflowResults<EverInitializedLvals<'b, 'gcx, 'tcx>>,
2340+
fn new(
2341+
borrows: FlowInProgress<Borrows<'b, 'gcx, 'tcx>>,
2342+
inits: FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
2343+
uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
2344+
move_outs: FlowInProgress<MovingOutStatements<'b, 'gcx, 'tcx>>,
2345+
ever_inits: FlowInProgress<EverInitializedLvals<'b, 'gcx, 'tcx>>,
23272346
) -> Self {
23282347
InProgress {
2329-
borrows: FlowInProgress::new(borrows),
2330-
inits: FlowInProgress::new(inits),
2331-
uninits: FlowInProgress::new(uninits),
2332-
move_outs: FlowInProgress::new(move_out),
2333-
ever_inits: FlowInProgress::new(ever_inits),
2348+
borrows,
2349+
inits,
2350+
uninits,
2351+
move_outs,
2352+
ever_inits,
23342353
}
23352354
}
23362355

@@ -2436,8 +2455,11 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
24362455
}
24372456
}
24382457

2439-
impl<'b, 'gcx, 'tcx> FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>> {
2440-
fn has_any_child_of(&self, mpi: MovePathIndex) -> Option<MovePathIndex> {
2458+
impl<'tcx, T> FlowInProgress<T>
2459+
where
2460+
T: HasMoveData<'tcx> + BitDenotation<Idx = MovePathIndex>,
2461+
{
2462+
fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> {
24412463
let move_data = self.base_results.operator().move_data();
24422464

24432465
let mut todo = vec![mpi];

src/librustc_mir/transform/nll/constraint_generation.rs renamed to src/librustc_mir/borrow_check/nll/constraint_generation.rs

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use rustc::hir;
12-
use rustc::mir::{Location, Place, Mir, Rvalue};
12+
use rustc::mir::{Local, Location, Place, Mir, Rvalue};
1313
use rustc::mir::visit::Visitor;
1414
use rustc::mir::Place::Projection;
1515
use rustc::mir::{PlaceProjection, ProjectionElem};
@@ -20,36 +20,46 @@ use rustc::ty::fold::TypeFoldable;
2020
use rustc::util::common::ErrorReported;
2121
use rustc_data_structures::fx::FxHashSet;
2222
use syntax::codemap::DUMMY_SP;
23+
use borrow_check::FlowInProgress;
24+
use dataflow::MaybeInitializedLvals;
25+
use dataflow::move_paths::{MoveData, HasMoveData};
2326

2427
use super::LivenessResults;
2528
use super::ToRegionVid;
2629
use super::region_infer::RegionInferenceContext;
2730

28-
pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
29-
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
31+
pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
32+
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
3033
regioncx: &mut RegionInferenceContext<'tcx>,
3134
mir: &Mir<'tcx>,
3235
param_env: ty::ParamEnv<'tcx>,
3336
liveness: &LivenessResults,
37+
flow_inits: &mut FlowInProgress<MaybeInitializedLvals<'cx, 'gcx, 'tcx>>,
38+
move_data: &MoveData<'tcx>,
3439
) {
3540
ConstraintGeneration {
3641
infcx,
3742
regioncx,
3843
mir,
3944
liveness,
4045
param_env,
46+
flow_inits,
47+
move_data,
4148
}.add_constraints();
4249
}
4350

44-
struct ConstraintGeneration<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
45-
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
46-
regioncx: &'cx mut RegionInferenceContext<'tcx>,
47-
mir: &'cx Mir<'tcx>,
48-
liveness: &'cx LivenessResults,
51+
/// 'cg = the duration of the constraint generation process itself.
52+
struct ConstraintGeneration<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> {
53+
infcx: &'cg InferCtxt<'cx, 'gcx, 'tcx>,
54+
regioncx: &'cg mut RegionInferenceContext<'tcx>,
55+
mir: &'cg Mir<'tcx>,
56+
liveness: &'cg LivenessResults,
4957
param_env: ty::ParamEnv<'tcx>,
58+
flow_inits: &'cg mut FlowInProgress<MaybeInitializedLvals<'cx, 'gcx, 'tcx>>,
59+
move_data: &'cg MoveData<'tcx>,
5060
}
5161

52-
impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
62+
impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
5363
fn add_constraints(&mut self) {
5464
self.add_liveness_constraints();
5565
self.add_borrow_constraints();
@@ -73,14 +83,51 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
7383
}
7484
});
7585

76-
self.liveness
77-
.drop
78-
.simulate_block(self.mir, bb, |location, live_locals| {
79-
for live_local in live_locals.iter() {
86+
let mut all_live_locals: Vec<(Location, Vec<Local>)> = vec![];
87+
self.liveness.drop.simulate_block(self.mir, bb, |location, live_locals| {
88+
all_live_locals.push((location, live_locals.iter().collect()));
89+
});
90+
debug!("add_liveness_constraints: all_live_locals={:#?}", all_live_locals);
91+
92+
let terminator_index = self.mir.basic_blocks()[bb].statements.len();
93+
self.flow_inits.reset_to_entry_of(bb);
94+
while let Some((location, live_locals)) = all_live_locals.pop() {
95+
for live_local in live_locals {
96+
debug!("add_liveness_constraints: location={:?} live_local={:?}", location,
97+
live_local);
98+
99+
self.flow_inits.each_state_bit(|mpi_init| {
100+
debug!("add_liveness_constraints: location={:?} initialized={:?}",
101+
location,
102+
&self.flow_inits
103+
.base_results
104+
.operator()
105+
.move_data()
106+
.move_paths[mpi_init]);
107+
});
108+
109+
let mpi = self.move_data.rev_lookup.find_local(live_local);
110+
if let Some(initialized_child) = self.flow_inits.has_any_child_of(mpi) {
111+
debug!("add_liveness_constraints: mpi={:?} has initialized child {:?}",
112+
self.move_data.move_paths[mpi],
113+
self.move_data.move_paths[initialized_child]);
114+
80115
let live_local_ty = self.mir.local_decls[live_local].ty;
81116
self.add_drop_live_constraint(live_local_ty, location);
82117
}
83-
});
118+
}
119+
120+
if location.statement_index == terminator_index {
121+
debug!("add_liveness_constraints: reconstruct_terminator_effect from {:#?}",
122+
location);
123+
self.flow_inits.reconstruct_terminator_effect(location);
124+
} else {
125+
debug!("add_liveness_constraints: reconstruct_statement_effect from {:#?}",
126+
location);
127+
self.flow_inits.reconstruct_statement_effect(location);
128+
}
129+
self.flow_inits.apply_local_effect();
130+
}
84131
}
85132
}
86133

@@ -219,7 +266,7 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
219266
}
220267
}
221268

222-
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
269+
impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx, 'tcx> {
223270
fn visit_rvalue(&mut self,
224271
rvalue: &Rvalue<'tcx>,
225272
location: Location) {

0 commit comments

Comments
 (0)