Skip to content

Commit c75a4f3

Browse files
committed
separate out the liveness constraints from the final value
It will be useful later for diagnostics to be able to remember where things were live.
1 parent e8a9120 commit c75a4f3

File tree

1 file changed

+47
-34
lines changed

1 file changed

+47
-34
lines changed

src/librustc_mir/transform/nll/region_infer.rs

+47-34
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ pub struct RegionInferenceContext<'tcx> {
2828
/// from as well as its final inferred value.
2929
definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
3030

31+
/// The liveness constraints added to each region. For most
32+
/// regions, these start out empty and steadily grow, though for
33+
/// each free region R they start out containing the entire CFG
34+
/// and `end(R)`.
35+
liveness_constraints: IndexVec<RegionVid, Region>,
36+
37+
/// The final inferred values of the inference variables; `None`
38+
/// until `solve` is invoked.
39+
inferred_values: Option<IndexVec<RegionVid, Region>>,
40+
3141
/// The constraints we have accumulated and used during solving.
3242
constraints: Vec<Constraint>,
3343
}
@@ -46,11 +56,6 @@ struct RegionDefinition<'tcx> {
4656
/// If true, this is a constant region which cannot grow larger.
4757
/// This is used for named regions as well as `'static`.
4858
constant: bool,
49-
50-
/// The current value of this inference variable. This starts out
51-
/// empty, but grows as we add constraints. The final value is
52-
/// determined when `solve()` is executed.
53-
value: Region,
5459
}
5560

5661
/// The value of an individual region variable. Region variables
@@ -115,6 +120,8 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
115120
/// of those will be constant regions representing the free
116121
/// regions defined in `free_regions`.
117122
pub fn new(var_origins: VarOrigins, free_regions: &FreeRegions<'tcx>, mir: &Mir<'tcx>) -> Self {
123+
let num_region_variables = var_origins.len();
124+
118125
// Create a RegionDefinition for each inference variable.
119126
let definitions = var_origins
120127
.into_iter()
@@ -123,6 +130,8 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
123130

124131
let mut result = Self {
125132
definitions: definitions,
133+
liveness_constraints: IndexVec::from_elem_n(Region::default(), num_region_variables),
134+
inferred_values: None,
126135
constraints: Vec::new(),
127136
};
128137

@@ -170,24 +179,23 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
170179

171180
// Add all nodes in the CFG to `definition.value`.
172181
for (block, block_data) in mir.basic_blocks().iter_enumerated() {
173-
let definition = &mut self.definitions[variable];
182+
let liveness_constraint = &mut self.liveness_constraints[variable];
174183
for statement_index in 0..block_data.statements.len() + 1 {
175184
let location = Location {
176185
block,
177186
statement_index,
178187
};
179-
definition.value.add_point(location);
188+
liveness_constraint.add_point(location);
180189
}
181190
}
182191

183192
// Add `end(X)` into the set for X.
184-
self.definitions[variable].value.add_free_region(variable);
193+
self.liveness_constraints[variable].add_free_region(variable);
185194

186195
// `'static` outlives all other free regions as well.
187196
if let ty::ReStatic = free_region {
188197
for &other_variable in indices.values() {
189-
self.definitions[variable]
190-
.value
198+
self.liveness_constraints[variable]
191199
.add_free_region(other_variable);
192200
}
193201
}
@@ -196,16 +204,14 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
196204
// Y: X is true). Add `end(X)` into the set for `Y`.
197205
for superregion in free_region_map.regions_that_outlive(&free_region) {
198206
let superregion_index = indices[superregion];
199-
self.definitions[superregion_index]
200-
.value
201-
.add_free_region(variable);
207+
self.liveness_constraints[superregion_index].add_free_region(variable);
202208
}
203209

204210
debug!(
205211
"init_free_regions: region variable for `{:?}` is `{:?}` with value `{:?}`",
206212
free_region,
207213
variable,
208-
self.definitions[variable].value
214+
self.liveness_constraints[variable],
209215
);
210216
}
211217
}
@@ -219,25 +225,25 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
219225
///
220226
/// Until `solve()` executes, this value is not particularly meaningful.
221227
pub fn region_contains_point(&self, r: RegionVid, p: Location) -> bool {
222-
self.definitions[r].value.contains_point(p)
228+
let inferred_values = self.inferred_values
229+
.as_ref()
230+
.expect("region values not yet inferred");
231+
inferred_values[r].contains_point(p)
223232
}
224233

225234
/// Returns access to the value of `r` for debugging purposes.
226235
pub(super) fn region_value(&self, r: RegionVid) -> &fmt::Debug {
227-
&self.definitions[r].value
236+
let inferred_values = self.inferred_values
237+
.as_ref()
238+
.expect("region values not yet inferred");
239+
&inferred_values[r]
228240
}
229241

230242
/// Indicates that the region variable `v` is live at the point `point`.
231243
pub(super) fn add_live_point(&mut self, v: RegionVid, point: Location) {
232244
debug!("add_live_point({:?}, {:?})", v, point);
233-
let definition = &mut self.definitions[v];
234-
if !definition.constant {
235-
definition.value.add_point(point);
236-
} else {
237-
// Constants are used for free regions, which already
238-
// contain all the points in the control-flow graph.
239-
assert!(definition.value.contains_point(point));
240-
}
245+
assert!(self.inferred_values.is_none(), "values already inferred");
246+
self.liveness_constraints[v].add_point(point);
241247
}
242248

243249
/// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
@@ -249,6 +255,7 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
249255
point: Location,
250256
) {
251257
debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point);
258+
assert!(self.inferred_values.is_none(), "values already inferred");
252259
self.constraints.push(Constraint {
253260
span,
254261
sup,
@@ -259,6 +266,7 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
259266

260267
/// Perform region inference.
261268
pub(super) fn solve(&mut self, infcx: &InferCtxt<'a, 'gcx, 'tcx>, mir: &Mir<'tcx>) {
269+
assert!(self.inferred_values.is_none(), "values already inferred");
262270
let errors = self.propagate_constraints(mir);
263271

264272
// worst error msg ever
@@ -291,39 +299,43 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
291299
constraints
292300
});
293301

302+
// The initial values for each region are derived from the liveness
303+
// constraints we have accumulated.
304+
let mut inferred_values = self.liveness_constraints.clone();
305+
294306
while changed {
295307
changed = false;
296308
for constraint in &self.constraints {
297309
debug!("propagate_constraints: constraint={:?}", constraint);
298-
let sub = &self.definitions[constraint.sub].value.clone();
299-
let sup_def = &mut self.definitions[constraint.sup];
310+
let sub = &inferred_values[constraint.sub].clone();
311+
let sup_value = &mut inferred_values[constraint.sup];
300312

301313
debug!("propagate_constraints: sub (before): {:?}", sub);
302-
debug!("propagate_constraints: sup (before): {:?}", sup_def.value);
314+
debug!("propagate_constraints: sup (before): {:?}", sup_value);
303315

304-
if !sup_def.constant {
316+
if !self.definitions[constraint.sup].constant {
305317
// If this is not a constant, then grow the value as needed to
306318
// accommodate the outlives constraint.
307319

308-
if dfs.copy(sub, &mut sup_def.value, constraint.point) {
320+
if dfs.copy(sub, sup_value, constraint.point) {
309321
changed = true;
310322
}
311323

312-
debug!("propagate_constraints: sup (after) : {:?}", sup_def.value);
324+
debug!("propagate_constraints: sup (after) : {:?}", sup_value);
313325
debug!("propagate_constraints: changed : {:?}", changed);
314326
} else {
315327
// If this is a constant, check whether it *would
316328
// have* to grow in order for the constraint to be
317329
// satisfied. If so, create an error.
318330

319-
let mut sup_value = sup_def.value.clone();
320-
if dfs.copy(sub, &mut sup_value, constraint.point) {
331+
let sup_value = &mut sup_value.clone();
332+
if dfs.copy(sub, sup_value, constraint.point) {
321333
// Constant values start out with the entire
322334
// CFG, so it must be some new free region
323335
// that was added. Find one.
324336
let &new_region = sup_value
325337
.free_regions
326-
.difference(&sup_def.value.free_regions)
338+
.difference(&sup_value.free_regions)
327339
.next()
328340
.unwrap();
329341
debug!("propagate_constraints: new_region : {:?}", new_region);
@@ -335,6 +347,8 @@ impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
335347
}
336348
debug!("\n");
337349
}
350+
351+
self.inferred_values = Some(inferred_values);
338352
errors
339353
}
340354
}
@@ -424,7 +438,6 @@ impl<'tcx> RegionDefinition<'tcx> {
424438
origin,
425439
name: None,
426440
constant: false,
427-
value: Region::default(),
428441
}
429442
}
430443
}

0 commit comments

Comments
 (0)