Skip to content

Commit 15c7e59

Browse files
committed
favor placeholders over existentials when choosing SCC representatives
... even when the existential has the least RegionVid. universal regions (of root universe) > placeholders > existentials The previous behavior, that chooses the minimal RegionVid index, naturally prefers universal regions over others because they always have the least RegionVids, but there was no guranteed ordering between placeholders and existentials.
1 parent ce91e46 commit 15c7e59

File tree

1 file changed

+20
-12
lines changed
  • compiler/rustc_borrowck/src/region_infer

1 file changed

+20
-12
lines changed

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,11 @@ pub struct RegionInferenceContext<'tcx> {
9595
/// visible from this index.
9696
scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
9797

98-
/// Contains a "representative" from each SCC. This will be the
99-
/// minimal RegionVid belonging to that universe. It is used as a
100-
/// kind of hacky way to manage checking outlives relationships,
98+
/// Contains the "representative" region of each SCC.
99+
/// It is defined as the one with the minimal RegionVid, favoring
100+
/// free regions, then placeholders, then existential regions.
101+
///
102+
/// It is a hacky way to manage checking regions for equality,
101103
/// since we can 'canonicalize' each region to the representative
102104
/// of its SCC and be sure that -- if they have the same repr --
103105
/// they *must* be equal (though not having the same repr does not
@@ -481,22 +483,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
481483
scc_universes
482484
}
483485

484-
/// For each SCC, we compute a unique `RegionVid` (in fact, the
485-
/// minimal one that belongs to the SCC). See
486+
/// For each SCC, we compute a unique `RegionVid`. See the
486487
/// `scc_representatives` field of `RegionInferenceContext` for
487488
/// more details.
488489
fn compute_scc_representatives(
489490
constraints_scc: &Sccs<RegionVid, ConstraintSccIndex>,
490491
definitions: &IndexSlice<RegionVid, RegionDefinition<'tcx>>,
491492
) -> IndexVec<ConstraintSccIndex, ty::RegionVid> {
492493
let num_sccs = constraints_scc.num_sccs();
493-
let next_region_vid = definitions.next_index();
494-
let mut scc_representatives = IndexVec::from_elem_n(next_region_vid, num_sccs);
495-
496-
for region_vid in definitions.indices() {
497-
let scc = constraints_scc.scc(region_vid);
498-
let prev_min = scc_representatives[scc];
499-
scc_representatives[scc] = region_vid.min(prev_min);
494+
let mut scc_representatives = IndexVec::from_elem_n(RegionVid::MAX, num_sccs);
495+
496+
// Iterate over all RegionVids *in-order* and pick the least RegionVid as the
497+
// representative of its SCC. This naturally prefers free regions over others.
498+
for (vid, def) in definitions.iter_enumerated() {
499+
let repr = &mut scc_representatives[constraints_scc.scc(vid)];
500+
if *repr == ty::RegionVid::MAX {
501+
*repr = vid;
502+
} else if matches!(def.origin, NllRegionVariableOrigin::Placeholder(_))
503+
&& matches!(definitions[*repr].origin, NllRegionVariableOrigin::Existential { .. })
504+
{
505+
// Pick placeholders over existentials even if they have a greater RegionVid.
506+
*repr = vid;
507+
}
500508
}
501509

502510
scc_representatives

0 commit comments

Comments
 (0)