about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs43
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/lib.rs21
-rw-r--r--compiler/rustc_borrowck/src/nll.rs46
-rw-r--r--compiler/rustc_borrowck/src/polonius/mod.rs15
-rw-r--r--compiler/rustc_borrowck/src/region_infer/dump_mir.rs3
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs82
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs6
-rw-r--r--compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs12
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs39
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs9
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs7
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs58
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs2
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs15
23 files changed, 171 insertions, 226 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 0897d140d60..90d12ea8328 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -60,7 +60,7 @@ impl<'tcx> UniverseInfo<'tcx> {
             UniverseInfo::RelateTys { expected, found } => {
                 let err = mbcx.infcx.err_ctxt().report_mismatched_types(
                     &cause,
-                    mbcx.param_env,
+                    mbcx.infcx.param_env,
                     expected,
                     found,
                     TypeError::RegionsPlaceholderMismatch,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 129a30661d6..c11103af476 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -266,7 +266,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 }
             }
 
-            if self.param_env.caller_bounds().iter().any(|c| {
+            if self.infcx.param_env.caller_bounds().iter().any(|c| {
                 c.as_trait_clause().is_some_and(|pred| {
                     pred.skip_binder().self_ty() == ty && self.infcx.tcx.is_fn_trait(pred.def_id())
                 })
@@ -682,13 +682,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 // Normalize before comparing to see through type aliases and projections.
                 let old_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args);
                 let new_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, new_args);
-                if let Ok(old_ty) =
-                    tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), old_ty)
-                    && let Ok(new_ty) = tcx.try_normalize_erasing_regions(
-                        self.infcx.typing_env(self.param_env),
-                        new_ty,
-                    )
-                {
+                if let Ok(old_ty) = tcx.try_normalize_erasing_regions(
+                    self.infcx.typing_env(self.infcx.param_env),
+                    old_ty,
+                ) && let Ok(new_ty) = tcx.try_normalize_erasing_regions(
+                    self.infcx.typing_env(self.infcx.param_env),
+                    new_ty,
+                ) {
                     old_ty == new_ty
                 } else {
                     false
@@ -707,15 +707,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             // Test the callee's predicates, substituting in `ref_ty` for the moved argument type.
             clauses.instantiate(tcx, new_args).predicates.iter().all(|&(mut clause)| {
                 // Normalize before testing to see through type aliases and projections.
-                if let Ok(normalized) =
-                    tcx.try_normalize_erasing_regions(self.infcx.typing_env(self.param_env), clause)
-                {
+                if let Ok(normalized) = tcx.try_normalize_erasing_regions(
+                    self.infcx.typing_env(self.infcx.param_env),
+                    clause,
+                ) {
                     clause = normalized;
                 }
                 self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
                     tcx,
                     ObligationCause::dummy(),
-                    self.param_env,
+                    self.infcx.param_env,
                     clause,
                 ))
             })
@@ -904,7 +905,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
         debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
 
-        let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.param_env, ty)
+        let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.infcx.param_env, ty)
         else {
             return;
         };
@@ -1304,7 +1305,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     pub(crate) fn implements_clone(&self, ty: Ty<'tcx>) -> bool {
         let Some(clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() else { return false };
         self.infcx
-            .type_implements_trait(clone_trait_def, [ty], self.param_env)
+            .type_implements_trait(clone_trait_def, [ty], self.infcx.param_env)
             .must_apply_modulo_regions()
     }
 
@@ -1437,7 +1438,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
         let cause = ObligationCause::misc(span, self.mir_def_id());
 
-        ocx.register_bound(cause, self.param_env, ty, def_id);
+        ocx.register_bound(cause, self.infcx.param_env, ty, def_id);
         let errors = ocx.select_all_or_error();
 
         // Only emit suggestion if all required predicates are on generic
@@ -1957,7 +1958,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 && let ty::Ref(_, inner, _) = rcvr_ty.kind()
                 && let inner = inner.peel_refs()
                 && (Holds { ty: inner }).visit_ty(local_ty).is_break()
-                && let None = self.infcx.type_implements_trait_shallow(clone, inner, self.param_env)
+                && let None =
+                    self.infcx.type_implements_trait_shallow(clone, inner, self.infcx.param_env)
             {
                 err.span_label(
                     span,
@@ -1989,7 +1991,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             let obligation = Obligation::new(
                 self.infcx.tcx,
                 ObligationCause::dummy(),
-                self.param_env,
+                self.infcx.param_env,
                 trait_ref,
             );
             self.infcx.err_ctxt().suggest_derive(
@@ -3398,7 +3400,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
                 && self
                     .infcx
-                    .type_implements_trait(iter_trait, [return_ty], self.param_env)
+                    .type_implements_trait(iter_trait, [return_ty], self.infcx.param_env)
                     .must_apply_modulo_regions()
             {
                 err.span_suggestion_hidden(
@@ -3839,14 +3841,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
                         Instance::try_resolve(
                             tcx,
-                            self.infcx.typing_env(self.param_env),
+                            self.infcx.typing_env(self.infcx.param_env),
                             deref_target,
                             method_args,
                         )
                         .transpose()
                     });
                 if let Some(Ok(instance)) = deref_target {
-                    let deref_target_ty = instance.ty(tcx, self.infcx.typing_env(self.param_env));
+                    let deref_target_ty =
+                        instance.ty(tcx, self.infcx.typing_env(self.infcx.param_env));
                     err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
                     err.span_note(tcx.def_span(instance.def_id()), "deref defined here");
                 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 6c63da819c7..bda96726738 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -864,7 +864,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
             let kind = call_kind(
                 self.infcx.tcx,
-                self.infcx.typing_env(self.param_env),
+                self.infcx.typing_env(self.infcx.param_env),
                 method_did,
                 method_args,
                 *fn_span,
@@ -1160,7 +1160,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                         let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
                             Some(def_id) => type_known_to_meet_bound_modulo_regions(
                                 self.infcx,
-                                self.param_env,
+                                self.infcx.param_env,
                                 Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty),
                                 def_id,
                             ),
@@ -1224,7 +1224,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                                 BoundRegionConversionTime::FnCall,
                                 tcx.fn_sig(method_did).instantiate(tcx, method_args).input(0),
                             )
-                            && self.infcx.can_eq(self.param_env, ty, self_ty)
+                            && self.infcx.can_eq(self.infcx.param_env, ty, self_ty)
                         {
                             err.subdiagnostic(CaptureReasonSuggest::FreshReborrow {
                                 span: move_span.shrink_to_hi(),
@@ -1258,7 +1258,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                             if let Some(errors) = self.infcx.type_implements_trait_shallow(
                                 clone_trait,
                                 ty,
-                                self.param_env,
+                                self.infcx.param_env,
                             ) && !has_sugg
                             {
                                 let msg = match &errors[..] {
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 15cc9c20ab7..4ba6b2e94ec 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -305,7 +305,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false };
         // This is only going to be ambiguous if there are incoherent impls, because otherwise
         // ambiguity should never happen in MIR.
-        self.infcx.type_implements_trait(copy_trait_def, [ty], self.param_env).may_apply()
+        self.infcx.type_implements_trait(copy_trait_def, [ty], self.infcx.param_env).may_apply()
     }
 
     fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index d064bf098e4..c5ebf3c547e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1242,7 +1242,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                             .type_implements_trait_shallow(
                                 clone_trait,
                                 ty.peel_refs(),
-                                self.param_env,
+                                self.infcx.param_env,
                             )
                             .as_deref()
                         {
@@ -1279,7 +1279,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                                 let obligation = traits::Obligation::new(
                                     self.infcx.tcx,
                                     traits::ObligationCause::dummy(),
-                                    self.param_env,
+                                    self.infcx.param_env,
                                     trait_ref,
                                 );
                                 self.infcx.err_ctxt().suggest_derive(
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index d4660d8af43..c38747f6675 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -952,7 +952,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
             if let Ok(Some(instance)) = ty::Instance::try_resolve(
                 tcx,
-                self.infcx.typing_env(self.param_env),
+                self.infcx.typing_env(self.infcx.param_env),
                 *fn_did,
                 self.infcx.resolve_vars_if_possible(args),
             ) {
@@ -1091,7 +1091,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             peeled_ty = ref_ty;
             count += 1;
         }
-        if !self.infcx.type_is_copy_modulo_regions(self.param_env, peeled_ty) {
+        if !self.infcx.type_is_copy_modulo_regions(self.infcx.param_env, peeled_ty) {
             return;
         }
 
@@ -1160,7 +1160,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let ocx = ObligationCtxt::new(&self.infcx);
         ocx.register_obligations(preds.iter().map(|(pred, span)| {
             trace!(?pred);
-            Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred)
+            Obligation::misc(tcx, span, self.mir_def_id(), self.infcx.param_env, pred)
         }));
 
         if ocx.select_all_or_error().is_empty() && count > 0 {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 7eaf265d410..03f7b05d1e3 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -140,7 +140,6 @@ fn do_mir_borrowck<'tcx>(
 ) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
     let def = input_body.source.def_id().expect_local();
     let infcx = BorrowckInferCtxt::new(tcx, def);
-    let param_env = tcx.param_env(def);
 
     let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
     for var_debug_info in &input_body.var_debug_info {
@@ -175,8 +174,7 @@ fn do_mir_borrowck<'tcx>(
     // will have a lifetime tied to the inference context.
     let mut body_owned = input_body.clone();
     let mut promoted = input_promoted.to_owned();
-    let free_regions =
-        nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
+    let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
     let body = &body_owned; // no further changes
 
     // FIXME(-Znext-solver): A bit dubious that we're only registering
@@ -192,7 +190,7 @@ fn do_mir_borrowck<'tcx>(
         .iter_enumerated()
         .map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, |_| true)));
 
-    let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
+    let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
         .iterate_to_fixpoint(tcx, body, Some("borrowck"))
         .into_results_cursor(body);
 
@@ -213,18 +211,12 @@ fn do_mir_borrowck<'tcx>(
         body,
         &promoted,
         &location_table,
-        param_env,
-        &mut flow_inits,
+        flow_inits,
         &move_data,
         &borrow_set,
-        tcx.closure_captures(def),
         consumer_options,
     );
 
-    // `flow_inits` is large, so we drop it as soon as possible. This reduces
-    // peak memory usage significantly on some benchmarks.
-    drop(flow_inits);
-
     // Dump MIR results into a file, if that is enabled. This let us
     // write unit-tests, as well as helping with debugging.
     nll::dump_nll_mir(&infcx, body, &regioncx, &opt_closure_req, &borrow_set);
@@ -251,7 +243,6 @@ fn do_mir_borrowck<'tcx>(
         let promoted_body = &promoted[idx];
         let mut promoted_mbcx = MirBorrowckCtxt {
             infcx: &infcx,
-            param_env,
             body: promoted_body,
             move_data: &move_data,
             location_table: &location_table, // no need to create a real one for the promoted, it is not used
@@ -291,7 +282,6 @@ fn do_mir_borrowck<'tcx>(
 
     let mut mbcx = MirBorrowckCtxt {
         infcx: &infcx,
-        param_env,
         body,
         move_data: &move_data,
         location_table: &location_table,
@@ -448,12 +438,14 @@ fn get_flow_results<'a, 'tcx>(
 pub(crate) struct BorrowckInferCtxt<'tcx> {
     pub(crate) infcx: InferCtxt<'tcx>,
     pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
+    pub(crate) param_env: ParamEnv<'tcx>,
 }
 
 impl<'tcx> BorrowckInferCtxt<'tcx> {
     pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
         let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id));
-        BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
+        let param_env = tcx.param_env(def_id);
+        BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env }
     }
 
     pub(crate) fn next_region_var<F>(
@@ -532,7 +524,6 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
 
 struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
     infcx: &'infcx BorrowckInferCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
     body: &'a Body<'tcx>,
     move_data: &'a MoveData<'tcx>,
 
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index f76603d5679..be02e2f48df 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -30,7 +30,7 @@ use crate::diagnostics::RegionErrors;
 use crate::facts::{AllFacts, AllFactsExt, RustcFacts};
 use crate::location::LocationTable;
 use crate::region_infer::RegionInferenceContext;
-use crate::type_check::{self, MirTypeckRegionConstraints, MirTypeckResults};
+use crate::type_check::{self, MirTypeckResults};
 use crate::universal_regions::UniversalRegions;
 use crate::{BorrowckInferCtxt, polonius, renumber};
 
@@ -50,10 +50,9 @@ pub(crate) struct NllOutput<'tcx> {
 /// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal
 /// regions (e.g., region parameters) declared on the function. That set will need to be given to
 /// `compute_regions`.
-#[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
+#[instrument(skip(infcx, body, promoted), level = "debug")]
 pub(crate) fn replace_regions_in_mir<'tcx>(
     infcx: &BorrowckInferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &mut Body<'tcx>,
     promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
 ) -> UniversalRegions<'tcx> {
@@ -62,7 +61,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
     debug!(?def);
 
     // Compute named region information. This also renumbers the inputs/outputs.
-    let universal_regions = UniversalRegions::new(infcx, def, param_env);
+    let universal_regions = UniversalRegions::new(infcx, def);
 
     // Replace all remaining regions with fresh inference variables.
     renumber::renumber_mir(infcx, body, promoted);
@@ -81,11 +80,9 @@ pub(crate) fn compute_regions<'a, 'tcx>(
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
     location_table: &LocationTable,
-    param_env: ty::ParamEnv<'tcx>,
-    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
-    upvars: &[&ty::CapturedPlace<'tcx>],
     consumer_options: Option<ConsumerOptions>,
 ) -> NllOutput<'tcx> {
     let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled();
@@ -96,41 +93,27 @@ pub(crate) fn compute_regions<'a, 'tcx>(
     let mut all_facts =
         (polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
 
-    let universal_regions = Rc::new(universal_regions);
-
     let elements = Rc::new(DenseLocationMap::new(body));
 
     // Run the MIR type-checker.
     let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } =
         type_check::type_check(
             infcx,
-            param_env,
             body,
             promoted,
-            Rc::clone(&universal_regions),
+            universal_regions,
             location_table,
             borrow_set,
             &mut all_facts,
             flow_inits,
             move_data,
             Rc::clone(&elements),
-            upvars,
         );
 
     // Create the region inference context, taking ownership of the
     // region inference data that was contained in `infcx`, and the
     // base constraints generated by the type-check.
     let var_origins = infcx.get_region_var_origins();
-    let MirTypeckRegionConstraints {
-        placeholder_indices,
-        placeholder_index_to_region: _,
-        liveness_constraints,
-        mut outlives_constraints,
-        mut member_constraints,
-        universe_causes,
-        type_tests,
-    } = constraints;
-    let placeholder_indices = Rc::new(placeholder_indices);
 
     // If requested, emit legacy polonius facts.
     polonius::emit_facts(
@@ -140,31 +123,14 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         body,
         borrow_set,
         move_data,
-        &universal_regions,
         &universal_region_relations,
     );
 
-    if let Some(guar) = universal_regions.tainted_by_errors() {
-        // Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
-        // outlives bounds that we may end up checking.
-        outlives_constraints = Default::default();
-        member_constraints = Default::default();
-
-        // Also taint the entire scope.
-        infcx.set_tainted_by_errors(guar);
-    }
-
     let mut regioncx = RegionInferenceContext::new(
         infcx,
         var_origins,
-        universal_regions,
-        placeholder_indices,
+        constraints,
         universal_region_relations,
-        outlives_constraints,
-        member_constraints,
-        universe_causes,
-        type_tests,
-        liveness_constraints,
         elements,
     );
 
diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs
index 6862eb13427..9fccc00bdaf 100644
--- a/compiler/rustc_borrowck/src/polonius/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/mod.rs
@@ -12,7 +12,6 @@ use crate::borrow_set::BorrowSet;
 use crate::facts::{AllFacts, PoloniusRegionVid};
 use crate::location::LocationTable;
 use crate::type_check::free_region_relations::UniversalRegionRelations;
-use crate::universal_regions::UniversalRegions;
 
 mod loan_invalidations;
 mod loan_kills;
@@ -32,7 +31,6 @@ pub(crate) fn emit_facts<'tcx>(
     body: &Body<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     move_data: &MoveData<'_>,
-    universal_regions: &UniversalRegions<'_>,
     universal_region_relations: &UniversalRegionRelations<'_>,
 ) {
     let Some(all_facts) = all_facts else {
@@ -41,12 +39,7 @@ pub(crate) fn emit_facts<'tcx>(
     };
     let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
     emit_move_facts(all_facts, move_data, location_table, body);
-    emit_universal_region_facts(
-        all_facts,
-        borrow_set,
-        universal_regions,
-        universal_region_relations,
-    );
+    emit_universal_region_facts(all_facts, borrow_set, universal_region_relations);
     emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
     emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
 }
@@ -129,7 +122,6 @@ fn emit_move_facts(
 fn emit_universal_region_facts(
     all_facts: &mut AllFacts,
     borrow_set: &BorrowSet<'_>,
-    universal_regions: &UniversalRegions<'_>,
     universal_region_relations: &UniversalRegionRelations<'_>,
 ) {
     // 1: universal regions are modeled in Polonius as a pair:
@@ -138,9 +130,10 @@ fn emit_universal_region_facts(
     //   the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
     //   added to the existing number of loans, as if they succeeded them in the set.
     //
+    let universal_regions = &universal_region_relations.universal_regions;
     all_facts
         .universal_region
-        .extend(universal_regions.universal_regions().map(PoloniusRegionVid::from));
+        .extend(universal_regions.universal_regions_iter().map(PoloniusRegionVid::from));
     let borrow_count = borrow_set.len();
     debug!(
         "emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
@@ -148,7 +141,7 @@ fn emit_universal_region_facts(
         borrow_count
     );
 
-    for universal_region in universal_regions.universal_regions() {
+    for universal_region in universal_regions.universal_regions_iter() {
         let universal_region_idx = universal_region.index();
         let placeholder_loan_idx = borrow_count + universal_region_idx;
         all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
index 6b8dd1a49e7..ef3d6309c19 100644
--- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
+++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
@@ -23,7 +23,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         for region in self.regions() {
             if let NllRegionVariableOrigin::FreeRegion = self.definitions[region].origin {
-                let classification = self.universal_regions.region_classification(region).unwrap();
+                let classification =
+                    self.universal_regions().region_classification(region).unwrap();
                 let outlived_by = self.universal_region_relations.regions_outlived_by(region);
                 writeln!(
                     out,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 7e317ea6554..0ddb4e110e3 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -31,11 +31,9 @@ use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo};
 use crate::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
 use crate::nll::PoloniusOutput;
 use crate::region_infer::reverse_sccs::ReverseSccGraph;
-use crate::region_infer::values::{
-    LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex,
-};
-use crate::type_check::Locations;
+use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues, ToElementIndex};
 use crate::type_check::free_region_relations::UniversalRegionRelations;
+use crate::type_check::{Locations, MirTypeckRegionConstraints};
 use crate::universal_regions::UniversalRegions;
 
 mod dump_mir;
@@ -191,10 +189,6 @@ pub struct RegionInferenceContext<'tcx> {
     /// Type constraints that we check after solving.
     type_tests: Vec<TypeTest<'tcx>>,
 
-    /// Information about the universally quantified regions in scope
-    /// on this function.
-    universal_regions: Rc<UniversalRegions<'tcx>>,
-
     /// Information about how the universally quantified regions in
     /// scope on this function relate to one another.
     universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
@@ -399,21 +393,36 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn new(
         infcx: &BorrowckInferCtxt<'tcx>,
         var_infos: VarInfos,
-        universal_regions: Rc<UniversalRegions<'tcx>>,
-        placeholder_indices: Rc<PlaceholderIndices>,
+        constraints: MirTypeckRegionConstraints<'tcx>,
         universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-        mut outlives_constraints: OutlivesConstraintSet<'tcx>,
-        member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
-        universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
-        type_tests: Vec<TypeTest<'tcx>>,
-        liveness_constraints: LivenessValues,
         elements: Rc<DenseLocationMap>,
     ) -> Self {
-        debug!("universal_regions: {:#?}", universal_regions);
+        let universal_regions = &universal_region_relations.universal_regions;
+        let MirTypeckRegionConstraints {
+            placeholder_indices,
+            placeholder_index_to_region: _,
+            liveness_constraints,
+            mut outlives_constraints,
+            mut member_constraints,
+            universe_causes,
+            type_tests,
+        } = constraints;
+
+        debug!("universal_regions: {:#?}", universal_region_relations.universal_regions);
         debug!("outlives constraints: {:#?}", outlives_constraints);
         debug!("placeholder_indices: {:#?}", placeholder_indices);
         debug!("type tests: {:#?}", type_tests);
 
+        if let Some(guar) = universal_region_relations.universal_regions.tainted_by_errors() {
+            // Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
+            // outlives bounds that we may end up checking.
+            outlives_constraints = Default::default();
+            member_constraints = Default::default();
+
+            // Also taint the entire scope.
+            infcx.set_tainted_by_errors(guar);
+        }
+
         // Create a RegionDefinition for each inference variable.
         let definitions: IndexVec<_, _> = var_infos
             .iter()
@@ -438,7 +447,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
 
         let member_constraints =
-            Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
+            Rc::new(member_constraints.into_mapped(|r| constraint_sccs.scc(r)));
 
         let mut result = Self {
             var_infos,
@@ -453,7 +462,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             universe_causes,
             scc_values,
             type_tests,
-            universal_regions,
             universal_region_relations,
         };
 
@@ -518,7 +526,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn init_free_and_bound_regions(&mut self) {
         // Update the names (if any)
         // This iterator has unstable order but we collect it all into an IndexVec
-        for (external_name, variable) in self.universal_regions.named_universal_regions() {
+        for (external_name, variable) in
+            self.universal_region_relations.universal_regions.named_universal_regions_iter()
+        {
             debug!(
                 "init_free_and_bound_regions: region {:?} has external name {:?}",
                 variable, external_name
@@ -562,7 +572,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// (Panics if `r` is not a registered universal region.)
     pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
-        self.universal_regions.to_region_vid(r)
+        self.universal_regions().to_region_vid(r)
     }
 
     /// Returns an iterator over all the outlives constraints.
@@ -574,7 +584,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`.
     pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) {
-        self.universal_regions.annotate(tcx, err)
+        self.universal_regions().annotate(tcx, err)
     }
 
     /// Returns `true` if the region `r` contains the point `p`.
@@ -686,7 +696,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         if outlives_requirements.is_empty() {
             (None, errors_buffer)
         } else {
-            let num_external_vids = self.universal_regions.num_global_and_external_regions();
+            let num_external_vids = self.universal_regions().num_global_and_external_regions();
             (
                 Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }),
                 errors_buffer,
@@ -989,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // always be in the root universe.
         if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() {
             debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p);
-            let static_r = self.universal_regions.fr_static;
+            let static_r = self.universal_regions().fr_static;
             propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                 subject,
                 outlived_free_region: static_r,
@@ -1032,8 +1042,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // avoid potential non-determinism we approximate this by requiring
             // T: '1 and T: '2.
             for upper_bound in non_local_ub {
-                debug_assert!(self.universal_regions.is_universal_region(upper_bound));
-                debug_assert!(!self.universal_regions.is_local_free_region(upper_bound));
+                debug_assert!(self.universal_regions().is_universal_region(upper_bound));
+                debug_assert!(!self.universal_regions().is_local_free_region(upper_bound));
 
                 let requirement = ClosureOutlivesRequirement {
                     subject,
@@ -1101,7 +1111,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // To do so, we simply check every candidate `u_r` for equality.
             self.scc_values
                 .universal_regions_outlived_by(r_scc)
-                .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
+                .filter(|&u_r| !self.universal_regions().is_local_free_region(u_r))
                 .find(|&u_r| self.eval_equal(u_r, r_vid))
                 .map(|u_r| ty::Region::new_var(tcx, u_r))
                 // In case we could not find a named region to map to,
@@ -1139,9 +1149,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // Find the smallest universal region that contains all other
         // universal regions within `region`.
-        let mut lub = self.universal_regions.fr_fn_body;
+        let mut lub = self.universal_regions().fr_fn_body;
         let r_scc = self.constraint_sccs.scc(r);
-        let static_r = self.universal_regions.fr_static;
+        let static_r = self.universal_regions().fr_static;
         for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
             let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
             debug!(?ur, ?lub, ?new_lub);
@@ -1288,12 +1298,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!(
             "sup_region's value = {:?} universal={:?}",
             self.region_value_str(sup_region),
-            self.universal_regions.is_universal_region(sup_region),
+            self.universal_regions().is_universal_region(sup_region),
         );
         debug!(
             "sub_region's value = {:?} universal={:?}",
             self.region_value_str(sub_region),
-            self.universal_regions.is_universal_region(sub_region),
+            self.universal_regions().is_universal_region(sub_region),
         );
 
         let sub_region_scc = self.constraint_sccs.scc(sub_region);
@@ -1308,7 +1318,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 by super `{sup_region_scc:?}`, promoting to static",
             );
 
-            return self.eval_outlives(sup_region, self.universal_regions.fr_static);
+            return self.eval_outlives(sup_region, self.universal_regions().fr_static);
         }
 
         // Both the `sub_region` and `sup_region` consist of the union
@@ -1332,7 +1342,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Now we have to compare all the points in the sub region and make
         // sure they exist in the sup region.
 
-        if self.universal_regions.is_universal_region(sup_region) {
+        if self.universal_regions().is_universal_region(sup_region) {
             // Micro-opt: universal regions contain all points.
             debug!("super is universal and hence contains all points");
             return true;
@@ -1736,7 +1746,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
         let result = {
             r == fr2 || {
-                fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r)
+                fr2 == self.universal_regions().fr_static && self.cannot_name_placeholder(fr1, r)
             }
         };
         debug!("provides_universal_region: result = {:?}", result);
@@ -1837,7 +1847,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
             // A constraint like `'r: 'x` can come from our constraint
             // graph.
-            let fr_static = self.universal_regions.fr_static;
+            let fr_static = self.universal_regions().fr_static;
             let outgoing_edges_from_graph =
                 self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static);
 
@@ -1952,7 +1962,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     pub(crate) fn universal_regions(&self) -> &UniversalRegions<'tcx> {
-        self.universal_regions.as_ref()
+        &self.universal_region_relations.universal_regions
     }
 
     /// Tries to find the best constraint to blame for the fact that
@@ -2212,7 +2222,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     /// Access to the region graph, built from the outlives constraints.
     pub(crate) fn region_graph(&self) -> RegionGraph<'_, 'tcx, graph::Normal> {
-        self.constraint_graph.region_graph(&self.constraints, self.universal_regions.fr_static)
+        self.constraint_graph.region_graph(&self.constraints, self.universal_regions().fr_static)
     }
 
     /// Returns whether the given region is considered live at all points: whether it is a
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index d676ce59cfe..993d5d86333 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -74,7 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             debug!(?opaque_type_key, ?concrete_type);
 
             let mut arg_regions: Vec<(ty::RegionVid, ty::Region<'_>)> =
-                vec![(self.universal_regions.fr_static, infcx.tcx.lifetimes.re_static)];
+                vec![(self.universal_regions().fr_static, infcx.tcx.lifetimes.re_static)];
 
             let opaque_type_key =
                 opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |region| {
@@ -88,12 +88,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         // the same name and simplifies subsequent handling.
                         // See [rustc-dev-guide chapter] § "Semantic lifetime equality".
                         NllRegionVariableOrigin::FreeRegion => self
-                            .universal_regions
                             .universal_regions()
+                            .universal_regions_iter()
                             .filter(|&ur| {
                                 // See [rustc-dev-guide chapter] § "Closure restrictions".
                                 !matches!(
-                                    self.universal_regions.region_classification(ur),
+                                    self.universal_regions().region_classification(ur),
                                     Some(RegionClassification::External)
                                 )
                             })
diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
index cfd5a92787e..d0cfe572d08 100644
--- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
+++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
@@ -45,8 +45,8 @@ impl RegionInferenceContext<'_> {
 
         let graph = self.constraint_sccs.reverse();
         let mut paired_scc_regions = self
-            .universal_regions
             .universal_regions()
+            .universal_regions_iter()
             .map(|region| (self.constraint_sccs.scc(region), region))
             .collect::<Vec<_>>();
         paired_scc_regions.sort();
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 519edfafda5..a16bce63839 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -258,10 +258,9 @@ impl PlaceholderIndices {
 /// Here, the variable `'0` would contain the free region `'a`,
 /// because (since it is returned) it must live for at least `'a`. But
 /// it would also contain various points from within the function.
-#[derive(Clone)]
 pub(crate) struct RegionValues<N: Idx> {
     elements: Rc<DenseLocationMap>,
-    placeholder_indices: Rc<PlaceholderIndices>,
+    placeholder_indices: PlaceholderIndices,
     points: SparseIntervalMatrix<N, PointIndex>,
     free_regions: SparseBitMatrix<N, RegionVid>,
 
@@ -277,7 +276,7 @@ impl<N: Idx> RegionValues<N> {
     pub(crate) fn new(
         elements: Rc<DenseLocationMap>,
         num_universal_regions: usize,
-        placeholder_indices: Rc<PlaceholderIndices>,
+        placeholder_indices: PlaceholderIndices,
     ) -> Self {
         let num_points = elements.num_points();
         let num_placeholders = placeholder_indices.len();
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index aee13ca8cd7..68b843d4d0d 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -132,7 +132,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         let predicate = predicate.upcast(self.tcx());
         let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             locations,
@@ -158,7 +158,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     where
         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
     {
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             location.to_locations(),
             category,
@@ -176,7 +176,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let tcx = self.tcx();
         if self.infcx.next_trait_solver() {
             let body = self.body;
-            let param_env = self.param_env;
+            let param_env = self.infcx.param_env;
             self.fully_perform_op(
                 location.to_locations(),
                 ConstraintCategory::Boring,
@@ -223,7 +223,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
-            self.param_env.and(type_op::ascribe_user_type::AscribeUserType { mir_ty, user_ty }),
+            self.infcx
+                .param_env
+                .and(type_op::ascribe_user_type::AscribeUserType { mir_ty, user_ty }),
         );
     }
 
@@ -250,7 +252,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let mir_ty = self.normalize(mir_ty, Locations::All(span));
 
         let cause = ObligationCause::dummy_with_span(span);
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 6c86968389a..67915371b1f 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -37,7 +37,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
     implicit_region_bound: ty::Region<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
+    known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
     locations: Locations,
     span: Span,
     category: ConstraintCategory<'tcx>,
@@ -52,7 +52,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
         implicit_region_bound: ty::Region<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
+        known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
         locations: Locations,
         span: Span,
         category: ConstraintCategory<'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 8e1faf025e2..ea965eb6545 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -1,5 +1,3 @@
-use std::rc::Rc;
-
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
 use rustc_hir::def::DefKind;
@@ -23,7 +21,7 @@ use crate::universal_regions::UniversalRegions;
 
 #[derive(Debug)]
 pub(crate) struct UniversalRegionRelations<'tcx> {
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    pub(crate) universal_regions: UniversalRegions<'tcx>,
 
     /// Stores the outlives relations that are known to hold from the
     /// implied bounds, in-scope where-clauses, and that sort of
@@ -46,7 +44,7 @@ type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
 pub(crate) struct CreateResult<'tcx> {
     pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
     pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>,
-    pub(crate) known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
+    pub(crate) known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
     pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
 }
 
@@ -54,7 +52,7 @@ pub(crate) fn create<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     implicit_region_bound: ty::Region<'tcx>,
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    universal_regions: UniversalRegions<'tcx>,
     constraints: &mut MirTypeckRegionConstraints<'tcx>,
 ) -> CreateResult<'tcx> {
     UniversalRegionRelationsBuilder {
@@ -184,7 +182,7 @@ impl UniversalRegionRelations<'_> {
 struct UniversalRegionRelationsBuilder<'a, 'tcx> {
     infcx: &'a InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    universal_regions: UniversalRegions<'tcx>,
     implicit_region_bound: ty::Region<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
 
@@ -220,7 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         //   region `'r`, all of which are provided by our caller
         let fr_static = self.universal_regions.fr_static;
         let fr_fn_body = self.universal_regions.fr_fn_body;
-        for fr in self.universal_regions.universal_regions() {
+        for fr in self.universal_regions.universal_regions_iter() {
             debug!("build: relating free region {:?} to itself and to 'static", fr);
             self.relate_universal_regions(fr, fr);
             self.relate_universal_regions(fr_static, fr);
@@ -236,7 +234,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             // In the new solver, normalize the type-outlives obligation assumptions.
             if self.infcx.next_trait_solver() {
                 match deeply_normalize(
-                    self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env),
+                    self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), param_env),
                     outlives,
                 ) {
                     Ok(normalized_outlives) => {
@@ -250,8 +248,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
 
             known_type_outlives_obligations.push(outlives);
         }
-        let known_type_outlives_obligations =
-            self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations);
 
         let unnormalized_input_output_tys = self
             .universal_regions
@@ -278,15 +274,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             if let Some(c) = constraints_unnorm {
                 constraints.push(c)
             }
-            let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
-                .param_env
-                .and(type_op::normalize::Normalize { value: ty })
-                .fully_perform(self.infcx, span)
-                .unwrap_or_else(|guar| TypeOpOutput {
-                    output: Ty::new_error(self.infcx.tcx, guar),
-                    constraints: None,
-                    error_info: None,
-                });
+            let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } =
+                param_env
+                    .and(type_op::normalize::Normalize { value: ty })
+                    .fully_perform(self.infcx, span)
+                    .unwrap_or_else(|guar| TypeOpOutput {
+                        output: Ty::new_error(self.infcx.tcx, guar),
+                        constraints: None,
+                        error_info: None,
+                    });
             if let Some(c) = constraints_normalize {
                 constraints.push(c)
             }
@@ -316,8 +312,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         // Add implied bounds from impl header.
         if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
             for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
-                let result: Result<_, ErrorGuaranteed> = self
-                    .param_env
+                let result: Result<_, ErrorGuaranteed> = param_env
                     .and(type_op::normalize::Normalize { value: ty })
                     .fully_perform(self.infcx, span);
                 let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
@@ -340,7 +335,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                 &self.region_bound_pairs,
                 self.implicit_region_bound,
                 param_env,
-                known_type_outlives_obligations,
+                &known_type_outlives_obligations,
                 Locations::All(span),
                 span,
                 ConstraintCategory::Internal,
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 7effd5c5a68..bbe2b55d8c4 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -19,7 +19,7 @@ use tracing::{debug, instrument};
 
 use super::{Locations, TypeChecker};
 use crate::renumber::RegionCtxt;
-use crate::universal_regions::{DefiningTy, UniversalRegions};
+use crate::universal_regions::DefiningTy;
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     /// Check explicit closure signature annotation,
@@ -124,11 +124,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
     }
 
-    #[instrument(skip(self, body, universal_regions), level = "debug")]
+    #[instrument(skip(self, body), level = "debug")]
     pub(super) fn equate_inputs_and_outputs(
         &mut self,
         body: &Body<'tcx>,
-        universal_regions: &UniversalRegions<'tcx>,
         normalized_inputs_and_output: &[Ty<'tcx>],
     ) {
         let (&normalized_output_ty, normalized_input_tys) =
@@ -161,7 +160,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if let Some(mir_yield_ty) = body.yield_ty() {
             let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
             self.equate_normalized_input_or_output(
-                universal_regions.yield_ty.unwrap(),
+                self.universal_regions.yield_ty.unwrap(),
                 mir_yield_ty,
                 yield_span,
             );
@@ -170,7 +169,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if let Some(mir_resume_ty) = body.resume_ty() {
             let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
             self.equate_normalized_input_or_output(
-                universal_regions.resume_ty.unwrap(),
+                self.universal_regions.resume_ty.unwrap(),
                 mir_resume_ty,
                 yield_span,
             );
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index 84fb36dd32a..20d19a53752 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -32,14 +32,14 @@ pub(super) fn generate<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
     elements: &DenseLocationMap,
-    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) {
     debug!("liveness::generate");
 
     let free_regions = regions_that_outlive_free_regions(
         typeck.infcx.num_region_vars(),
-        typeck.universal_regions,
+        &typeck.universal_regions,
         &typeck.constraints.outlives_constraints,
     );
     let (relevant_live_locals, boring_locals) =
@@ -107,7 +107,7 @@ fn regions_that_outlive_free_regions<'tcx>(
     let rev_region_graph = rev_constraint_graph.region_graph(constraint_set, fr_static);
 
     // Stack for the depth-first search. Start out with all the free regions.
-    let mut stack: Vec<_> = universal_regions.universal_regions().collect();
+    let mut stack: Vec<_> = universal_regions.universal_regions_iter().collect();
 
     // Set of all free regions, plus anything that outlives them. Initially
     // just contains the free regions.
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 72f6a605279..3ec36c16cbf 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -38,7 +38,7 @@ pub(super) fn trace<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
     elements: &DenseLocationMap,
-    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     relevant_live_locals: Vec<Local>,
     boring_locals: Vec<Local>,
@@ -113,7 +113,7 @@ struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
 
     /// Results of dataflow tracking which variables (and paths) have been
     /// initialized.
-    flow_inits: &'a mut ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
+    flow_inits: ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
 
     /// Index indicating where each variable is assigned, used, or
     /// dropped.
@@ -608,7 +608,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
 
         value.visit_with(&mut for_liveness::FreeRegionsVisitor {
             tcx: typeck.tcx(),
-            param_env: typeck.param_env,
+            param_env: typeck.infcx.param_env,
             op: |r| {
                 let live_region_vid = typeck.universal_regions.to_region_vid(r);
 
@@ -621,6 +621,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
         debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
 
         match typeck
+            .infcx
             .param_env
             .and(DropckOutlives { dropped_ty })
             .fully_perform(typeck.infcx, DUMMY_SP)
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index ac0219684d8..58a23b9e558 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -118,17 +118,15 @@ mod relate_tys;
 /// - `elements` -- MIR region map
 pub(crate) fn type_check<'a, 'tcx>(
     infcx: &BorrowckInferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
-    universal_regions: Rc<UniversalRegions<'tcx>>,
+    universal_regions: UniversalRegions<'tcx>,
     location_table: &LocationTable,
     borrow_set: &BorrowSet<'tcx>,
     all_facts: &mut Option<AllFacts>,
-    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     elements: Rc<DenseLocationMap>,
-    upvars: &[&ty::CapturedPlace<'tcx>],
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
@@ -148,9 +146,9 @@ pub(crate) fn type_check<'a, 'tcx>(
         known_type_outlives_obligations,
     } = free_region_relations::create(
         infcx,
-        param_env,
+        infcx.param_env,
         implicit_region_bound,
-        Rc::clone(&universal_regions),
+        universal_regions,
         &mut constraints,
     );
 
@@ -158,29 +156,27 @@ pub(crate) fn type_check<'a, 'tcx>(
 
     let mut checker = TypeChecker {
         infcx,
-        param_env,
         last_span: body.span,
         body,
         user_type_annotations: &body.user_type_annotations,
-        region_bound_pairs: &region_bound_pairs,
+        region_bound_pairs,
         known_type_outlives_obligations,
         implicit_region_bound,
         reported_errors: Default::default(),
-        universal_regions: &universal_regions,
+        universal_regions: &universal_region_relations.universal_regions,
         location_table,
         all_facts,
         borrow_set,
         constraints: &mut constraints,
-        upvars,
     };
 
     checker.check_user_type_annotations();
 
-    let mut verifier = TypeVerifier::new(&mut checker, promoted);
+    let mut verifier = TypeVerifier { cx: &mut checker, promoted, last_span: body.span };
     verifier.visit_body(body);
 
     checker.typeck_mir(body);
-    checker.equate_inputs_and_outputs(body, &universal_regions, &normalized_inputs_and_output);
+    checker.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
     checker.check_signature_annotation(body);
 
     liveness::generate(&mut checker, body, &elements, flow_inits, move_data);
@@ -467,13 +463,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 }
 
 impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
-    fn new(
-        cx: &'a mut TypeChecker<'b, 'tcx>,
-        promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
-    ) -> Self {
-        TypeVerifier { promoted, last_span: cx.body.span, cx }
-    }
-
     fn body(&self) -> &Body<'tcx> {
         self.cx.body
     }
@@ -837,14 +826,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 /// NLL region checking.
 struct TypeChecker<'a, 'tcx> {
     infcx: &'a BorrowckInferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     last_span: Span,
     body: &'a Body<'tcx>,
     /// User type annotations are shared between the main MIR and the MIR of
     /// all of the promoted items.
     user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
-    region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-    known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
+    region_bound_pairs: RegionBoundPairs<'tcx>,
+    known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
     implicit_region_bound: ty::Region<'tcx>,
     reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
     universal_regions: &'a UniversalRegions<'tcx>,
@@ -852,7 +840,6 @@ struct TypeChecker<'a, 'tcx> {
     all_facts: &'a mut Option<AllFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
-    upvars: &'a [&'a ty::CapturedPlace<'tcx>],
 }
 
 /// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions
@@ -1025,10 +1012,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         constraint_conversion::ConstraintConversion::new(
             self.infcx,
             self.universal_regions,
-            self.region_bound_pairs,
+            &self.region_bound_pairs,
             self.implicit_region_bound,
-            self.param_env,
-            self.known_type_outlives_obligations,
+            self.infcx.param_env,
+            &self.known_type_outlives_obligations,
             locations,
             locations.span(self.body),
             category,
@@ -1527,9 +1514,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 // The signature in this call can reference region variables,
                 // so erase them before calling a query.
                 let output_ty = self.tcx().erase_regions(sig.output());
-                if !output_ty
-                    .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.param_env))
-                {
+                if !output_ty.is_privately_uninhabited(
+                    self.tcx(),
+                    self.infcx.typing_env(self.infcx.param_env),
+                ) {
                     span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
                 }
             }
@@ -1739,7 +1727,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // `Sized` bound in no way depends on precise regions, so this
         // shouldn't affect `is_sized`.
         let erased_ty = tcx.erase_regions(ty);
-        if !erased_ty.is_sized(tcx, self.param_env) {
+        if !erased_ty.is_sized(tcx, self.infcx.param_env) {
             // in current MIR construction, all non-control-flow rvalue
             // expressions evaluate through `as_temp` or `into` a return
             // slot or local, so to find all unsized rvalues it is enough
@@ -2631,8 +2619,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
 
         let tcx = self.infcx.tcx;
+        let def = self.body.source.def_id().expect_local();
+        let upvars = tcx.closure_captures(def);
         let field =
-            path_utils::is_upvar_field_projection(tcx, self.upvars, borrowed_place.as_ref(), body);
+            path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), body);
         let category = if let Some(field) = field {
             ConstraintCategory::ClosureUpvar(field)
         } else {
@@ -2787,10 +2777,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
                 self.universal_regions,
-                self.region_bound_pairs,
+                &self.region_bound_pairs,
                 self.implicit_region_bound,
-                self.param_env,
-                self.known_type_outlives_obligations,
+                self.infcx.param_env,
+                &self.known_type_outlives_obligations,
                 locations,
                 self.body.span,             // irrelevant; will be overridden.
                 ConstraintCategory::Boring, // same as above.
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index e2f3e065bc0..752b2bf1a24 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -522,7 +522,7 @@ impl<'b, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating<'_
     }
 
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.type_checker.param_env
+        self.type_checker.infcx.param_env
     }
 
     fn register_predicates(
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index b63144f560f..f1c23aa26a9 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -248,12 +248,8 @@ impl<'tcx> UniversalRegions<'tcx> {
     /// MIR -- that is, all the regions that appear in the function's
     /// signature. This will also compute the relationships that are
     /// known between those regions.
-    pub(crate) fn new(
-        infcx: &BorrowckInferCtxt<'tcx>,
-        mir_def: LocalDefId,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> Self {
-        UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
+    pub(crate) fn new(infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId) -> Self {
+        UniversalRegionsBuilder { infcx, mir_def }.build()
     }
 
     /// Given a reference to a closure type, extracts all the values
@@ -312,7 +308,7 @@ impl<'tcx> UniversalRegions<'tcx> {
 
     /// Returns an iterator over all the RegionVids corresponding to
     /// universally quantified free regions.
-    pub(crate) fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
+    pub(crate) fn universal_regions_iter(&self) -> impl Iterator<Item = RegionVid> {
         (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
     }
 
@@ -336,7 +332,7 @@ impl<'tcx> UniversalRegions<'tcx> {
     }
 
     /// Gets an iterator over all the early-bound regions that have names.
-    pub(crate) fn named_universal_regions<'s>(
+    pub(crate) fn named_universal_regions_iter<'s>(
         &'s self,
     ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + 's {
         self.indices.indices.iter().map(|(&r, &v)| (r, v))
@@ -426,7 +422,6 @@ impl<'tcx> UniversalRegions<'tcx> {
 struct UniversalRegionsBuilder<'infcx, 'tcx> {
     infcx: &'infcx BorrowckInferCtxt<'tcx>,
     mir_def: LocalDefId,
-    param_env: ty::ParamEnv<'tcx>,
 }
 
 const FR: NllRegionVariableOrigin = NllRegionVariableOrigin::FreeRegion;
@@ -435,7 +430,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
     fn build(self) -> UniversalRegions<'tcx> {
         debug!("build(mir_def={:?})", self.mir_def);
 
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         debug!("build: param_env={:?}", param_env);
 
         assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());