Skip to content

Commit ef9cb23

Browse files
committed
Use an enum for SCC representatives, plus other code review
1 parent dbc6b67 commit ef9cb23

File tree

2 files changed

+70
-51
lines changed

2 files changed

+70
-51
lines changed

compiler/rustc_borrowck/src/eliminate_placeholders.rs

Lines changed: 27 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::consumers::OutlivesConstraint;
1818
use crate::diagnostics::UniverseInfo;
1919
use crate::member_constraints::MemberConstraintSet;
2020
use crate::region_infer::values::{LivenessValues, PlaceholderIndices};
21-
use crate::region_infer::{ConstraintSccs, RegionDefinition, TypeTest};
21+
use crate::region_infer::{ConstraintSccs, RegionDefinition, Representative, TypeTest};
2222
use crate::ty::VarianceDiagInfo;
2323
use crate::type_check::free_region_relations::UniversalRegionRelations;
2424
use crate::type_check::{Locations, MirTypeckRegionConstraints};
@@ -76,36 +76,23 @@ pub(crate) struct RegionTracker {
7676
/// The smallest universe index reachable form the nodes of this SCC.
7777
min_reachable_universe: UniverseIndex,
7878

79-
/// The representative Region Variable Id for this SCC. We prefer
80-
/// placeholders over existentially quantified variables, otherwise
81-
/// it's the one with the smallest Region Variable ID.
82-
pub(crate) representative: RegionVid,
83-
84-
/// Is the current representative a placeholder?
85-
representative_is_placeholder: bool,
86-
87-
/// Is the current representative existentially quantified?
88-
representative_is_existential: bool,
79+
/// The representative Region Variable Id for this SCC.
80+
pub(crate) representative: Representative,
8981
}
9082

9183
impl RegionTracker {
9284
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
93-
let (representative_is_placeholder, representative_is_existential) = match definition.origin
94-
{
95-
NllRegionVariableOrigin::FreeRegion => (false, false),
96-
NllRegionVariableOrigin::Placeholder(_) => (true, false),
97-
NllRegionVariableOrigin::Existential { .. } => (false, true),
98-
};
99-
10085
let placeholder_universe =
101-
if representative_is_placeholder { definition.universe } else { UniverseIndex::ROOT };
86+
if matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_)) {
87+
definition.universe
88+
} else {
89+
UniverseIndex::ROOT
90+
};
10291

10392
Self {
10493
max_placeholder_universe_reached: placeholder_universe,
10594
min_reachable_universe: definition.universe,
106-
representative: rvid,
107-
representative_is_placeholder,
108-
representative_is_existential,
95+
representative: Representative::new(rvid, definition),
10996
}
11097
}
11198

@@ -139,21 +126,10 @@ impl RegionTracker {
139126
}
140127

141128
impl scc::Annotation for RegionTracker {
142-
fn merge_scc(mut self, mut other: Self) -> Self {
143-
// Prefer any placeholder over any existential
144-
if other.representative_is_placeholder && self.representative_is_existential {
145-
other.merge_min_max_seen(&self);
146-
return other;
147-
}
148-
149-
if self.representative_is_placeholder && other.representative_is_existential
150-
|| (self.representative <= other.representative)
151-
{
152-
self.merge_min_max_seen(&other);
153-
return self;
154-
}
155-
other.merge_min_max_seen(&self);
156-
other
129+
fn merge_scc(mut self, other: Self) -> Self {
130+
self.representative = self.representative.merge_scc(other.representative);
131+
self.merge_min_max_seen(&other);
132+
self
157133
}
158134

159135
fn merge_reached(mut self, other: Self) -> Self {
@@ -267,13 +243,14 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
267243
)
268244
};
269245

246+
let mut scc_annotations = SccAnnotations::init(&definitions);
247+
let constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
248+
270249
// This code structure is a bit convoluted because it allows for a planned
271250
// future change where the early return here has a different type of annotation
272251
// that does much less work.
273252
if !has_placeholders {
274253
debug!("No placeholder regions found; skipping rewriting logic!");
275-
let mut scc_annotations = SccAnnotations::init(&definitions);
276-
let constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
277254

278255
return LoweredConstraints {
279256
type_tests,
@@ -289,13 +266,14 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
289266
}
290267
debug!("Placeholders present; activating placeholder handling logic!");
291268

292-
let mut annotations = SccAnnotations::init(&definitions);
293-
let sccs = compute_sccs(&outlives_constraints, &mut annotations);
294-
295-
let outlives_static =
296-
rewrite_outlives(&sccs, &annotations, fr_static, &mut outlives_constraints);
269+
let outlives_static = rewrite_placeholder_outlives(
270+
&constraint_sccs,
271+
&scc_annotations,
272+
fr_static,
273+
&mut outlives_constraints,
274+
);
297275

298-
let (sccs, scc_annotations) = if !outlives_static.is_empty() {
276+
let (constraint_sccs, scc_annotations) = if !outlives_static.is_empty() {
299277
debug!("The following SCCs had :'static constraints added: {:?}", outlives_static);
300278
let mut annotations = SccAnnotations::init(&definitions);
301279

@@ -307,11 +285,11 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
307285
} else {
308286
// If we didn't add any back-edges; no more work needs doing
309287
debug!("No constraints rewritten!");
310-
(sccs, annotations.scc_to_annotation)
288+
(constraint_sccs, scc_annotations.scc_to_annotation)
311289
};
312290

313291
LoweredConstraints {
314-
constraint_sccs: sccs,
292+
constraint_sccs,
315293
definitions,
316294
scc_annotations,
317295
member_constraints,
@@ -323,7 +301,7 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
323301
}
324302
}
325303

326-
fn rewrite_outlives<'tcx>(
304+
fn rewrite_placeholder_outlives<'tcx>(
327305
sccs: &Sccs<RegionVid, ConstraintSccIndex>,
328306
annotations: &SccAnnotations<'_, '_, RegionTracker>,
329307
fr_static: RegionVid,
@@ -356,7 +334,7 @@ fn rewrite_outlives<'tcx>(
356334
// outlive static.
357335
outlives_static.insert(scc);
358336
let scc_representative_outlives_static = OutlivesConstraint {
359-
sup: annotation.representative,
337+
sup: annotation.representative.rvid(),
360338
sub: fr_static,
361339
category: ConstraintCategory::IllegalUniverse,
362340
locations: Locations::All(rustc_span::DUMMY_SP),

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::rc::Rc;
44
use rustc_data_structures::binary_search_util;
55
use rustc_data_structures::frozen::Frozen;
66
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
7-
use rustc_data_structures::graph::scc::Sccs;
7+
use rustc_data_structures::graph::scc::{self, Sccs};
88
use rustc_errors::Diag;
99
use rustc_hir::def_id::CRATE_DEF_ID;
1010
use rustc_index::IndexVec;
@@ -50,6 +50,47 @@ mod reverse_sccs;
5050

5151
pub(crate) mod values;
5252

53+
/// The representative region variable for an SCC, tagged by its origin.
54+
/// We prefer placeholders over existentially quantified variables, otherwise
55+
/// it's the one with the smallest Region Variable ID. In other words,
56+
/// the order of this enumeration really matters!
57+
#[derive(Copy, Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
58+
pub(crate) enum Representative {
59+
FreeRegion(RegionVid),
60+
Placeholder(RegionVid),
61+
Existential(RegionVid),
62+
}
63+
64+
impl Representative {
65+
pub(crate) fn rvid(self) -> RegionVid {
66+
match self {
67+
Representative::FreeRegion(region_vid)
68+
| Representative::Placeholder(region_vid)
69+
| Representative::Existential(region_vid) => region_vid,
70+
}
71+
}
72+
73+
pub(crate) fn new(r: RegionVid, definition: &RegionDefinition<'_>) -> Self {
74+
match definition.origin {
75+
NllRegionVariableOrigin::FreeRegion => Representative::FreeRegion(r),
76+
NllRegionVariableOrigin::Placeholder(_) => Representative::Placeholder(r),
77+
NllRegionVariableOrigin::Existential { .. } => Representative::Existential(r),
78+
}
79+
}
80+
}
81+
82+
impl scc::Annotation for Representative {
83+
fn merge_scc(self, other: Self) -> Self {
84+
// Just pick the smallest one. Note that we order by tag first!
85+
std::cmp::min(self, other)
86+
}
87+
88+
// For reachability, we do nothing since the representative doesn't change.
89+
fn merge_reached(self, _other: Self) -> Self {
90+
self
91+
}
92+
}
93+
5394
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>;
5495

5596
pub struct RegionInferenceContext<'tcx> {
@@ -2086,7 +2127,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
20862127
/// they *must* be equal (though not having the same repr does not
20872128
/// mean they are unequal).
20882129
fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid {
2089-
self.scc_annotations[scc].representative
2130+
self.scc_annotations[scc].representative.rvid()
20902131
}
20912132

20922133
pub(crate) fn liveness_constraints(&self) -> &LivenessValues {

0 commit comments

Comments
 (0)