Skip to content

Commit e4f0368

Browse files
committed
use the type system to ensure we dedup from the start
1 parent 0119669 commit e4f0368

File tree

7 files changed

+60
-43
lines changed

7 files changed

+60
-43
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use borrow_check::nll::region_infer::{ConstraintIndex, OutlivesConstraint};
2+
use rustc_data_structures::indexed_vec::IndexVec;
3+
use rustc_data_structures::fx::FxHashSet;
4+
use rustc::ty::RegionVid;
5+
6+
#[derive(Clone, Default)]
7+
crate struct ConstraintSet {
8+
constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
9+
seen_constraints: FxHashSet<(RegionVid, RegionVid)>,
10+
}
11+
12+
impl ConstraintSet {
13+
pub fn push(&mut self, outlives_constraint: OutlivesConstraint) {
14+
debug!("add_outlives({:?}: {:?} @ {:?}", outlives_constraint.sup, outlives_constraint.sub, outlives_constraint.point);
15+
if outlives_constraint.sup == outlives_constraint.sub {
16+
// 'a: 'a is pretty uninteresting
17+
return;
18+
}
19+
if self.seen_constraints.insert(outlives_constraint.dedup_key()) {
20+
self.constraints.push(outlives_constraint);
21+
}
22+
}
23+
24+
pub fn iner(&self) -> &IndexVec<ConstraintIndex, OutlivesConstraint> {
25+
&self.constraints
26+
}
27+
28+
/// Do Not use this to add nor remove items to the Vec, nor change the `sup`, nor `sub` of the data.
29+
pub fn iner_mut(&mut self) -> &mut IndexVec<ConstraintIndex, OutlivesConstraint> {
30+
&mut self.constraints
31+
}
32+
}
33+

src/librustc_mir/borrow_check/nll/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ mod renumber;
4545
crate mod type_check;
4646
mod universal_regions;
4747

48+
crate mod constraint_set;
49+
4850
use self::facts::AllFacts;
4951
use self::region_infer::RegionInferenceContext;
5052
use self::universal_regions::UniversalRegions;

src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
7676
}
7777
}
7878

79-
let mut constraints: Vec<_> = self.constraints.iter().collect();
79+
let mut constraints: Vec<_> = self.constraints.iner().iter().collect();
8080
constraints.sort();
8181
for constraint in &constraints {
8282
let OutlivesConstraint {

src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl<'this, 'tcx> dot::GraphWalk<'this> for RegionInferenceContext<'tcx> {
5555
vids.into_cow()
5656
}
5757
fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint> {
58-
(&self.constraints.raw[..]).into_cow()
58+
(&self.constraints.iner().raw[..]).into_cow()
5959
}
6060

6161
// Render `a: b` as `a <- b`, indicating the flow

src/librustc_mir/borrow_check/nll/region_infer/mod.rs

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use super::universal_regions::UniversalRegions;
1212
use borrow_check::nll::region_infer::values::ToElementIndex;
13+
use borrow_check::nll::constraint_set::ConstraintSet;
1314
use rustc::hir::def_id::DefId;
1415
use rustc::infer::canonical::QueryRegionConstraint;
1516
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
@@ -24,7 +25,6 @@ use rustc::mir::{
2425
use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
2526
use rustc::util::common::{self, ErrorReported};
2627
use rustc_data_structures::bitvec::BitVector;
27-
use rustc_data_structures::fx::FxHashSet;
2828
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
2929
use std::fmt;
3030
use std::rc::Rc;
@@ -66,8 +66,7 @@ pub struct RegionInferenceContext<'tcx> {
6666
dependency_map: Option<IndexVec<RegionVid, Option<ConstraintIndex>>>,
6767

6868
/// The constraints we have accumulated and used during solving.
69-
constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
70-
seen_constraints: FxHashSet<(RegionVid, RegionVid)>,
69+
constraints: ConstraintSet,
7170

7271
/// Type constraints that we check after solving.
7372
type_tests: Vec<TypeTest<'tcx>>,
@@ -146,7 +145,7 @@ pub struct OutlivesConstraint {
146145
}
147146

148147
impl OutlivesConstraint {
149-
fn dedup_key(&self) -> (RegionVid, RegionVid) {
148+
pub fn dedup_key(&self) -> (RegionVid, RegionVid) {
150149
(self.sup, self.sub)
151150
}
152151
}
@@ -251,11 +250,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
251250
var_infos: VarInfos,
252251
universal_regions: UniversalRegions<'tcx>,
253252
mir: &Mir<'tcx>,
254-
mut outlives_constraints: Vec<OutlivesConstraint>,
253+
outlives_constraints: ConstraintSet,
255254
type_tests: Vec<TypeTest<'tcx>>,
256255
) -> Self {
257256
// The `next` field should not yet have been initialized:
258-
debug_assert!(outlives_constraints.iter().all(|c| c.next.is_none()));
257+
debug_assert!(outlives_constraints.iner().iter().all(|c| c.next.is_none()));
259258

260259
let num_region_variables = var_infos.len();
261260
let num_universal_regions = universal_regions.len();
@@ -268,18 +267,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
268267
.map(|info| RegionDefinition::new(info.origin))
269268
.collect();
270269

271-
let mut seen_constraints: FxHashSet<(RegionVid, RegionVid)> = Default::default();
272-
273-
outlives_constraints.retain(|c| c.sup != c.sub && seen_constraints.insert(c.dedup_key()));
274-
275270
let mut result = Self {
276271
definitions,
277272
elements: elements.clone(),
278273
liveness_constraints: RegionValues::new(elements, num_region_variables),
279274
inferred_values: None,
280275
dependency_map: None,
281-
constraints: IndexVec::from_raw(outlives_constraints),
282-
seen_constraints,
276+
constraints: outlives_constraints,
283277
type_tests,
284278
universal_regions,
285279
};
@@ -405,7 +399,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
405399
sub: RegionVid,
406400
point: Location,
407401
) {
408-
self.add_outlives_iner(OutlivesConstraint {
402+
assert!(self.inferred_values.is_none(), "values already inferred");
403+
self.constraints.push(OutlivesConstraint {
409404
span,
410405
sup,
411406
sub,
@@ -414,22 +409,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
414409
})
415410
}
416411

417-
/// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
418-
fn add_outlives_iner(
419-
&mut self,
420-
outlives_constraint: OutlivesConstraint
421-
) {
422-
debug!("add_outlives({:?}: {:?} @ {:?}", outlives_constraint.sup, outlives_constraint.sub, outlives_constraint.point);
423-
assert!(self.inferred_values.is_none(), "values already inferred");
424-
if outlives_constraint.sup == outlives_constraint.sub {
425-
// 'a: 'a is pretty uninteresting
426-
return;
427-
}
428-
if self.seen_constraints.insert(outlives_constraint.dedup_key()) {
429-
self.constraints.push(outlives_constraint);
430-
}
431-
}
432-
433412
/// Perform region inference and report errors if we see any
434413
/// unsatisfiable constraints. If this is a closure, returns the
435414
/// region requirements to propagate to our creator, if any.
@@ -497,7 +476,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
497476
fn compute_region_values(&self, _mir: &Mir<'tcx>) -> RegionValues {
498477
debug!("compute_region_values()");
499478
debug!("compute_region_values: constraints={:#?}", {
500-
let mut constraints: Vec<_> = self.constraints.iter().collect();
479+
let mut constraints: Vec<_> = self.constraints.iner().iter().collect();
501480
constraints.sort();
502481
constraints
503482
});
@@ -509,7 +488,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
509488
let dependency_map = self.dependency_map.as_ref().unwrap();
510489

511490
// Constraints that may need to be repropagated (initially all):
512-
let mut dirty_list: Vec<_> = self.constraints.indices().collect();
491+
let mut dirty_list: Vec<_> = self.constraints.iner().indices().collect();
513492

514493
// Set to 0 for each constraint that is on the dirty list:
515494
let mut clean_bit_vec = BitVector::new(dirty_list.len());
@@ -518,7 +497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
518497
while let Some(constraint_idx) = dirty_list.pop() {
519498
clean_bit_vec.insert(constraint_idx.index());
520499

521-
let constraint = &self.constraints[constraint_idx];
500+
let constraint = &self.constraints.iner()[constraint_idx];
522501
debug!("propagate_constraints: constraint={:?}", constraint);
523502

524503
if inferred_values.add_region(constraint.sup, constraint.sub) {
@@ -530,7 +509,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
530509
if clean_bit_vec.remove(dep_idx.index()) {
531510
dirty_list.push(dep_idx);
532511
}
533-
opt_dep_idx = self.constraints[dep_idx].next;
512+
opt_dep_idx = self.constraints.iner()[dep_idx].next;
534513
}
535514
}
536515

@@ -547,7 +526,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
547526
fn build_dependency_map(&mut self) -> IndexVec<RegionVid, Option<ConstraintIndex>> {
548527
let mut map = IndexVec::from_elem(None, &self.definitions);
549528

550-
for (idx, constraint) in self.constraints.iter_enumerated_mut().rev() {
529+
for (idx, constraint) in self.constraints.iner_mut().iter_enumerated_mut().rev() {
551530
let mut head = &mut map[constraint.sub];
552531
debug_assert!(constraint.next.is_none());
553532
constraint.next = *head;
@@ -995,7 +974,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
995974
);
996975

997976
let blame_index = self.blame_constraint(longer_fr, shorter_fr);
998-
let blame_span = self.constraints[blame_index].span;
977+
let blame_span = self.constraints.iner()[blame_index].span;
999978

1000979
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
1001980
// Shrink `fr` until we find a non-local region (if we do).
@@ -1086,7 +1065,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
10861065
// - `fr1: X` transitively
10871066
// - and `Y` is live at `elem`
10881067
let index = self.blame_constraint(fr1, elem);
1089-
let region_sub = self.constraints[index].sub;
1068+
let region_sub = self.constraints.iner()[index].sub;
10901069

10911070
// then return why `Y` was live at `elem`
10921071
self.liveness_constraints.cause(region_sub, elem)
@@ -1107,6 +1086,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11071086
// of dependencies, which doesn't account for the locations of
11081087
// contraints at all. But it will do for now.
11091088
let relevant_constraint = self.constraints
1089+
.iner()
11101090
.iter_enumerated()
11111091
.filter_map(|(i, constraint)| {
11121092
if !self.liveness_constraints.contains(constraint.sub, elem) {
@@ -1142,7 +1122,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11421122

11431123
while changed {
11441124
changed = false;
1145-
for constraint in &self.constraints {
1125+
for constraint in self.constraints.iner() {
11461126
if let Some(n) = result_set[constraint.sup] {
11471127
let m = n + 1;
11481128
if result_set[constraint.sub]

src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use borrow_check::nll::facts::AllFacts;
1313
use borrow_check::nll::region_infer::{OutlivesConstraint, RegionTest, TypeTest};
1414
use borrow_check::nll::type_check::Locations;
1515
use borrow_check::nll::universal_regions::UniversalRegions;
16+
use borrow_check::nll::constraint_set::ConstraintSet;
1617
use rustc::infer::canonical::QueryRegionConstraint;
1718
use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
1819
use rustc::infer::region_constraints::{GenericKind, VerifyBound};
@@ -31,7 +32,7 @@ crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
3132
implicit_region_bound: Option<ty::Region<'tcx>>,
3233
param_env: ty::ParamEnv<'tcx>,
3334
locations: Locations,
34-
outlives_constraints: &'a mut Vec<OutlivesConstraint>,
35+
outlives_constraints: &'a mut ConstraintSet,
3536
type_tests: &'a mut Vec<TypeTest<'tcx>>,
3637
all_facts: &'a mut Option<AllFacts>,
3738
}
@@ -46,7 +47,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
4647
implicit_region_bound: Option<ty::Region<'tcx>>,
4748
param_env: ty::ParamEnv<'tcx>,
4849
locations: Locations,
49-
outlives_constraints: &'a mut Vec<OutlivesConstraint>,
50+
outlives_constraints: &'a mut ConstraintSet,
5051
type_tests: &'a mut Vec<TypeTest<'tcx>>,
5152
all_facts: &'a mut Option<AllFacts>,
5253
) -> Self {

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
#![allow(unreachable_code)]
1313

1414
use borrow_check::location::LocationTable;
15+
use borrow_check::nll::constraint_set::ConstraintSet;
1516
use borrow_check::nll::facts::AllFacts;
1617
use borrow_check::nll::region_infer::Cause;
17-
use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, OutlivesConstraint, TypeTest};
18+
use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
1819
use borrow_check::nll::universal_regions::UniversalRegions;
1920
use dataflow::move_paths::MoveData;
2021
use dataflow::FlowAtLocation;
@@ -621,7 +622,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
621622
/// hence it must report on their liveness constraints.
622623
crate liveness_set: Vec<(ty::Region<'tcx>, Location, Cause)>,
623624

624-
crate outlives_constraints: Vec<OutlivesConstraint>,
625+
crate outlives_constraints: ConstraintSet,
625626

626627
crate type_tests: Vec<TypeTest<'tcx>>,
627628
}

0 commit comments

Comments
 (0)