Rollup merge of #155910 - BoxyUwU:borrowck_cleanup_5, r=lcnr

misc stuff from reading borrowck again :)

r? lcnr
This commit is contained in:
Jonathan Brouwer
2026-04-28 20:24:36 +02:00
committed by GitHub
3 changed files with 27 additions and 24 deletions
@@ -35,18 +35,18 @@ pub(crate) struct LoweredConstraints<'tcx> {
pub(crate) placeholder_indices: PlaceholderIndices<'tcx>,
}
impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> {
pub(crate) fn init(definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>) -> Self {
Self { scc_to_annotation: IndexVec::new(), definitions }
}
}
/// A Visitor for SCC annotation construction.
pub(crate) struct SccAnnotations<'d, 'tcx, A: scc::Annotation> {
pub(crate) scc_to_annotation: IndexVec<ConstraintSccIndex, A>,
definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>,
}
impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> {
pub(crate) fn init(definitions: &'d IndexVec<RegionVid, RegionDefinition<'tcx>>) -> Self {
Self { scc_to_annotation: IndexVec::new(), definitions }
}
}
impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
fn new(&self, element: RegionVid) -> RegionTracker {
RegionTracker::new(element, &self.definitions[element])
@@ -118,7 +118,7 @@ pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
}
/// The largest universe this SCC can name. It's the smallest
/// largest nameable universe of any reachable region, or
/// max-nameable-universe of any reachable region, or
/// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
self.max_nameable_universe.0
@@ -208,7 +208,7 @@ pub(super) fn region_definitions<'tcx>(
/// graph such that there is a series of constraints
/// A: B: C: ... : X where
/// A contains a placeholder whose universe cannot be named by X,
/// add a constraint that A: 'static. This is a safe upper bound
/// add a constraint that X: 'static. This is a safe upper bound
/// in the face of borrow checker/trait solver limitations that will
/// eventually go away.
///
@@ -327,8 +327,6 @@ pub(crate) fn rewrite_placeholder_outlives<'tcx>(
for scc in sccs.all_sccs() {
// No point in adding 'static: 'static!
// This micro-optimisation makes somewhat sense
// because static outlives *everything*.
if scc == sccs.scc(fr_static) {
continue;
}
+18 -13
View File
@@ -501,43 +501,48 @@ pub(super) fn solve(
let mut errors_buffer = RegionErrors::new(infcx.tcx);
// If this is a closure, we can propagate unsatisfied
// `outlives_requirements` to our creator, so create a vector
// to store those. Otherwise, we'll pass in `None` to the
// functions below, which will trigger them to report errors
// eagerly.
let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);
// If this is a nested body, we propagate unsatisfied
// outlives constraints to the parent body instead of
// eagerly erroing.
let mut propagated_outlives_requirements =
infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);
self.check_type_tests(infcx, outlives_requirements.as_mut(), &mut errors_buffer);
self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer);
debug!(?errors_buffer);
debug!(?outlives_requirements);
debug!(?propagated_outlives_requirements);
// In Polonius mode, the errors about missing universal region relations are in the output
// and need to be emitted or propagated. Otherwise, we need to check whether the
// constraints were too strong, and if so, emit or propagate those errors.
if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() {
self.check_polonius_subset_errors(
outlives_requirements.as_mut(),
propagated_outlives_requirements.as_mut(),
&mut errors_buffer,
polonius_output
.as_ref()
.expect("Polonius output is unavailable despite `-Z polonius`"),
);
} else {
self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer);
self.check_universal_regions(
propagated_outlives_requirements.as_mut(),
&mut errors_buffer,
);
}
debug!(?errors_buffer);
let outlives_requirements = outlives_requirements.unwrap_or_default();
let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default();
if outlives_requirements.is_empty() {
if propagated_outlives_requirements.is_empty() {
(None, errors_buffer)
} else {
let num_external_vids = self.universal_regions().num_global_and_external_regions();
(
Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }),
Some(ClosureRegionRequirements {
num_external_vids,
outlives_requirements: propagated_outlives_requirements,
}),
errors_buffer,
)
}
@@ -27,7 +27,7 @@
/// the max/min element of the SCC, or all of the above.
///
/// Concretely, the both merge operations must commute, e.g. where `merge`
/// is `update_scc` and `update_reached`: `a.merge(b) == b.merge(a)`
/// is `update_scc` and `update_reachable`: `a.merge(b) == b.merge(a)`
///
/// In general, what you want is probably always min/max according
/// to some ordering, potentially with side constraints (min x such