Skip to content

Commit 2eb3e96

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 8b7f218 commit 2eb3e96

20 files changed

+370
-74
lines changed
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::{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};
@@ -40,6 +39,7 @@ use util::borrowck_errors::{BorrowckErrors, Origin};
4039
use self::MutateMode::{JustWrite, WriteAndRead};
4140
use self::ConsumeKind::Consume;
4241

42+
pub(crate) mod nll;
4343

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

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

114-
// Make our own copy of the MIR. This copy will be modified (in place) to
115-
// contain non-lexical lifetimes. It will have a lifetime tied
116-
// to the inference context.
117-
let mut mir: Mir<'tcx> = input_mir.clone();
118-
let mir = &mut mir;
119-
120-
// If we are in non-lexical mode, compute the non-lexical lifetimes.
121-
let opt_regioncx = if !tcx.sess.opts.debugging_opts.nll {
122-
None
123-
} else {
124-
Some(nll::compute_regions(infcx, def_id, param_env, mir))
125-
};
126-
127128
let mdpe = MoveDataParamEnv {
128129
move_data: move_data,
129130
param_env: param_env,
130131
};
131132
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
132-
let flow_borrows = do_dataflow(
133-
tcx,
134-
mir,
135-
id,
136-
&attributes,
137-
&dead_unwinds,
138-
Borrows::new(tcx, mir, opt_regioncx.as_ref()),
139-
|bd, i| bd.location(i),
140-
);
141-
let flow_inits = do_dataflow(
133+
let mut flow_inits = FlowInProgress::new(do_dataflow(
142134
tcx,
143135
mir,
144136
id,
145137
&attributes,
146138
&dead_unwinds,
147139
MaybeInitializedLvals::new(tcx, mir, &mdpe),
148140
|bd, i| &bd.move_data().move_paths[i],
149-
);
150-
let flow_uninits = do_dataflow(
141+
));
142+
let flow_uninits = FlowInProgress::new(do_dataflow(
151143
tcx,
152144
mir,
153145
id,
154146
&attributes,
155147
&dead_unwinds,
156148
MaybeUninitializedLvals::new(tcx, mir, &mdpe),
157149
|bd, i| &bd.move_data().move_paths[i],
158-
);
159-
let flow_move_outs = do_dataflow(
150+
));
151+
let flow_move_outs = FlowInProgress::new(do_dataflow(
160152
tcx,
161153
mir,
162154
id,
163155
&attributes,
164156
&dead_unwinds,
165157
MovingOutStatements::new(tcx, mir, &mdpe),
166158
|bd, i| &bd.move_data().moves[i],
167-
);
159+
));
160+
161+
// If we are in non-lexical mode, compute the non-lexical lifetimes.
162+
let opt_regioncx = if let Some(free_regions) = free_regions {
163+
Some(nll::compute_regions(
164+
infcx,
165+
def_id,
166+
free_regions,
167+
mir,
168+
param_env,
169+
&mut flow_inits,
170+
&mdpe.move_data,
171+
))
172+
} else {
173+
assert!(!tcx.sess.opts.debugging_opts.nll);
174+
None
175+
};
176+
let flow_inits = flow_inits; // remove mut
168177

169178
let mut mbcx = MirBorrowckCtxt {
170179
tcx: tcx,
@@ -175,6 +184,16 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
175184
storage_drop_or_dead_error_reported: FxHashSet(),
176185
};
177186

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

180199
mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
@@ -2160,17 +2179,17 @@ impl ContextKind {
21602179
}
21612180

21622181
impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
2163-
pub(super) fn new(
2164-
borrows: DataflowResults<Borrows<'b, 'gcx, 'tcx>>,
2165-
inits: DataflowResults<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
2166-
uninits: DataflowResults<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
2167-
move_out: DataflowResults<MovingOutStatements<'b, 'gcx, 'tcx>>,
2182+
fn new(
2183+
borrows: FlowInProgress<Borrows<'b, 'gcx, 'tcx>>,
2184+
inits: FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
2185+
uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
2186+
move_outs: FlowInProgress<MovingOutStatements<'b, 'gcx, 'tcx>>,
21682187
) -> Self {
21692188
InProgress {
2170-
borrows: FlowInProgress::new(borrows),
2171-
inits: FlowInProgress::new(inits),
2172-
uninits: FlowInProgress::new(uninits),
2173-
move_outs: FlowInProgress::new(move_out),
2189+
borrows,
2190+
inits,
2191+
uninits,
2192+
move_outs,
21742193
}
21752194
}
21762195

@@ -2260,8 +2279,11 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
22602279
}
22612280
}
22622281

2263-
impl<'b, 'gcx, 'tcx> FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>> {
2264-
fn has_any_child_of(&self, mpi: MovePathIndex) -> Option<MovePathIndex> {
2282+
impl<'tcx, T> FlowInProgress<T>
2283+
where
2284+
T: HasMoveData<'tcx> + BitDenotation<Idx = MovePathIndex>,
2285+
{
2286+
fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> {
22652287
let move_data = self.base_results.operator().move_data();
22662288

22672289
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) {
File renamed without changes.

0 commit comments

Comments
 (0)