about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAmanda Stjerna <amanda.stjerna@it.uu.se>2025-05-02 10:50:03 +0200
committerAmanda Stjerna <amanda.stjerna@it.uu.se>2025-06-04 13:26:08 +0200
commitf455c4fc39bcc04d104bc440ebc1c23f183f20f9 (patch)
tree117a2aa35fba962e88d70f808fb65c6ad22d06d8
parentaca36fd12a3277ce17eb94e4e89567843bf137f7 (diff)
downloadrust-f455c4fc39bcc04d104bc440ebc1c23f183f20f9.tar.gz
rust-f455c4fc39bcc04d104bc440ebc1c23f183f20f9.zip
Use an enum for SCC representatives, plus other code review
Co-authored-by: lcnr <rust@lcnr.de>
-rw-r--r--compiler/rustc_borrowck/src/handle_placeholders.rs (renamed from compiler/rustc_borrowck/src/eliminate_placeholders.rs)165
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/nll.rs4
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/dump_mir.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs90
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
7 files changed, 131 insertions, 136 deletions
diff --git a/compiler/rustc_borrowck/src/eliminate_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs
index e8e1acbd7a5..aaaf2f45c86 100644
--- a/compiler/rustc_borrowck/src/eliminate_placeholders.rs
+++ b/compiler/rustc_borrowck/src/handle_placeholders.rs
@@ -1,14 +1,13 @@
 //! Logic for lowering higher-kinded outlives constraints
 //! (with placeholders and universes) and turn them into regular
 //! outlives constraints.
-//!
-//! This logic is provisional and should be removed once the trait
-//! solver can handle this kind of constraint.
+
 use rustc_data_structures::frozen::Frozen;
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::graph::scc;
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_index::IndexVec;
+use rustc_infer::infer::RegionVariableOrigin;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{RegionVid, UniverseIndex};
 use tracing::debug;
@@ -18,7 +17,7 @@ use crate::consumers::OutlivesConstraint;
 use crate::diagnostics::UniverseInfo;
 use crate::member_constraints::MemberConstraintSet;
 use crate::region_infer::values::{LivenessValues, PlaceholderIndices};
-use crate::region_infer::{ConstraintSccs, RegionDefinition, TypeTest};
+use crate::region_infer::{ConstraintSccs, RegionDefinition, Representative, TypeTest};
 use crate::ty::VarianceDiagInfo;
 use crate::type_check::free_region_relations::UniversalRegionRelations;
 use crate::type_check::{Locations, MirTypeckRegionConstraints};
@@ -32,7 +31,7 @@ pub(crate) struct LoweredConstraints<'tcx> {
     pub(crate) definitions: Frozen<IndexVec<RegionVid, RegionDefinition<'tcx>>>,
     pub(crate) scc_annotations: IndexVec<ConstraintSccIndex, RegionTracker>,
     pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
-    pub(crate) outlives_constraints: OutlivesConstraintSet<'tcx>,
+    pub(crate) outlives_constraints: Frozen<OutlivesConstraintSet<'tcx>>,
     pub(crate) type_tests: Vec<TypeTest<'tcx>>,
     pub(crate) liveness_constraints: LivenessValues,
     pub(crate) universe_causes: FxIndexMap<UniverseIndex, UniverseInfo<'tcx>>,
@@ -73,45 +72,35 @@ pub(crate) struct RegionTracker {
     /// This includes placeholders within this SCC.
     max_placeholder_universe_reached: UniverseIndex,
 
-    /// The smallest universe index reachable form the nodes of this SCC.
-    min_reachable_universe: UniverseIndex,
-
-    /// The representative Region Variable Id for this SCC. We prefer
-    /// placeholders over existentially quantified variables, otherwise
-    ///  it's the one with the smallest Region Variable ID.
-    pub(crate) representative: RegionVid,
-
-    /// Is the current representative a placeholder?
-    representative_is_placeholder: bool,
+    /// The largest universe nameable from this SCC.
+    /// It is the smallest nameable universes of all
+    /// existential regions reachable from it.
+    max_nameable_universe: UniverseIndex,
 
-    /// Is the current representative existentially quantified?
-    representative_is_existential: bool,
+    /// The representative Region Variable Id for this SCC.
+    pub(crate) representative: Representative,
 }
 
 impl RegionTracker {
     pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
-        let (representative_is_placeholder, representative_is_existential) = match definition.origin
-        {
-            NllRegionVariableOrigin::FreeRegion => (false, false),
-            NllRegionVariableOrigin::Placeholder(_) => (true, false),
-            NllRegionVariableOrigin::Existential { .. } => (false, true),
-        };
-
         let placeholder_universe =
-            if representative_is_placeholder { definition.universe } else { UniverseIndex::ROOT };
+            if matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_)) {
+                definition.universe
+            } else {
+                UniverseIndex::ROOT
+            };
 
         Self {
             max_placeholder_universe_reached: placeholder_universe,
-            min_reachable_universe: definition.universe,
-            representative: rvid,
-            representative_is_placeholder,
-            representative_is_existential,
+            max_nameable_universe: definition.universe,
+            representative: Representative::new(rvid, definition),
         }
     }
 
-    /// The smallest-indexed universe reachable from and/or in this SCC.
-    pub(crate) fn min_universe(self) -> UniverseIndex {
-        self.min_reachable_universe
+    /// The largest universe this SCC can name. It's the smallest
+    /// largest nameable uninverse of any reachable region.
+    pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
+        self.max_nameable_universe
     }
 
     fn merge_min_max_seen(&mut self, other: &Self) {
@@ -120,40 +109,29 @@ impl RegionTracker {
             other.max_placeholder_universe_reached,
         );
 
-        self.min_reachable_universe =
-            std::cmp::min(self.min_reachable_universe, other.min_reachable_universe);
+        self.max_nameable_universe =
+            std::cmp::min(self.max_nameable_universe, other.max_nameable_universe);
     }
 
     /// Returns `true` if during the annotated SCC reaches a placeholder
-    /// with a universe larger than the smallest reachable one, `false` otherwise.
+    /// with a universe larger than the smallest nameable universe of any
+    /// reachable existential region.
     pub(crate) fn has_incompatible_universes(&self) -> bool {
-        self.min_universe().cannot_name(self.max_placeholder_universe_reached)
+        self.max_nameable_universe().cannot_name(self.max_placeholder_universe_reached)
     }
 
-    /// Determine if the tracked universes of the two SCCs
-    /// are compatible.
+    /// Determine if the tracked universes of the two SCCs are compatible.
     pub(crate) fn universe_compatible_with(&self, other: Self) -> bool {
-        self.min_universe().can_name(other.min_universe())
-            || self.min_universe().can_name(other.max_placeholder_universe_reached)
+        self.max_nameable_universe().can_name(other.max_nameable_universe())
+            || self.max_nameable_universe().can_name(other.max_placeholder_universe_reached)
     }
 }
 
 impl scc::Annotation for RegionTracker {
-    fn merge_scc(mut self, mut other: Self) -> Self {
-        // Prefer any placeholder over any existential
-        if other.representative_is_placeholder && self.representative_is_existential {
-            other.merge_min_max_seen(&self);
-            return other;
-        }
-
-        if self.representative_is_placeholder && other.representative_is_existential
-            || (self.representative <= other.representative)
-        {
-            self.merge_min_max_seen(&other);
-            return self;
-        }
-        other.merge_min_max_seen(&self);
-        other
+    fn merge_scc(mut self, other: Self) -> Self {
+        self.representative = self.representative.merge_scc(other.representative);
+        self.merge_min_max_seen(&other);
+        self
     }
 
     fn merge_reached(mut self, other: Self) -> Self {
@@ -164,7 +142,7 @@ impl scc::Annotation for RegionTracker {
 }
 
 /// Determines if the region variable definitions contain
-/// placeholers, and compute them for later use.
+/// placeholders, and compute them for later use.
 fn region_definitions<'tcx>(
     universal_regions: &UniversalRegions<'tcx>,
     infcx: &BorrowckInferCtxt<'tcx>,
@@ -177,12 +155,19 @@ fn region_definitions<'tcx>(
     let mut has_placeholders = false;
 
     for info in var_infos.iter() {
-        let definition = RegionDefinition::new(info);
-        has_placeholders |= matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_));
+        let origin = match info.origin {
+            RegionVariableOrigin::Nll(origin) => origin,
+            _ => NllRegionVariableOrigin::Existential { from_forall: false },
+        };
+
+        let definition = RegionDefinition { origin, universe: info.universe, external_name: None };
+
+        has_placeholders |= matches!(origin, NllRegionVariableOrigin::Placeholder(_));
         definitions.push(definition);
     }
 
     // Add external names from universal regions in fun function definitions.
+    // FIXME: this two-step method is annoying, but I don't know how to avoid it.
     for (external_name, variable) in universal_regions.named_universal_regions_iter() {
         debug!("region {:?} has external name {:?}", variable, external_name);
         definitions[variable].external_name = Some(external_name);
@@ -190,29 +175,19 @@ fn region_definitions<'tcx>(
     (Frozen::freeze(definitions), has_placeholders)
 }
 
-/// This method handles Universe errors by rewriting the constraint
+/// This method handles placeholders by rewriting the constraint
 /// graph. For each strongly connected component in the constraint
 /// graph such that there is a series of constraints
 ///    A: B: C: ... : X  where
-/// A's universe is smaller than X's and A is a placeholder,
+/// A contains a placeholder whose universe cannot be named by X,
 /// add a constraint that A: 'static. This is a safe upper bound
 /// in the face of borrow checker/trait solver limitations that will
 /// eventually go away.
 ///
 /// For a more precise definition, see the documentation for
-/// [`RegionTracker`] and its methods!.
-///
-/// Since universes can also be involved in errors (if one placeholder
-/// transitively outlives another), this function also flags those.
-///
-/// Additionally, it similarly rewrites type-tests.
-///
-/// This edge case used to be handled during constraint propagation
-/// by iterating over the strongly connected components in the constraint
-/// graph while maintaining a set of bookkeeping mappings similar
-/// to what is stored in `RegionTracker` and manually adding 'sttaic as
-/// needed.
+/// [`RegionTracker`] and its methods!
 ///
+/// This edge case used to be handled during constraint propagation.
 /// It was rewritten as part of the Polonius project with the goal of moving
 /// higher-kindedness concerns out of the path of the borrow checker,
 /// for two reasons:
@@ -228,7 +203,7 @@ fn region_definitions<'tcx>(
 /// This code is a stop-gap measure in preparation for the future trait solver.
 ///
 /// Every constraint added by this method is an internal `IllegalUniverse` constraint.
-pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
+pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
     constraints: MirTypeckRegionConstraints<'tcx>,
     universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
     infcx: &BorrowckInferCtxt<'tcx>,
@@ -267,13 +242,14 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
             )
         };
 
+    let mut scc_annotations = SccAnnotations::init(&definitions);
+    let constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
+
     // This code structure is a bit convoluted because it allows for a planned
     // future change where the early return here has a different type of annotation
     // that does much less work.
     if !has_placeholders {
         debug!("No placeholder regions found; skipping rewriting logic!");
-        let mut scc_annotations = SccAnnotations::init(&definitions);
-        let constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
 
         return LoweredConstraints {
             type_tests,
@@ -281,7 +257,7 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
             constraint_sccs,
             scc_annotations: scc_annotations.scc_to_annotation,
             definitions,
-            outlives_constraints,
+            outlives_constraints: Frozen::freeze(outlives_constraints),
             liveness_constraints,
             universe_causes,
             placeholder_indices,
@@ -289,14 +265,14 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
     }
     debug!("Placeholders present; activating placeholder handling logic!");
 
-    let mut annotations = SccAnnotations::init(&definitions);
-    let sccs = compute_sccs(&outlives_constraints, &mut annotations);
-
-    let outlives_static =
-        rewrite_outlives(&sccs, &annotations, fr_static, &mut outlives_constraints);
+    let added_constraints = rewrite_placeholder_outlives(
+        &constraint_sccs,
+        &scc_annotations,
+        fr_static,
+        &mut outlives_constraints,
+    );
 
-    let (sccs, scc_annotations) = if !outlives_static.is_empty() {
-        debug!("The following SCCs had :'static constraints added: {:?}", outlives_static);
+    let (constraint_sccs, scc_annotations) = if added_constraints {
         let mut annotations = SccAnnotations::init(&definitions);
 
         // We changed the constraint set and so must recompute SCCs.
@@ -307,15 +283,15 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
     } else {
         // If we didn't add any back-edges; no more work needs doing
         debug!("No constraints rewritten!");
-        (sccs, annotations.scc_to_annotation)
+        (constraint_sccs, scc_annotations.scc_to_annotation)
     };
 
     LoweredConstraints {
-        constraint_sccs: sccs,
+        constraint_sccs,
         definitions,
         scc_annotations,
         member_constraints,
-        outlives_constraints,
+        outlives_constraints: Frozen::freeze(outlives_constraints),
         type_tests,
         liveness_constraints,
         universe_causes,
@@ -323,15 +299,15 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
     }
 }
 
-fn rewrite_outlives<'tcx>(
+fn rewrite_placeholder_outlives<'tcx>(
     sccs: &Sccs<RegionVid, ConstraintSccIndex>,
     annotations: &SccAnnotations<'_, '_, RegionTracker>,
     fr_static: RegionVid,
     outlives_constraints: &mut OutlivesConstraintSet<'tcx>,
-) -> FxHashSet<ConstraintSccIndex> {
-    // Changed to `true` if we added any constraints to `self` and need to
+) -> bool {
+    // Changed to `true` if we added any constraints and need to
     // recompute SCCs.
-    let mut outlives_static = FxHashSet::default();
+    let mut added_constraints = false;
 
     let annotations = &annotations.scc_to_annotation;
 
@@ -354,9 +330,8 @@ fn rewrite_outlives<'tcx>(
             // needed for correctness, since an SCC upstream of another with
             // a universe violation will "infect" its downstream SCCs to also
             // outlive static.
-            outlives_static.insert(scc);
             let scc_representative_outlives_static = OutlivesConstraint {
-                sup: annotation.representative,
+                sup: annotation.representative.rvid(),
                 sub: fr_static,
                 category: ConstraintCategory::IllegalUniverse,
                 locations: Locations::All(rustc_span::DUMMY_SP),
@@ -365,7 +340,9 @@ fn rewrite_outlives<'tcx>(
                 from_closure: false,
             };
             outlives_constraints.push(scc_representative_outlives_static);
+            added_constraints = true;
+            debug!("Added {:?}: 'static!", annotation.representative.rvid());
         }
     }
-    outlives_static
+    added_constraints
 }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index edf5494e886..8c4d5c0debe 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -75,7 +75,7 @@ mod constraints;
 mod dataflow;
 mod def_use;
 mod diagnostics;
-mod eliminate_placeholders;
+mod handle_placeholders;
 mod member_constraints;
 mod nll;
 mod path_utils;
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 9b1a5df8d06..66ab39476b1 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -22,7 +22,7 @@ use tracing::{debug, instrument};
 use crate::borrow_set::BorrowSet;
 use crate::consumers::ConsumerOptions;
 use crate::diagnostics::RegionErrors;
-use crate::eliminate_placeholders::rewrite_higher_kinded_outlives_as_constraints;
+use crate::handle_placeholders::compute_sccs_applying_placeholder_outlives_constraints;
 use crate::polonius::PoloniusDiagnosticsContext;
 use crate::polonius::legacy::{
     PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
@@ -118,7 +118,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         Rc::clone(&location_map),
     );
 
-    let lowered_constraints = rewrite_higher_kinded_outlives_as_constraints(
+    let lowered_constraints = compute_sccs_applying_placeholder_outlives_constraints(
         constraints,
         &universal_region_relations,
         infcx,
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
index 67da43ca578..05fd6e39476 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs
@@ -13,7 +13,7 @@ use tracing::debug;
 
 use crate::borrow_set::BorrowSet;
 use crate::constraints::OutlivesConstraint;
-use crate::eliminate_placeholders::LoweredConstraints;
+use crate::handle_placeholders::LoweredConstraints;
 use crate::type_check::free_region_relations::UniversalRegionRelations;
 use crate::universal_regions::UniversalRegions;
 
diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
index ef3d6309c19..a9ab30fd8fa 100644
--- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
+++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
@@ -46,7 +46,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 "| {r:rw$?} | {ui:4?} | {v}",
                 r = region,
                 rw = REGION_WIDTH,
-                ui = self.region_universe(region),
+                ui = self.max_nameable_universe(self.constraint_sccs.scc(region)),
                 v = self.region_value_str(region),
             )?;
         }
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index cfad071460b..dcb09d5be14 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -4,15 +4,13 @@ use std::rc::Rc;
 use rustc_data_structures::binary_search_util;
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_data_structures::graph::scc::Sccs;
+use rustc_data_structures::graph::scc::{self, Sccs};
 use rustc_errors::Diag;
 use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_index::IndexVec;
 use rustc_infer::infer::outlives::test_type_match;
-use rustc_infer::infer::region_constraints::{
-    GenericKind, RegionVariableInfo, VerifyBound, VerifyIfEq,
-};
-use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
+use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound, VerifyIfEq};
+use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_middle::bug;
 use rustc_middle::mir::{
     AnnotationSource, BasicBlock, Body, ConstraintCategory, Local, Location, ReturnConstraint,
@@ -29,7 +27,7 @@ use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph};
 use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet};
 use crate::dataflow::BorrowIndex;
 use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo};
-use crate::eliminate_placeholders::{LoweredConstraints, RegionTracker};
+use crate::handle_placeholders::{LoweredConstraints, RegionTracker};
 use crate::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
 use crate::polonius::LiveLoans;
 use crate::polonius::legacy::PoloniusOutput;
@@ -50,6 +48,47 @@ mod reverse_sccs;
 
 pub(crate) mod values;
 
+/// The representative region variable for an SCC, tagged by its origin.
+/// We prefer placeholders over existentially quantified variables, otherwise
+/// it's the one with the smallest Region Variable ID. In other words,
+/// the order of this enumeration really matters!
+#[derive(Copy, Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
+pub(crate) enum Representative {
+    FreeRegion(RegionVid),
+    Placeholder(RegionVid),
+    Existential(RegionVid),
+}
+
+impl Representative {
+    pub(crate) fn rvid(self) -> RegionVid {
+        match self {
+            Representative::FreeRegion(region_vid)
+            | Representative::Placeholder(region_vid)
+            | Representative::Existential(region_vid) => region_vid,
+        }
+    }
+
+    pub(crate) fn new(r: RegionVid, definition: &RegionDefinition<'_>) -> Self {
+        match definition.origin {
+            NllRegionVariableOrigin::FreeRegion => Representative::FreeRegion(r),
+            NllRegionVariableOrigin::Placeholder(_) => Representative::Placeholder(r),
+            NllRegionVariableOrigin::Existential { .. } => Representative::Existential(r),
+        }
+    }
+}
+
+impl scc::Annotation for Representative {
+    fn merge_scc(self, other: Self) -> Self {
+        // Just pick the smallest one. Note that we order by tag first!
+        std::cmp::min(self, other)
+    }
+
+    // For reachability, we do nothing since the representative doesn't change.
+    fn merge_reached(self, _other: Self) -> Self {
+        self
+    }
+}
+
 pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>;
 
 pub struct RegionInferenceContext<'tcx> {
@@ -351,7 +390,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let mut result = Self {
             definitions,
             liveness_constraints,
-            constraints: Frozen::freeze(outlives_constraints),
+            constraints: outlives_constraints,
             constraint_graph,
             constraint_sccs,
             scc_annotations,
@@ -510,11 +549,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         self.scc_values.placeholders_contained_in(scc)
     }
 
-    /// Returns access to the value of `r` for debugging purposes.
-    pub(crate) fn region_universe(&self, r: RegionVid) -> ty::UniverseIndex {
-        self.scc_universe(self.constraint_sccs.scc(r))
-    }
-
     /// Once region solving has completed, this function will return the member constraints that
     /// were applied to the value of a given SCC `scc`. See `AppliedMemberConstraint`.
     pub(crate) fn applied_member_constraints(
@@ -681,7 +715,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // If the member region lives in a higher universe, we currently choose
         // the most conservative option by leaving it unchanged.
-        if !self.scc_universe(scc).is_root() {
+        if !self.max_nameable_universe(scc).is_root() {
             return;
         }
 
@@ -861,7 +895,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             "lower_bound = {:?} r_scc={:?} universe={:?}",
             lower_bound,
             r_scc,
-            self.scc_universe(r_scc)
+            self.max_nameable_universe(r_scc)
         );
         // If the type test requires that `T: 'a` where `'a` is a
         // placeholder from another universe, that effectively requires
@@ -1339,10 +1373,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
-    /// The minimum universe of any variable reachable from this
-    /// SCC, inside or outside of it.
-    fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
-        self.scc_annotations[scc].min_universe()
+    /// The largest universe of any region nameable from this SCC.
+    fn max_nameable_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
+        self.scc_annotations[scc].max_nameable_universe()
     }
 
     /// Checks the final value for the free region `fr` to see if it
@@ -1364,7 +1397,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // Because this free region must be in the ROOT universe, we
         // know it cannot contain any bound universes.
-        assert!(self.scc_universe(longer_fr_scc).is_root());
+        assert!(self.max_nameable_universe(longer_fr_scc).is_root());
 
         // Only check all of the relations for the main representative of each
         // SCC, otherwise just check that we outlive said representative. This
@@ -1755,7 +1788,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     #[instrument(skip(self), level = "trace", ret)]
     pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid {
         trace!(scc = ?self.constraint_sccs.scc(fr1));
-        trace!(universe = ?self.region_universe(fr1));
+        trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1)));
         self.find_constraint_paths_between_regions(fr1, |r| {
             // First look for some `r` such that `fr1: r` and `r` is live at `location`
             trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r));
@@ -2086,7 +2119,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// they *must* be equal (though not having the same repr does not
     /// mean they are unequal).
     fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid {
-        self.scc_annotations[scc].representative
+        self.scc_annotations[scc].representative.rvid()
     }
 
     pub(crate) fn liveness_constraints(&self) -> &LivenessValues {
@@ -2108,21 +2141,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 }
 
-impl<'tcx> RegionDefinition<'tcx> {
-    pub(crate) fn new(rv_info: &RegionVariableInfo) -> Self {
-        // Create a new region definition. Note that, for free
-        // regions, the `external_name` field gets updated later in
-        // [[crate::eliminate_placeholders]].
-
-        let origin = match rv_info.origin {
-            RegionVariableOrigin::Nll(origin) => origin,
-            _ => NllRegionVariableOrigin::Existential { from_forall: false },
-        };
-
-        Self { origin, universe: rv_info.universe, external_name: None }
-    }
-}
-
 #[derive(Clone, Debug)]
 pub(crate) struct BlameConstraint<'tcx> {
     pub category: ConstraintCategory<'tcx>,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 550c57338d3..3c05fa2ae0f 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -191,7 +191,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 let scc = self.constraint_sccs.scc(vid);
 
                 // Special handling of higher-ranked regions.
-                if !self.scc_universe(scc).is_root() {
+                if !self.max_nameable_universe(scc).is_root() {
                     match self.scc_values.placeholders_contained_in(scc).enumerate().last() {
                         // If the region contains a single placeholder then they're equal.
                         Some((0, placeholder)) => {