Skip to content

Commit 0a7b7dd

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 12fede8 commit 0a7b7dd

20 files changed

+416
-74
lines changed

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

Lines changed: 63 additions & 41 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, Lvalue};
1919
use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
2020
use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind};
21-
use transform::nll;
2221

2322
use rustc_data_structures::indexed_set::{self, IdxSetBuf};
2423
use rustc_data_structures::indexed_vec::Idx;
@@ -39,6 +38,7 @@ use util::borrowck_errors::{BorrowckErrors, Origin};
3938
use self::MutateMode::{JustWrite, WriteAndRead};
4039
use self::ConsumeKind::Consume;
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, param_env) {
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, param_env) {
8195
Ok(move_data) => move_data,
8296
Err((move_data, move_errors)) => {
8397
for move_error in move_errors {
@@ -110,60 +124,55 @@ 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-
);
158+
));
159+
160+
// If we are in non-lexical mode, compute the non-lexical lifetimes.
161+
let opt_regioncx = if let Some(free_regions) = free_regions {
162+
Some(nll::compute_regions(
163+
infcx,
164+
def_id,
165+
free_regions,
166+
mir,
167+
param_env,
168+
&mut flow_inits,
169+
&mdpe.move_data,
170+
))
171+
} else {
172+
assert!(!tcx.sess.opts.debugging_opts.nll);
173+
None
174+
};
175+
let flow_inits = flow_inits; // remove mut
167176

168177
let mut mbcx = MirBorrowckCtxt {
169178
tcx: tcx,
@@ -173,6 +182,16 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
173182
param_env: param_env,
174183
};
175184

185+
let flow_borrows = FlowInProgress::new(do_dataflow(
186+
tcx,
187+
mir,
188+
id,
189+
&attributes,
190+
&dead_unwinds,
191+
Borrows::new(tcx, mir, opt_regioncx),
192+
|bd, i| bd.location(i),
193+
));
194+
176195
let mut state = InProgress::new(flow_borrows, flow_inits, flow_uninits, flow_move_outs);
177196

178197
mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
@@ -2018,17 +2037,17 @@ impl ContextKind {
20182037
}
20192038

20202039
impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
2021-
pub(super) fn new(
2022-
borrows: DataflowResults<Borrows<'b, 'gcx, 'tcx>>,
2023-
inits: DataflowResults<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
2024-
uninits: DataflowResults<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
2025-
move_out: DataflowResults<MovingOutStatements<'b, 'gcx, 'tcx>>,
2040+
fn new(
2041+
borrows: FlowInProgress<Borrows<'b, 'gcx, 'tcx>>,
2042+
inits: FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
2043+
uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
2044+
move_outs: FlowInProgress<MovingOutStatements<'b, 'gcx, 'tcx>>,
20262045
) -> Self {
20272046
InProgress {
2028-
borrows: FlowInProgress::new(borrows),
2029-
inits: FlowInProgress::new(inits),
2030-
uninits: FlowInProgress::new(uninits),
2031-
move_outs: FlowInProgress::new(move_out),
2047+
borrows,
2048+
inits,
2049+
uninits,
2050+
move_outs,
20322051
}
20332052
}
20342053

@@ -2118,8 +2137,11 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
21182137
}
21192138
}
21202139

2121-
impl<'b, 'gcx, 'tcx> FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>> {
2122-
fn has_any_child_of(&self, mpi: MovePathIndex) -> Option<MovePathIndex> {
2140+
impl<'tcx, T> FlowInProgress<T>
2141+
where
2142+
T: HasMoveData<'tcx> + BitDenotation<Idx = MovePathIndex>,
2143+
{
2144+
fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> {
21232145
let move_data = self.base_results.operator().move_data();
21242146

21252147
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
@@ -12,44 +12,54 @@ use rustc::hir;
1212
use rustc::mir::{Location, Lvalue, Mir, Rvalue};
1313
use rustc::mir::visit::Visitor;
1414
use rustc::mir::Lvalue::Projection;
15-
use rustc::mir::{LvalueProjection, ProjectionElem};
15+
use rustc::mir::{LvalueProjection, ProjectionElem, Local};
1616
use rustc::infer::InferCtxt;
1717
use rustc::traits::{self, ObligationCause};
1818
use rustc::ty::{self, Ty};
1919
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

@@ -212,7 +259,7 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
212259
}
213260
}
214261

215-
impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
262+
impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx, 'tcx> {
216263
fn visit_rvalue(&mut self,
217264
rvalue: &Rvalue<'tcx>,
218265
location: Location) {

0 commit comments

Comments
 (0)