diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index 2a7dc8ba10162..11b8890346dfb 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -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>) -> 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, definitions: &'d IndexVec>, } +impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> { + pub(crate) fn init(definitions: &'d IndexVec>) -> Self { + Self { scc_to_annotation: IndexVec::new(), definitions } + } +} + impl scc::Annotations for SccAnnotations<'_, '_, RegionTracker> { fn new(&self, element: RegionVid) -> RegionTracker { RegionTracker::new(element, &self.definitions[element]) @@ -118,7 +118,7 @@ impl RegionTracker { } /// 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; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 5cdda777723b3..2a759387788a7 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -501,43 +501,48 @@ impl<'tcx> RegionInferenceContext<'tcx> { 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, ) } diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 10abfd7a55ced..c04688e0a49fa 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -27,7 +27,7 @@ mod tests; /// 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