Skip to content

Commit 793f502

Browse files
committed
Refactor region constraint search into its own module
Region constraint search is now used in multiple places. This PR moves it into `rustc_borrowck::constraints::graph`, since it uses the Region graph for searching. Use blame constraint in outlives static edges
1 parent 9a1face commit 793f502

File tree

2 files changed

+557
-24
lines changed

2 files changed

+557
-24
lines changed

compiler/rustc_borrowck/src/eliminate_placeholders.rs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ impl RegionTracker {
153153

154154
Self {
155155
// The largest reachable universe from a rvid is its
156-
// declared largest reachable one.
156+
// declared one.
157157
min_max_universe_reached: (definition.universe, rvid),
158158
reachable_placeholders,
159159
representative: Representative::new(rvid, definition),
@@ -175,17 +175,15 @@ impl RegionTracker {
175175
|| other.reachable_placeholders.can_be_named_by(self.max_nameable_universe())
176176
}
177177

178-
/// If this SCC reaches an universe that's too large, return it.
179-
fn reaches_too_large_universe(&self) -> Option<(RegionVid, UniverseIndex)> {
180-
let min_u = self.max_nameable_universe();
181-
178+
/// If this SCC reaches a placeholder it can't name, return it.
179+
fn unnameable_placeholder(&self) -> Option<(RegionVid, UniverseIndex)> {
182180
let PlaceholderReachability::Placeholders { max_universe: (max_u, max_u_rvid), .. } =
183181
self.reachable_placeholders
184182
else {
185183
return None;
186184
};
187185

188-
if min_u.can_name(max_u) {
186+
if self.max_nameable_universe().can_name(max_u) {
189187
return None;
190188
}
191189

@@ -216,7 +214,7 @@ impl scc::Annotation for RegionTracker {
216214
}
217215

218216
fn merge_reached(mut self, other: Self) -> Self {
219-
let already_has_placeholder_violation = self.reaches_too_large_universe().is_some();
217+
let already_has_unnameable_placeholder = self.unnameable_placeholder().is_some();
220218
self.min_max_universe_reached = pick_min_max_universe(self, other);
221219
// This detail is subtle. We stop early here, because there may be multiple
222220
// illegally reached regions, but they are not equally good as blame candidates.
@@ -227,8 +225,8 @@ impl scc::Annotation for RegionTracker {
227225
// FIXME: a potential optimisation if this is slow is to reimplement
228226
// this check as a boolean fuse, since it will idempotently turn
229227
// true once triggered and never go false again.
230-
if already_has_placeholder_violation {
231-
debug!("SCC already has a placeholder violation; no use looking for more!");
228+
if already_has_unnameable_placeholder {
229+
debug!("SCC already has an unnameable placeholder; no use looking for more!");
232230
self
233231
} else {
234232
self.reachable_placeholders =
@@ -426,40 +424,48 @@ fn rewrite_placeholder_outlives<'tcx>(
426424

427425
let annotation = &annotations[scc];
428426

429-
// Figure out if there is a universe violation in this SCC.
430-
// This can happen in two cases: either one of our placeholders
431-
// had its universe lowered from reaching a region with a lower universe,
432-
// (in which case we blame the lower universe's region), or because we reached
433-
// a larger universe (in which case we blame the larger universe's region).
434-
let Some((max_u_rvid, max_u)) = annotation.reaches_too_large_universe() else {
427+
let Some((max_u_rvid, max_u)) = annotation.unnameable_placeholder() else {
435428
continue;
436429
};
437430

438-
let min_u = annotation.max_nameable_universe();
439-
440431
debug!(
441-
"Universe {max_u:?} is too large for its SCC, represented by {:?}",
432+
"Placeholder universe {max_u:?} is too large for its SCC, represented by {:?}",
442433
annotation.representative
443434
);
435+
436+
// We only add one `r: 'static` constraint per SCC, where `r` is the SCC representative.
437+
// That constraint is annotated with some outlives relation `tries: unnameable` where
438+
// `unnameable` is unnameable from `tries` and there is a path in the constraint
439+
// graph between them.
440+
//
441+
// We prefer the representative as `tries` in all cases but one: where the problem
442+
// is that the SCC has had its universe lowered to accomodate some other region and
443+
// no longer can name its representative. In that case, we blame `r: low_u`, where `low_u`
444+
// cannot name `r` so that any explanation always starts with the SCC representative.
444445
let blame_to = if annotation.representative.rvid() == max_u_rvid {
445-
// We originally had a large enough universe to fit all our reachable
446-
// placeholders, but had it lowered because we also reached something
447-
// small-universed. In this case, that's to blame!
446+
// The SCC's representative is not nameable from some region
447+
// that ends up in the SCC.
448448
let small_universed_rvid = find_region(
449449
outlives_constraints,
450450
constraint_graph.get_or_init(|| outlives_constraints.graph(definitions.len())),
451451
definitions,
452452
max_u_rvid,
453-
|r: RegionVid| definitions[r].universe == min_u,
453+
|r: RegionVid| definitions[r].universe == annotation.max_nameable_universe(),
454454
fr_static,
455455
);
456-
debug!("{small_universed_rvid:?} lowered our universe to {min_u:?}");
456+
debug!(
457+
"{small_universed_rvid:?} lowered our universe to {:?}",
458+
annotation.max_nameable_universe()
459+
);
457460
small_universed_rvid
458461
} else {
459-
// The problem is that we, who have a small universe, reach a large one.
462+
// `max_u_rvid` is not nameable by the SCC's representative.
460463
max_u_rvid
461464
};
462465

466+
// FIXME: if we can extract a useful blame span here, future error
467+
// reporting and constraint search can be simplified. That does however
468+
463469
outlives_static.insert(scc);
464470
outlives_constraints.push(OutlivesConstraint {
465471
sup: annotation.representative.rvid(),

0 commit comments

Comments
 (0)