about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-11-29 12:05:41 +0000
committerbors <bors@rust-lang.org>2024-11-29 12:05:41 +0000
commit0c4f3a45b86c77b0a89ff06703aa6097af35d924 (patch)
tree83c16880f6bc199f38f75acdfaa3326fa69328e1
parent5bbbc0938cfeb3dbd348d5258ddb6025bc8398c7 (diff)
parentce52b7b3d82eef4aca24d4f0cc9e22057fe3f755 (diff)
downloadrust-0c4f3a45b86c77b0a89ff06703aa6097af35d924.tar.gz
rust-0c4f3a45b86c77b0a89ff06703aa6097af35d924.zip
Auto merge of #133619 - matthiaskrgr:rollup-7ywaheb, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #132782 (improvements on initial sysroot and libdir finding logics)
 - #133466 (Fix typos in pin.rs)
 - #133492 (bootstrap: allow skipping steps with start of path)
 - #133501 (support revealing defined opaque post borrowck)
 - #133530 (Use consistent wording in docs, use is zero instead of is 0)
 - #133538 (Better diagnostic for fn items in variadic functions)
 - #133590 (Rename `-Zparse-only`)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/lib.rs3
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs5
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs7
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs5
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs6
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs3
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl5
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs7
-rw-r--r--compiler/rustc_infer/src/infer/context.rs6
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs17
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs5
-rw-r--r--compiler/rustc_interface/src/tests.rs2
-rw-r--r--compiler/rustc_middle/src/mir/query.rs5
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs83
-rw-r--r--compiler/rustc_middle/src/ty/util.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs15
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs21
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs21
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs19
-rw-r--r--compiler/rustc_session/src/config.rs4
-rw-r--r--compiler/rustc_session/src/options.rs7
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs10
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs4
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs3
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs3
-rw-r--r--compiler/rustc_type_ir/src/fold.rs74
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs13
-rw-r--r--compiler/rustc_type_ir/src/relate/combine.rs6
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs4
-rw-r--r--library/alloc/src/vec/mod.rs8
-rw-r--r--library/core/src/iter/traits/iterator.rs4
-rw-r--r--library/core/src/num/int_macros.rs26
-rw-r--r--library/core/src/num/uint_macros.rs22
-rw-r--r--library/core/src/pin.rs6
-rw-r--r--library/core/src/slice/mod.rs32
-rw-r--r--library/std/src/collections/hash/map.rs4
-rw-r--r--library/std/src/collections/hash/set.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs2
-rw-r--r--src/bootstrap/src/core/builder/mod.rs12
-rw-r--r--src/bootstrap/src/core/config/config.rs14
-rw-r--r--src/bootstrap/src/core/download.rs5
-rw-r--r--src/bootstrap/src/lib.rs55
-rw-r--r--src/librustdoc/clean/auto_trait.rs3
-rw-r--r--tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs13
-rw-r--r--tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr16
-rw-r--r--tests/ui/c-variadic/issue-32201.rs5
-rw-r--r--tests/ui/c-variadic/issue-32201.stderr11
-rw-r--r--tests/ui/error-codes/E0617.rs5
-rw-r--r--tests/ui/error-codes/E0617.stderr8
-rw-r--r--tests/ui/generic-associated-types/parse/in-trait-impl.rs2
-rw-r--r--tests/ui/generic-associated-types/parse/in-trait.rs2
-rw-r--r--tests/ui/impl-trait/impl-trait-plus-priority.rs2
-rw-r--r--tests/ui/parser/assoc/assoc-oddities-1.rs2
-rw-r--r--tests/ui/parser/assoc/assoc-oddities-2.rs2
-rw-r--r--tests/ui/parser/bounds-type.rs2
-rw-r--r--tests/ui/parser/impl-qpath.rs2
-rw-r--r--tests/ui/parser/issues/issue-17904.rs2
-rw-r--r--tests/ui/traits/const-traits/syntax.rs2
-rw-r--r--tests/ui/traits/const-traits/tilde-const-syntax.rs2
-rw-r--r--tests/ui/traits/const-traits/tilde-twice.rs2
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs (renamed from tests/ui/traits/next-solver/dont-remap-tait-substs.rs)0
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr (renamed from tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr)0
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr (renamed from tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr)0
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs (renamed from tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs)0
-rw-r--r--tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr34
-rw-r--r--tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs66
-rw-r--r--tests/ui/traits/next-solver/opaques/select-alias-bound-as-param.rs (renamed from tests/ui/traits/next-solver/select-alias-bound-as-param.rs)0
85 files changed, 535 insertions, 317 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 16a4f699177..9b7474c2208 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -34,6 +34,7 @@ use rustc_infer::infer::{
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::impls::{
@@ -502,7 +503,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
         for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) {
             // HIR typeck did not infer the regions of the opaque, so we instantiate
             // them with fresh inference variables.
-            let (key, hidden_ty) = tcx.fold_regions(data, |_, _| {
+            let (key, hidden_ty) = fold_regions(tcx, data, |_, _| {
                 self.next_nll_region_var_in_universe(
                     NllRegionVariableOrigin::Existential { from_forall: false },
                     ty::UniverseIndex::ROOT,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 0ddb4e110e3..99af5500ac6 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -18,6 +18,7 @@ use rustc_middle::mir::{
     TerminatorKind,
 };
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex};
 use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::Span;
@@ -1100,7 +1101,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let ty = ty.fold_with(&mut OpaqueFolder { tcx });
         let mut failed = false;
 
-        let ty = tcx.fold_regions(ty, |r, _depth| {
+        let ty = fold_regions(tcx, ty, |r, _depth| {
             let r_vid = self.to_region_vid(r);
             let r_scc = self.constraint_sccs.scc(r_vid);
 
@@ -1273,7 +1274,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        tcx.fold_regions(value, |r, _db| {
+        fold_regions(tcx, value, |r, _db| {
             let vid = self.to_region_vid(r);
             let scc = self.constraint_sccs.scc(vid);
             let repr = self.scc_representative(scc);
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 993d5d86333..7164a129235 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -3,6 +3,7 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::LocalDefId;
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
 use rustc_macros::extension;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
     self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
@@ -117,7 +118,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 });
             debug!(?opaque_type_key, ?arg_regions);
 
-            let concrete_type = infcx.tcx.fold_regions(concrete_type, |region, _| {
+            let concrete_type = fold_regions(infcx.tcx, concrete_type, |region, _| {
                 arg_regions
                     .iter()
                     .find(|&&(arg_vid, _)| self.eval_equal(region.as_var(), arg_vid))
@@ -204,7 +205,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        tcx.fold_regions(ty, |region, _| match *region {
+        fold_regions(tcx, ty, |region, _| match *region {
             ty::ReVar(vid) => {
                 let scc = self.constraint_sccs.scc(vid);
 
@@ -442,7 +443,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
         let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
 
         let mut seen = vec![tcx.lifetimes.re_static];
-        let canonical_args = tcx.fold_regions(args, |r1, _| {
+        let canonical_args = fold_regions(tcx, args, |r1, _| {
             if r1.is_error() {
                 r1
             } else if let Some(&r2) = seen.iter().find(|&&r2| {
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index b7aef71eb54..d83d6ade203 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -2,6 +2,7 @@ use rustc_index::IndexSlice;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::mir::visit::{MutVisitor, TyContext};
 use rustc_middle::mir::{Body, ConstOperand, Location, Promoted};
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Symbol;
 use tracing::{debug, instrument};
@@ -68,7 +69,7 @@ impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
         F: Fn() -> RegionCtxt,
     {
         let origin = NllRegionVariableOrigin::Existential { from_forall: false };
-        self.infcx.tcx.fold_regions(value, |_region, _depth| {
+        fold_regions(self.infcx.tcx, value, |_region, _depth| {
             self.infcx.next_nll_region_var(origin, || region_ctxt_fn())
         })
     }
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 67915371b1f..918efac2a20 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -8,6 +8,7 @@ use rustc_middle::bug;
 use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::query::NoSolution;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_span::Span;
 use rustc_trait_selection::traits::ScrubbedTraitError;
@@ -216,7 +217,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
     /// are dealt with during trait solving.
     fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
         if value.has_placeholders() {
-            self.tcx.fold_regions(value, |r, _| match *r {
+            fold_regions(self.tcx, value, |r, _| match *r {
                 ty::RePlaceholder(placeholder) => {
                     self.constraints.placeholder_region(self.infcx, placeholder)
                 }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index b4763acbefa..89e683b8ae3 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -26,6 +26,7 @@ use rustc_middle::mir::*;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::cast::CastTy;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
     self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
@@ -213,7 +214,7 @@ pub(crate) fn type_check<'a, 'tcx>(
 
             // Convert all regions to nll vars.
             let (opaque_type_key, hidden_type) =
-                infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| {
+                fold_regions(infcx.tcx, (opaque_type_key, hidden_type), |region, _| {
                     match region.kind() {
                         ty::ReVar(_) => region,
                         ty::RePlaceholder(placeholder) => {
@@ -2073,7 +2074,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         );
 
                         let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
-                        let unsize_to = tcx.fold_regions(ty, |r, _| {
+                        let unsize_to = fold_regions(tcx, ty, |r, _| {
                             if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
                         });
                         self.prove_trait_ref(
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index f1c23aa26a9..86a0111db49 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -26,7 +26,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_index::IndexVec;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_macros::extension;
-use rustc_middle::ty::fold::TypeFoldable;
+use rustc_middle::ty::fold::{TypeFoldable, fold_regions};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
     self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty,
@@ -824,7 +824,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        self.infcx.tcx.fold_regions(value, |region, _depth| {
+        fold_regions(self.infcx.tcx, value, |region, _depth| {
             let name = region.get_name_or_anon();
             debug!(?region, ?name);
 
@@ -906,7 +906,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        tcx.fold_regions(value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
+        fold_regions(tcx, value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
     }
 }
 
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 005053e4508..85eaae8a104 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -418,7 +418,9 @@ fn run_compiler(
                 return early_exit();
             }
 
-            if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() {
+            if sess.opts.unstable_opts.parse_crate_root_only
+                || sess.opts.unstable_opts.show_span.is_some()
+            {
                 return early_exit();
             }
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index c66572a9377..192dc1b4d22 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -17,7 +17,7 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::span_bug;
 use rustc_middle::ty::error::TypeErrorToStringExt;
-use rustc_middle::ty::fold::BottomUpFolder;
+use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
 use rustc_middle::ty::{
@@ -322,8 +322,12 @@ fn check_opaque_meets_bounds<'tcx>(
     };
     let param_env = tcx.param_env(defining_use_anchor);
 
-    // FIXME(#132279): This should eventually use the already defined hidden types.
-    let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
+    // FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed.
+    let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() {
+        TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)
+    } else {
+        TypingMode::analysis_in_body(tcx, defining_use_anchor)
+    });
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
     let args = match origin {
@@ -346,7 +350,7 @@ fn check_opaque_meets_bounds<'tcx>(
     // FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it
     // here rather than using ReErased.
     let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args);
-    let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() {
+    let hidden_ty = fold_regions(tcx, hidden_ty, |re, _dbi| match re.kind() {
         ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
         _ => re,
     });
@@ -417,7 +421,11 @@ fn check_opaque_meets_bounds<'tcx>(
     let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
     ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
 
-    if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = origin {
+    if infcx.next_trait_solver() {
+        Ok(())
+    } else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
+        origin
+    {
         // HACK: this should also fall through to the hidden type check below, but the original
         // implementation had a bug where equivalent lifetimes are not identical. This caused us
         // to reject existing stable code that is otherwise completely fine. The real fix is to
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 93be3e06e5d..cf062e82cb6 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -34,6 +34,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::query::Providers;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
@@ -1415,7 +1416,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
                 GenericParamKind::Lifetime { .. } => true,
                 _ => false,
             });
-            let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
+            let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
                 ty::ReErased => {
                     if has_region_params {
                         ty::Region::new_error_with_message(
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 816761fd00f..18fb5bfd912 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -5,6 +5,7 @@ use rustc_hir as hir;
 use rustc_hir::HirId;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::plumbing::CyclePlaceholder;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
@@ -113,7 +114,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
         // so no need for ConstArg.
         Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => {
             let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id));
-            let ty = tcx.fold_regions(ty, |r, _| {
+            let ty = fold_regions(tcx, ty, |r, _| {
                 if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r }
             });
             let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false, None) {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 01276abec22..cf780a3d3bb 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -37,6 +37,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
 use rustc_middle::ty::{
     self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
@@ -1569,7 +1570,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                     infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
                                 );
 
-                                let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
+                                let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
                                 // FIXME: Don't bother dealing with non-lifetime binders here...
                                 if value.has_escaping_bound_vars() {
                                     return false;
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 5b0165bf993..c0fb94d2cb2 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -5,6 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, TyCtxt, TypingMode};
 use rustc_span::def_id::LocalDefId;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
@@ -75,7 +76,7 @@ fn diagnostic_hir_wf_check<'tcx>(
             // This visitor can walk into binders, resulting in the `tcx_ty` to
             // potentially reference escaping bound variables. We simply erase
             // those here.
-            let tcx_ty = self.tcx.fold_regions(tcx_ty, |r, _| {
+            let tcx_ty = fold_regions(self.tcx, tcx_ty, |r, _| {
                 if r.is_bound() { self.tcx.lifetimes.re_erased } else { r }
             });
             let cause = traits::ObligationCause::new(
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 3669100ed91..6001816ffbe 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -79,6 +79,11 @@ hir_typeck_field_multiply_specified_in_initializer =
     .label = used more than once
     .previous_use_label = first use of `{$ident}`
 
+hir_typeck_fn_item_to_variadic_function = can't pass a function item to a variadic function
+    .suggestion = use a function pointer instead
+    .help = a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+    .note = for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
+
 hir_typeck_fru_expr = this expression does not end in a comma...
 hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
 hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 4f579b05d83..fa27abd270f 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -797,3 +797,15 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> {
     #[note(hir_typeck_teach_help)]
     pub(crate) teach: bool,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)]
+#[help]
+#[note]
+pub(crate) struct PassFnItemToVariadicFunction {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " as {replace}", applicability = "machine-applicable", style = "verbose")]
+    pub sugg_span: Span,
+    pub replace: String,
+}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index f8f6564cf14..63777f82f1a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -472,9 +472,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
                     }
                     ty::FnDef(..) => {
-                        let ptr_ty = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
-                        let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
-                        variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
+                        let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
+                        let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
+
+                        let fn_item_spa = arg.span;
+                        tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction {
+                            span: fn_item_spa,
+                            sugg_span: fn_item_spa.shrink_to_hi(),
+                            replace: fn_ptr,
+                        });
                     }
                     _ => {}
                 }
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 5aaad3636a2..039c117c099 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1574,7 +1574,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         // Thus we need to prevent them from trying to match the `&_` autoref
                         // candidates that get created for `&self` trait methods.
                         ty::Alias(ty::Opaque, alias_ty)
-                            if self.infcx.can_define_opaque_ty(alias_ty.def_id)
+                            if !self.next_trait_solver()
+                                && self.infcx.can_define_opaque_ty(alias_ty.def_id)
                                 && !xform_self_ty.is_ty_var() =>
                         {
                             return ProbeResult::NoMatch;
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 2f436ce77a4..e17a68c8692 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -12,7 +12,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::span_bug;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
-use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
+use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, fold_regions};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable};
 use rustc_span::Span;
@@ -827,7 +827,10 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         // no reason to keep regions around. They will be repopulated during MIR
         // borrowck, and specifically region constraints will be populated during
         // MIR typeck which is run on the new body.
-        value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased);
+        //
+        // We're not using `tcx.erase_regions` as that also anonymizes bound variables,
+        // regressing borrowck diagnostics.
+        value = fold_regions(tcx, value, |_, _| tcx.lifetimes.re_erased);
 
         // Normalize consts in writeback, because GCE doesn't normalize eagerly.
         if tcx.features().generic_const_exprs() {
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index 1968ed34752..5fc9b679c8a 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::{DUMMY_SP, ErrorGuaranteed};
 
-use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin};
+use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
 
 impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
     type Interner = TyCtxt<'tcx>;
@@ -87,6 +87,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
     }
 
+    fn next_region_infer(&self) -> ty::Region<'tcx> {
+        self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
+    }
+
     fn next_ty_infer(&self) -> Ty<'tcx> {
         self.next_ty_var(DUMMY_SP)
     }
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 6af49accc84..e454a88e847 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -9,7 +9,7 @@ use rustc_data_structures::graph::implementation::{
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::unord::UnordSet;
 use rustc_index::{IndexSlice, IndexVec};
-use rustc_middle::ty::fold::TypeFoldable;
+use rustc_middle::ty::fold::{TypeFoldable, fold_regions};
 use rustc_middle::ty::{
     self, ReBound, ReEarlyParam, ReErased, ReError, ReLateParam, RePlaceholder, ReStatic, ReVar,
     Region, RegionVid, Ty, TyCtxt,
@@ -974,7 +974,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r))
+        fold_regions(tcx, value, |r, _db| self.resolve_region(tcx, r))
     }
 
     fn value(&self, rid: RegionVid) -> &VarValue<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 555c1022a8a..544f941dda5 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -33,7 +33,7 @@ use rustc_middle::traits::select;
 pub use rustc_middle::ty::IntVarValue;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{
-    BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable,
+    BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions,
 };
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
@@ -990,11 +990,17 @@ impl<'tcx> InferCtxt<'tcx> {
 
     #[inline(always)]
     pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
+        debug_assert!(!self.next_trait_solver());
         match self.typing_mode() {
             TypingMode::Analysis { defining_opaque_types } => {
                 id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
             }
-            TypingMode::Coherence | TypingMode::PostAnalysis => false,
+            // FIXME(#132279): This function is quite weird in post-analysis
+            // and post-borrowck analysis mode. We may need to modify its uses
+            // to support PostBorrowckAnalysis in the old solver as well.
+            TypingMode::Coherence
+            | TypingMode::PostBorrowckAnalysis { .. }
+            | TypingMode::PostAnalysis => false,
         }
     }
 
@@ -1165,7 +1171,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 }
                 if value.has_infer_regions() {
                     let guar = self.dcx().delayed_bug(format!("`{value:?}` is not fully resolved"));
-                    Ok(self.tcx.fold_regions(value, |re, _| {
+                    Ok(fold_regions(self.tcx, value, |re, _| {
                         if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re }
                     }))
                 } else {
@@ -1276,7 +1282,6 @@ impl<'tcx> InferCtxt<'tcx> {
     /// using canonicalization or carrying this inference context around.
     pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
         let typing_mode = match self.typing_mode() {
-            ty::TypingMode::Coherence => ty::TypingMode::Coherence,
             // FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible
             // to handle them without proper canonicalization. This means we may cause cycle
             // errors and fail to reveal opaques while inside of bodies. We should rename this
@@ -1284,7 +1289,9 @@ impl<'tcx> InferCtxt<'tcx> {
             ty::TypingMode::Analysis { defining_opaque_types: _ } => {
                 TypingMode::non_body_analysis()
             }
-            ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis,
+            mode @ (ty::TypingMode::Coherence
+            | ty::TypingMode::PostBorrowckAnalysis { .. }
+            | ty::TypingMode::PostAnalysis) => mode,
         };
         ty::TypingEnv { typing_mode, param_env }
     }
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index a608ea1ad57..b64686afd23 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -98,6 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
         span: Span,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
+        debug_assert!(!self.next_trait_solver());
         let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
@@ -546,7 +547,9 @@ impl<'tcx> InferCtxt<'tcx> {
                     );
                 }
             }
-            ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"),
+            mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => {
+                bug!("insert hidden type in {mode:?}")
+            }
         }
 
         Ok(())
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 6beae14100d..c1b2d856252 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -712,7 +712,7 @@ fn test_unstable_options_tracking_hash() {
     untracked!(no_analysis, true);
     untracked!(no_leak_check, true);
     untracked!(no_parallel_backend, true);
-    untracked!(parse_only, true);
+    untracked!(parse_crate_root_only, true);
     // `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
     untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
     untracked!(print_codegen_stats, true);
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 86abeb50382..8a708368713 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -17,6 +17,7 @@ use smallvec::SmallVec;
 
 use super::{ConstValue, SourceInfo};
 use crate::mir;
+use crate::ty::fold::fold_regions;
 use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt};
 
 rustc_index::newtype_index! {
@@ -315,7 +316,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
     /// All regions of `ty` must be of kind `ReVar` and must represent
     /// universal regions *external* to the closure.
     pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
-        let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
+        let inner = fold_regions(tcx, ty, |r, depth| match r.kind() {
             ty::ReVar(vid) => {
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::new(vid.index()),
@@ -334,7 +335,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
         tcx: TyCtxt<'tcx>,
         mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
     ) -> Ty<'tcx> {
-        tcx.fold_regions(self.inner, |r, depth| match r.kind() {
+        fold_regions(tcx, self.inner, |r, depth| match r.kind() {
             ty::ReBound(debruijn, br) => {
                 debug_assert_eq!(debruijn, depth);
                 map(ty::RegionVid::new(br.var.index()))
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 7adbd556141..1b073d3c466 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -2,9 +2,9 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::def_id::DefId;
 use rustc_type_ir::data_structures::DelayedMap;
 pub use rustc_type_ir::fold::{
-    FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region, shift_vars,
+    FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions, shift_region,
+    shift_vars,
 };
-use tracing::{debug, instrument};
 
 use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
 
@@ -51,85 +51,6 @@ where
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// Region folder
-
-impl<'tcx> TyCtxt<'tcx> {
-    /// Folds the escaping and free regions in `value` using `f`.
-    pub fn fold_regions<T>(
-        self,
-        value: T,
-        mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
-    ) -> T
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>,
-    {
-        value.fold_with(&mut RegionFolder::new(self, &mut f))
-    }
-}
-
-/// Folds over the substructure of a type, visiting its component
-/// types and all regions that occur *free* within it.
-///
-/// That is, function pointer types and trait object can introduce
-/// new bound regions which are not visited by this visitors as
-/// they are not free; only regions that occur free will be
-/// visited by `fld_r`.
-pub struct RegionFolder<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-
-    /// Stores the index of a binder *just outside* the stuff we have
-    /// visited. So this begins as INNERMOST; when we pass through a
-    /// binder, it is incremented (via `shift_in`).
-    current_index: ty::DebruijnIndex,
-
-    /// Callback invokes for each free region. The `DebruijnIndex`
-    /// points to the binder *just outside* the ones we have passed
-    /// through.
-    fold_region_fn:
-        &'a mut (dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx> + 'a),
-}
-
-impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
-    #[inline]
-    pub fn new(
-        tcx: TyCtxt<'tcx>,
-        fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
-    ) -> RegionFolder<'a, 'tcx> {
-        RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn }
-    }
-}
-
-impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
-        self.current_index.shift_in(1);
-        let t = t.super_fold_with(self);
-        self.current_index.shift_out(1);
-        t
-    }
-
-    #[instrument(skip(self), level = "debug", ret)]
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
-            ty::ReBound(debruijn, _) if debruijn < self.current_index => {
-                debug!(?self.current_index, "skipped bound region");
-                r
-            }
-            _ => {
-                debug!(?self.current_index, "folding free region");
-                (self.fold_region_fn)(r, self.current_index)
-            }
-        }
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
 // Bound vars replacer
 
 /// A delegate used when instantiating bound vars.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 55a7a837b6d..797ac9685b1 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -21,6 +21,7 @@ use tracing::{debug, instrument};
 use super::TypingEnv;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::query::Providers;
+use crate::ty::fold::fold_regions;
 use crate::ty::layout::{FloatExt, IntegerExt};
 use crate::ty::{
     self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
@@ -735,7 +736,7 @@ impl<'tcx> TyCtxt<'tcx> {
             .filter(|decl| !decl.ignore_for_traits)
             .map(move |decl| {
                 let mut vars = vec![];
-                let ty = self.fold_regions(decl.ty, |re, debruijn| {
+                let ty = fold_regions(self, decl.ty, |re, debruijn| {
                     assert_eq!(re, self.lifetimes.re_erased);
                     let var = ty::BoundVar::from_usize(vars.len());
                     vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index adac35b57cd..198ccb000f3 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -339,7 +339,9 @@ where
 
         match self.typing_mode() {
             TypingMode::Coherence => {}
-            TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
+            TypingMode::Analysis { .. }
+            | TypingMode::PostBorrowckAnalysis { .. }
+            | TypingMode::PostAnalysis => {
                 self.discard_impls_shadowed_by_env(goal, &mut candidates);
             }
         }
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 40d1576256e..70ceb22bfea 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -644,6 +644,12 @@ where
         }
     }
 
+    pub(super) fn next_region_var(&mut self) -> I::Region {
+        let region = self.delegate.next_region_infer();
+        self.inspect.add_var_value(region);
+        region
+    }
+
     pub(super) fn next_ty_infer(&mut self) -> I::Ty {
         let ty = self.delegate.next_ty_infer();
         self.inspect.add_var_value(ty);
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 5c54656cc59..ebf1013db1e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -23,7 +23,7 @@ mod trait_goals;
 
 use rustc_type_ir::inherent::*;
 pub use rustc_type_ir::solve::*;
-use rustc_type_ir::{self as ty, Interner};
+use rustc_type_ir::{self as ty, Interner, TypingMode};
 use tracing::instrument;
 
 pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt};
@@ -321,6 +321,19 @@ where
             Ok(ct)
         }
     }
+
+    fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool {
+        match self.typing_mode() {
+            // Opaques are never rigid outside of analysis mode.
+            TypingMode::Coherence | TypingMode::PostAnalysis => false,
+            // During analysis, opaques are rigid unless they may be defined by
+            // the current body.
+            TypingMode::Analysis { defining_opaque_types: non_rigid_opaques }
+            | TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
+                !def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
+            }
+        }
+    }
 }
 
 fn response_no_constraints_raw<I: Interner>(
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 33bd1cf2f56..f5b1b23b8e9 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -6,7 +6,7 @@ mod weak_types;
 use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
-use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _};
+use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
 use tracing::instrument;
 
 use crate::delegate::SolverDelegate;
@@ -71,21 +71,10 @@ where
                 Ok(())
             }
             ty::AliasTermKind::OpaqueTy => {
-                match self.typing_mode() {
-                    // Opaques are never rigid outside of analysis mode.
-                    TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution),
-                    // During analysis, opaques are only rigid if we may not define it.
-                    TypingMode::Analysis { defining_opaque_types } => {
-                        if rigid_alias
-                            .def_id
-                            .as_local()
-                            .is_some_and(|def_id| defining_opaque_types.contains(&def_id))
-                        {
-                            Err(NoSolution)
-                        } else {
-                            Ok(())
-                        }
-                    }
+                if self.opaque_type_is_rigid(rigid_alias.def_id) {
+                    Ok(())
+                } else {
+                    Err(NoSolution)
                 }
             }
             // FIXME(generic_const_exprs): we would need to support generic consts here
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index 336bcb9df33..26a8a22d77e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -2,6 +2,7 @@
 //! behaves differently depending on the current `TypingMode`.
 
 use rustc_index::bit_set::GrowableBitSet;
+use rustc_type_ir::fold::fold_regions;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::{self as ty, Interner, TypingMode};
 
@@ -95,6 +96,26 @@ where
                 );
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
+            TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
+                let Some(def_id) = opaque_ty.def_id.as_local() else {
+                    return Err(NoSolution);
+                };
+
+                if !defined_opaque_types.contains(&def_id) {
+                    return Err(NoSolution);
+                }
+
+                let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
+                // FIXME: Actually use a proper binder here instead of relying on `ReErased`.
+                //
+                // This is also probably unsound or sth :shrug:
+                let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
+                    ty::ReErased => self.next_region_var(),
+                    _ => re,
+                });
+                self.eq(goal.param_env, expected, actual)?;
+                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            }
             TypingMode::PostAnalysis => {
                 // FIXME: Add an assertion that opaque type storage is empty.
                 let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 096dc32ccc9..6641d2bf924 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -69,7 +69,9 @@ where
             // it's not a real impl.
             (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() {
                 TypingMode::Coherence => Certainty::AMBIGUOUS,
-                TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution),
+                TypingMode::Analysis { .. }
+                | TypingMode::PostBorrowckAnalysis { .. }
+                | TypingMode::PostAnalysis => return Err(NoSolution),
             },
 
             // Impl matches polarity
@@ -174,20 +176,7 @@ where
         // ideally we want to avoid, since we can make progress on this goal
         // via an alias bound or a locally-inferred hidden type instead.
         if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
-            match ecx.typing_mode() {
-                TypingMode::Coherence | TypingMode::PostAnalysis => {
-                    unreachable!("rigid opaque outside of analysis: {goal:?}");
-                }
-                TypingMode::Analysis { defining_opaque_types } => {
-                    if opaque_ty
-                        .def_id
-                        .as_local()
-                        .is_some_and(|def_id| defining_opaque_types.contains(&def_id))
-                    {
-                        return Err(NoSolution);
-                    }
-                }
-            }
+            debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id));
         }
 
         ecx.probe_and_evaluate_goal_for_constituent_tys(
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 0124397ea46..cb6d539cdf9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1208,7 +1208,7 @@ impl Options {
 
     /// Returns `true` if there will be an output file generated.
     pub fn will_create_output_file(&self) -> bool {
-        !self.unstable_opts.parse_only && // The file is just being parsed
+        !self.unstable_opts.parse_crate_root_only && // The file is just being parsed
             self.unstable_opts.ls.is_empty() // The file is just being queried
     }
 
@@ -1864,7 +1864,7 @@ fn parse_output_types(
     matches: &getopts::Matches,
 ) -> OutputTypes {
     let mut output_types = BTreeMap::new();
-    if !unstable_opts.parse_only {
+    if !unstable_opts.parse_crate_root_only {
         for list in matches.opt_strs("emit") {
             for output_type in list.split(',') {
                 let (shorthand, path) = split_out_file_name(output_type);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index a2d75917c82..25f75ae12e8 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1937,8 +1937,9 @@ options! {
         "support compiling tests with panic=abort (default: no)"),
     panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED],
         "panic strategy for panics in drops"),
-    parse_only: bool = (false, parse_bool, [UNTRACKED],
-        "parse only; do not compile, assemble, or link (default: no)"),
+    parse_crate_root_only: bool = (false, parse_bool, [UNTRACKED],
+        "parse the crate root file only; do not parse other files, compile, assemble, or link \
+        (default: no)"),
     patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED],
         "nop padding at function entry"),
     plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -2036,7 +2037,7 @@ written to standard error output)"),
     shell_argfiles: bool = (false, parse_bool, [UNTRACKED],
         "allow argument files to be specified with POSIX \"shell-style\" argument quoting"),
     show_span: Option<String> = (None, parse_opt_string, [TRACKED],
-        "show spans for compiler debugging (expr|pat|ty)"),
+        "show spans in the crate root file, for compiler debugging (expr|pat|ty)"),
     simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
         to rust's source base directory. only meant for testing purposes"),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
index 75054b22153..218d2e753ef 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
@@ -3,6 +3,7 @@
 
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 use tracing::instrument;
@@ -83,7 +84,7 @@ pub fn find_param_with_region<'tcx>(
             // May return None; sometimes the tables are not yet populated.
             let ty = fn_sig.inputs()[index];
             let mut found_anon_region = false;
-            let new_param_ty = tcx.fold_regions(ty, |r, _| {
+            let new_param_ty = fold_regions(tcx, ty, |r, _| {
                 if r == anon_region {
                     found_anon_region = true;
                     replace_region
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index 09bba24ba61..97cde67799c 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -205,7 +205,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
             // transmute checking and polymorphic MIR optimizations could
             // get a result which isn't correct for all monomorphizations.
             match self.typing_mode() {
-                TypingMode::Coherence | TypingMode::Analysis { .. } => false,
+                TypingMode::Coherence
+                | TypingMode::Analysis { .. }
+                | TypingMode::PostBorrowckAnalysis { .. } => false,
                 TypingMode::PostAnalysis => {
                     let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
                     !poly_trait_ref.still_further_specializable()
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index 4d3d8c66e62..e99c5eacbd8 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -118,9 +118,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
     // Opaques are treated as rigid outside of `TypingMode::PostAnalysis`,
     // so we can ignore those.
     match infcx.typing_mode() {
-        TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
-            flags.remove(ty::TypeFlags::HAS_TY_OPAQUE)
-        }
+        // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
+        TypingMode::Coherence
+        | TypingMode::Analysis { .. }
+        | TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE),
         TypingMode::PostAnalysis => {}
     }
 
@@ -213,9 +214,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
             ty::Opaque => {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.selcx.infcx.typing_mode() {
-                    TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
-                        ty.super_fold_with(self)
-                    }
+                    // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis
+                    TypingMode::Coherence
+                    | TypingMode::Analysis { .. }
+                    | TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self),
                     TypingMode::PostAnalysis => {
                         let recursion_limit = self.cx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 2864f277df5..01f6cccb375 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -975,7 +975,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     // transmute checking and polymorphic MIR optimizations could
                     // get a result which isn't correct for all monomorphizations.
                     match selcx.infcx.typing_mode() {
-                        TypingMode::Coherence | TypingMode::Analysis { .. } => {
+                        TypingMode::Coherence
+                        | TypingMode::Analysis { .. }
+                        | TypingMode::PostBorrowckAnalysis { .. } => {
                             debug!(
                                 assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
                                 ?obligation.predicate,
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 22cfbb2c840..2ef9d5421ba 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -216,9 +216,9 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
             ty::Opaque => {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.infcx.typing_mode() {
-                    TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => {
-                        ty.try_super_fold_with(self)?
-                    }
+                    TypingMode::Coherence
+                    | TypingMode::Analysis { .. }
+                    | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?,
 
                     TypingMode::PostAnalysis => {
                         let args = data.args.try_fold_with(self)?;
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 3b64a47181a..50c4f9eff6f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -25,6 +25,7 @@ use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds};
 pub use rustc_middle::traits::select::*;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::TypeErrorToStringExt;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
 use rustc_middle::ty::{
     self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
@@ -1470,7 +1471,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let obligation = &stack.obligation;
         match self.infcx.typing_mode() {
             TypingMode::Coherence => {}
-            TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()),
+            TypingMode::Analysis { .. }
+            | TypingMode::PostBorrowckAnalysis { .. }
+            | TypingMode::PostAnalysis => return Ok(()),
         }
 
         debug!("is_knowable()");
@@ -1517,6 +1520,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             TypingMode::Analysis { defining_opaque_types } => {
                 defining_opaque_types.is_empty() || !pred.has_opaque_types()
             }
+            // The hidden types of `defined_opaque_types` is not local to the current
+            // inference context, so we can freely move this to the global cache.
+            TypingMode::PostBorrowckAnalysis { .. } => true,
             // The global cache is only used if there are no opaque types in
             // the defining scope or we're outside of analysis.
             //
@@ -3209,7 +3215,7 @@ fn bind_coroutine_hidden_types_above<'tcx>(
             // Only remap erased regions if we use them.
             if considering_regions {
                 bty = bty.map_bound(|ty| {
-                    tcx.fold_regions(ty, |r, current_depth| match r.kind() {
+                    fold_regions(tcx, ty, |r, current_depth| match r.kind() {
                         ty::ReErased => {
                             let br = ty::BoundRegion {
                                 var: ty::BoundVar::from_u32(counter),
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 5cd10e90538..c4637f1293c 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -6,6 +6,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 
@@ -86,7 +87,8 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
                         }
                     }
                     // FIXME: This could use a real folder, I guess.
-                    let remapped_wf_tys = tcx.fold_regions(
+                    let remapped_wf_tys = fold_regions(
+                        tcx,
                         tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(),
                         |region, _| {
                             // If `region` is a `ReLateParam` that is captured by the
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 8798772e398..1a98c85bee9 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -149,7 +149,8 @@ fn resolve_associated_item<'tcx>(
                 // get a result which isn't correct for all monomorphizations.
                 match typing_env.typing_mode {
                     ty::TypingMode::Coherence
-                    | ty::TypingMode::Analysis { defining_opaque_types: _ } => false,
+                    | ty::TypingMode::Analysis { .. }
+                    | ty::TypingMode::PostBorrowckAnalysis { .. } => false,
                     ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(),
                 }
             };
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 61f2262dfe8..774f0660258 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -5,6 +5,7 @@ use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{
     self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast,
 };
@@ -197,7 +198,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             // We have entered some binders as we've walked into the
             // bounds of the RPITIT. Shift these binders back out when
             // constructing the top-level projection predicate.
-            let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| {
+            let shifted_alias_ty = fold_regions(self.tcx, unshifted_alias_ty, |re, depth| {
                 if let ty::ReBound(index, bv) = re.kind() {
                     if depth != ty::INNERMOST {
                         return ty::Region::new_error_with_message(
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index 8209d6f5fe3..d337a1a8ad9 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -49,7 +49,7 @@ use std::mem;
 
 use rustc_index::{Idx, IndexVec};
 use thin_vec::ThinVec;
-use tracing::instrument;
+use tracing::{debug, instrument};
 
 use crate::data_structures::Lrc;
 use crate::inherent::*;
@@ -431,3 +431,75 @@ where
         value.fold_with(&mut Shifter::new(cx, amount))
     }
 }
+
+///////////////////////////////////////////////////////////////////////////
+// Region folder
+
+pub fn fold_regions<I: Interner, T>(
+    cx: I,
+    value: T,
+    mut f: impl FnMut(I::Region, ty::DebruijnIndex) -> I::Region,
+) -> T
+where
+    T: TypeFoldable<I>,
+{
+    value.fold_with(&mut RegionFolder::new(cx, &mut f))
+}
+
+/// Folds over the substructure of a type, visiting its component
+/// types and all regions that occur *free* within it.
+///
+/// That is, function pointer types and trait object can introduce
+/// new bound regions which are not visited by this visitors as
+/// they are not free; only regions that occur free will be
+/// visited by `fld_r`.
+pub struct RegionFolder<'a, I: Interner> {
+    cx: I,
+
+    /// Stores the index of a binder *just outside* the stuff we have
+    /// visited. So this begins as INNERMOST; when we pass through a
+    /// binder, it is incremented (via `shift_in`).
+    current_index: ty::DebruijnIndex,
+
+    /// Callback invokes for each free region. The `DebruijnIndex`
+    /// points to the binder *just outside* the ones we have passed
+    /// through.
+    fold_region_fn: &'a mut (dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region + 'a),
+}
+
+impl<'a, I: Interner> RegionFolder<'a, I> {
+    #[inline]
+    pub fn new(
+        cx: I,
+        fold_region_fn: &'a mut dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region,
+    ) -> RegionFolder<'a, I> {
+        RegionFolder { cx, current_index: ty::INNERMOST, fold_region_fn }
+    }
+}
+
+impl<'a, I: Interner> TypeFolder<I> for RegionFolder<'a, I> {
+    fn cx(&self) -> I {
+        self.cx
+    }
+
+    fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
+        self.current_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.current_index.shift_out(1);
+        t
+    }
+
+    #[instrument(skip(self), level = "debug", ret)]
+    fn fold_region(&mut self, r: I::Region) -> I::Region {
+        match r.kind() {
+            ty::ReBound(debruijn, _) if debruijn < self.current_index => {
+                debug!(?self.current_index, "skipped bound region");
+                r
+            }
+            _ => {
+                debug!(?self.current_index, "folding free region");
+                (self.fold_region_fn)(r, self.current_index)
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index 13ad505bc04..a892b88c2c6 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -63,6 +63,12 @@ pub enum TypingMode<I: Interner> {
     /// }
     /// ```
     Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
+    /// Any analysis after borrowck for a given body should be able to use all the
+    /// hidden types defined by borrowck, without being able to define any new ones.
+    ///
+    /// This is currently only used by the new solver, but should be implemented in
+    /// the old solver as well.
+    PostBorrowckAnalysis { defined_opaque_types: I::DefiningOpaqueTypes },
     /// After analysis, mostly during codegen and MIR optimizations, we're able to
     /// reveal all opaque types. As the concrete type should *never* be observable
     /// directly by the user, this should not be used by checks which may expose
@@ -85,6 +91,12 @@ impl<I: Interner> TypingMode<I> {
     pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
         TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
     }
+
+    pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
+        TypingMode::PostBorrowckAnalysis {
+            defined_opaque_types: cx.opaque_types_defined_by(body_def_id),
+        }
+    }
 }
 
 pub trait InferCtxtLike: Sized {
@@ -126,6 +138,7 @@ pub trait InferCtxtLike: Sized {
         vid: ty::RegionVid,
     ) -> <Self::Interner as Interner>::Region;
 
+    fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
     fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
     fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
     fn fresh_args_for_item(
diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs
index c8abfee314e..d49f8d3093d 100644
--- a/compiler/rustc_type_ir/src/relate/combine.rs
+++ b/compiler/rustc_type_ir/src/relate/combine.rs
@@ -136,9 +136,9 @@ where
                     relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
                     Ok(a)
                 }
-                TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
-                    structurally_relate_tys(relation, a, b)
-                }
+                TypingMode::Analysis { .. }
+                | TypingMode::PostBorrowckAnalysis { .. }
+                | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
             }
         }
 
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index 59f10b09c73..0bc65cdbc55 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -452,7 +452,7 @@ impl<T: Ord> BinaryHeap<T> {
     ///
     /// The binary heap will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the binary heap will not allocate.
+    /// `capacity`. If `capacity` is zero, the binary heap will not allocate.
     ///
     /// # Examples
     ///
@@ -496,7 +496,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
     ///
     /// The binary heap will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the binary heap will not allocate.
+    /// `capacity`. If `capacity` is zero, the binary heap will not allocate.
     ///
     /// # Examples
     ///
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 990b7e8f761..87e730b13f8 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -427,7 +427,7 @@ impl<T> Vec<T> {
     ///
     /// The vector will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the vector will not allocate.
+    /// `capacity`. If `capacity` is zero, the vector will not allocate.
     ///
     /// It is important to note that although the returned vector has the
     /// minimum *capacity* specified, the vector will have a zero *length*. For
@@ -487,7 +487,7 @@ impl<T> Vec<T> {
     ///
     /// The vector will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the vector will not allocate.
+    /// `capacity`. If `capacity` is zero, the vector will not allocate.
     ///
     /// # Errors
     ///
@@ -745,7 +745,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// The vector will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the vector will not allocate.
+    /// `capacity`. If `capacity` is zero, the vector will not allocate.
     ///
     /// It is important to note that although the returned vector has the
     /// minimum *capacity* specified, the vector will have a zero *length*. For
@@ -808,7 +808,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// The vector will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the vector will not allocate.
+    /// `capacity`. If `capacity` is zero, the vector will not allocate.
     ///
     /// # Errors
     ///
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index ffaf1bc56e9..38dfbbef393 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1553,7 +1553,7 @@ pub trait Iterator {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0. This check will most probably get changed to a
+    /// Panics if `N` is zero. This check will most probably get changed to a
     /// compile time error before this method gets stabilized.
     ///
     /// ```should_panic
@@ -3454,7 +3454,7 @@ pub trait Iterator {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0.
+    /// Panics if `N` is zero.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 64dcb4c91e6..6c50f21a773 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1828,7 +1828,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -1986,7 +1986,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2014,7 +2014,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2042,7 +2042,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2069,7 +2069,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2526,7 +2526,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2557,7 +2557,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2588,7 +2588,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2619,7 +2619,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2887,7 +2887,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN`
+        /// This function will panic if `rhs` is zero or if `self` is `Self::MIN`
         /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag.
         ///
         /// # Examples
@@ -2926,7 +2926,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` and
+        /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` and
         /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag.
         ///
         /// # Examples
@@ -2975,7 +2975,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN`
+        /// This function will panic if `rhs` is zero or if `self` is `Self::MIN`
         /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag.
         ///
         /// # Examples
@@ -3019,7 +3019,7 @@ macro_rules! int_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN`
+        /// This function will panic if `rhs` is zero or if `self` is `Self::MIN`
         /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag.
         ///
         /// # Examples
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 0383c13fa08..23aace0cd66 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1877,7 +1877,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2034,7 +2034,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2063,7 +2063,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2091,7 +2091,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2121,7 +2121,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2545,7 +2545,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2576,7 +2576,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2604,7 +2604,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2635,7 +2635,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2872,7 +2872,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
@@ -2900,7 +2900,7 @@ macro_rules! uint_impl {
         ///
         /// # Panics
         ///
-        /// This function will panic if `rhs` is 0.
+        /// This function will panic if `rhs` is zero.
         ///
         /// # Examples
         ///
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index c14c49a0d92..43cebf4881e 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -373,9 +373,9 @@
 //! exactly what we did with our `AddrTracker` example above. Without doing this, you *must not*
 //! rely on pinning-related guarantees to apply to your type!
 //!
-//! If need to truly pin a value of a foreign or built-in type that implements [`Unpin`], you'll
-//! need to create your own wrapper type around the [`Unpin`] type you want to pin and then
-//! opts-out of [`Unpin`] using [`PhantomPinned`].
+//! If you really need to pin a value of a foreign or built-in type that implements [`Unpin`],
+//! you'll need to create your own wrapper type around the [`Unpin`] type you want to pin and then
+//! opt-out of [`Unpin`] using [`PhantomPinned`].
 //!
 //! Exposing access to the inner field which you want to remain pinned must then be carefully
 //! considered as well! Remember, exposing a method that gives access to a
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index ee91479bb1a..7afdb680df6 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1077,7 +1077,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `size` is 0.
+    /// Panics if `size` is zero.
     ///
     /// # Examples
     ///
@@ -1133,7 +1133,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `chunk_size` is 0.
+    /// Panics if `chunk_size` is zero.
     ///
     /// # Examples
     ///
@@ -1168,7 +1168,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `chunk_size` is 0.
+    /// Panics if `chunk_size` is zero.
     ///
     /// # Examples
     ///
@@ -1210,7 +1210,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `chunk_size` is 0.
+    /// Panics if `chunk_size` is zero.
     ///
     /// # Examples
     ///
@@ -1249,7 +1249,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `chunk_size` is 0.
+    /// Panics if `chunk_size` is zero.
     ///
     /// # Examples
     ///
@@ -1326,7 +1326,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// Panics if `N` is zero. This check will most probably get changed to a compile time
     /// error before this method gets stabilized.
     ///
     /// # Examples
@@ -1372,7 +1372,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// Panics if `N` is zero. This check will most probably get changed to a compile time
     /// error before this method gets stabilized.
     ///
     /// # Examples
@@ -1410,7 +1410,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// Panics if `N` is zero. This check will most probably get changed to a compile time
     /// error before this method gets stabilized.
     ///
     /// # Examples
@@ -1486,7 +1486,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// Panics if `N` is zero. This check will most probably get changed to a compile time
     /// error before this method gets stabilized.
     ///
     /// # Examples
@@ -1527,7 +1527,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// Panics if `N` is zero. This check will most probably get changed to a compile time
     /// error before this method gets stabilized.
     ///
     /// # Examples
@@ -1571,7 +1571,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// Panics if `N` is zero. This check will most probably get changed to a compile time
     /// error before this method gets stabilized.
     ///
     /// # Examples
@@ -1606,7 +1606,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// Panics if `N` is zero. This check will most probably get changed to a compile time
     /// error before this method gets stabilized.
     ///
     /// # Examples
@@ -1642,7 +1642,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `chunk_size` is 0.
+    /// Panics if `chunk_size` is zero.
     ///
     /// # Examples
     ///
@@ -1677,7 +1677,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `chunk_size` is 0.
+    /// Panics if `chunk_size` is zero.
     ///
     /// # Examples
     ///
@@ -1720,7 +1720,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `chunk_size` is 0.
+    /// Panics if `chunk_size` is zero.
     ///
     /// # Examples
     ///
@@ -1760,7 +1760,7 @@ impl<T> [T] {
     ///
     /// # Panics
     ///
-    /// Panics if `chunk_size` is 0.
+    /// Panics if `chunk_size` is zero.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 24bbc2f32cf..09c0b61fb2b 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -235,7 +235,7 @@ impl<K, V> HashMap<K, V, RandomState> {
     ///
     /// The hash map will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the hash map will not allocate.
+    /// `capacity`. If `capacity` is zero, the hash map will not allocate.
     ///
     /// # Examples
     ///
@@ -287,7 +287,7 @@ impl<K, V, S> HashMap<K, V, S> {
     ///
     /// The hash map will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the hash map will not allocate.
+    /// `capacity`. If `capacity` is zero, the hash map will not allocate.
     ///
     /// Warning: `hasher` is normally randomly generated, and
     /// is designed to allow HashMaps to be resistant to attacks that
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index f86bcdb4796..21a73259f61 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -130,7 +130,7 @@ impl<T> HashSet<T, RandomState> {
     ///
     /// The hash set will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
+    /// `capacity`. If `capacity` is zero, the hash set will not allocate.
     ///
     /// # Examples
     ///
@@ -379,7 +379,7 @@ impl<T, S> HashSet<T, S> {
     ///
     /// The hash set will be able to hold at least `capacity` elements without
     /// reallocating. This method is allowed to allocate for more elements than
-    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
+    /// `capacity`. If `capacity` is zero, the hash set will not allocate.
     ///
     /// Warning: `hasher` is normally randomly generated, and
     /// is designed to allow `HashSet`s to be resistant to attacks that
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index dd967bca867..aee3949f7a0 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1064,7 +1064,7 @@ impl Step for Tidy {
         if builder.config.channel == "dev" || builder.config.channel == "nightly" {
             builder.info("fmt check");
             if builder.initial_rustfmt().is_none() {
-                let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap();
+                let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
                 eprintln!(
                     "\
 ERROR: no `rustfmt` binary found in {PATH}
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 945a7b7366f..73bc7195ac2 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -258,11 +258,11 @@ impl PathSet {
 
     // internal use only
     fn check(p: &TaskPath, needle: &Path, module: Kind) -> bool {
-        if let Some(p_kind) = &p.kind {
-            p.path.ends_with(needle) && *p_kind == module
-        } else {
-            p.path.ends_with(needle)
-        }
+        let check_path = || {
+            // This order is important for retro-compatibility, as `starts_with` was introduced later.
+            p.path.ends_with(needle) || p.path.starts_with(needle)
+        };
+        if let Some(p_kind) = &p.kind { check_path() && *p_kind == module } else { check_path() }
     }
 
     /// Return all `TaskPath`s in `Self` that contain any of the `needles`, removing the
@@ -1262,7 +1262,7 @@ impl<'a> Builder<'a> {
     pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path {
         match self.config.libdir_relative() {
             Some(relative_libdir) if compiler.stage >= 1 => relative_libdir,
-            _ if compiler.stage == 0 => &self.build.initial_libdir,
+            _ if compiler.stage == 0 => &self.build.initial_relative_libdir,
             _ => Path::new("lib"),
         }
     }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 9b2d49e7620..80667b2b2a6 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -379,6 +379,7 @@ pub struct Config {
     pub initial_cargo: PathBuf,
     pub initial_rustc: PathBuf,
     pub initial_cargo_clippy: Option<PathBuf>,
+    pub initial_sysroot: PathBuf,
 
     #[cfg(not(test))]
     initial_rustfmt: RefCell<RustfmtState>,
@@ -1563,8 +1564,6 @@ impl Config {
             );
         }
 
-        config.initial_cargo_clippy = cargo_clippy;
-
         config.initial_rustc = if let Some(rustc) = rustc {
             if !flags.skip_stage0_validation {
                 config.check_stage0_version(&rustc, "rustc");
@@ -1580,6 +1579,10 @@ impl Config {
                 .join(exe("rustc", config.build))
         };
 
+        config.initial_sysroot = config.initial_rustc.ancestors().nth(2).unwrap().into();
+
+        config.initial_cargo_clippy = cargo_clippy;
+
         config.initial_cargo = if let Some(cargo) = cargo {
             if !flags.skip_stage0_validation {
                 config.check_stage0_version(&cargo, "cargo");
@@ -1587,12 +1590,7 @@ impl Config {
             cargo
         } else {
             config.download_beta_toolchain();
-            config
-                .out
-                .join(config.build)
-                .join("stage0")
-                .join("bin")
-                .join(exe("cargo", config.build))
+            config.initial_sysroot.join("bin").join(exe("cargo", config.build))
         };
 
         // NOTE: it's important this comes *after* we set `initial_rustc` just above.
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index db1f5b08338..22a2b806603 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -427,9 +427,8 @@ impl Config {
         let version = &self.stage0_metadata.compiler.version;
         let host = self.build;
 
-        let bin_root = self.out.join(host).join("stage0");
-        let clippy_stamp = bin_root.join(".clippy-stamp");
-        let cargo_clippy = bin_root.join("bin").join(exe("cargo-clippy", host));
+        let clippy_stamp = self.initial_sysroot.join(".clippy-stamp");
+        let cargo_clippy = self.initial_sysroot.join("bin").join(exe("cargo-clippy", host));
         if cargo_clippy.exists() && !program_out_of_date(&clippy_stamp, date) {
             return cargo_clippy;
         }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index c384fd6bf43..0ecf61ffcd9 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -158,7 +158,7 @@ pub struct Build {
     initial_rustc: PathBuf,
     initial_cargo: PathBuf,
     initial_lld: PathBuf,
-    initial_libdir: PathBuf,
+    initial_relative_libdir: PathBuf,
     initial_sysroot: PathBuf,
 
     // Runtime state filled in later on
@@ -312,46 +312,19 @@ impl Build {
         let in_tree_llvm_info = config.in_tree_llvm_info.clone();
         let in_tree_gcc_info = config.in_tree_gcc_info.clone();
 
-        let initial_target_libdir_str = if config.dry_run() {
-            "/dummy/lib/path/to/lib/".to_string()
-        } else {
-            output(
-                Command::new(&config.initial_rustc)
-                    .arg("--target")
-                    .arg(config.build.rustc_target_arg())
-                    .arg("--print")
-                    .arg("target-libdir"),
-            )
-        };
+        let initial_target_libdir_str =
+            config.initial_sysroot.join("lib/rustlib").join(config.build).join("lib");
+
         let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap();
         let initial_lld = initial_target_dir.join("bin").join("rust-lld");
 
-        let initial_sysroot = if config.dry_run() {
-            "/dummy".to_string()
-        } else {
-            output(Command::new(&config.initial_rustc).arg("--print").arg("sysroot"))
-        }
-        .trim()
-        .to_string();
-
-        // FIXME(Zalathar): Determining this path occasionally fails locally for
-        // unknown reasons, so we print some extra context to help track down why.
-        let find_initial_libdir = || {
-            let initial_libdir =
-                initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?;
-            Some(initial_libdir.to_path_buf())
-        };
-        let Some(initial_libdir) = find_initial_libdir() else {
-            panic!(
-                "couldn't determine `initial_libdir`:
-- config.initial_rustc:      {rustc:?}
-- initial_target_libdir_str: {initial_target_libdir_str:?}
-- initial_target_dir:        {initial_target_dir:?}
-- initial_sysroot:           {initial_sysroot:?}
-",
-                rustc = config.initial_rustc,
-            );
-        };
+        let initial_relative_libdir = initial_target_dir
+            .ancestors()
+            .nth(2)
+            .unwrap()
+            .strip_prefix(&config.initial_sysroot)
+            .expect("Couldn’t determine initial relative libdir.")
+            .to_path_buf();
 
         let version = std::fs::read_to_string(src.join("src").join("version"))
             .expect("failed to read src/version");
@@ -380,11 +353,11 @@ impl Build {
         }
 
         let mut build = Build {
+            initial_lld,
+            initial_relative_libdir,
             initial_rustc: config.initial_rustc.clone(),
             initial_cargo: config.initial_cargo.clone(),
-            initial_lld,
-            initial_libdir,
-            initial_sysroot: initial_sysroot.into(),
+            initial_sysroot: config.initial_sysroot.clone(),
             local_rebuild: config.local_rebuild,
             fail_fast: config.cmd.fail_fast(),
             doc_tests: config.cmd.doc_tests(),
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 3fe567b1c39..185898c31b7 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
 use rustc_hir as hir;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::bug;
+use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::{self, Region, Ty};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{Symbol, kw};
@@ -182,7 +183,7 @@ fn clean_param_env<'tcx>(
                     .is_some_and(|pred| tcx.lang_items().sized_trait() == Some(pred.def_id()))
         })
         .map(|pred| {
-            tcx.fold_regions(pred, |r, _| match *r {
+            fold_regions(tcx, pred, |r, _| match *r {
                 // FIXME: Don't `unwrap_or`, I think we should panic if we encounter an infer var that
                 // we can't map to a concrete region. However, `AutoTraitFinder` *does* leak those kinds
                 // of `ReVar`s for some reason at the time of writing. See `rustdoc-ui/` tests.
diff --git a/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs
new file mode 100644
index 00000000000..d0ef91b22b2
--- /dev/null
+++ b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs
@@ -0,0 +1,13 @@
+// https://github.com/rust-lang/rust/issues/69232
+
+extern "C" {
+    fn foo(x: usize, ...);
+}
+
+fn test() -> u8 {
+    127
+}
+
+fn main() {
+    unsafe { foo(1, test) }; //~ ERROR can't pass a function item to a variadic function
+}
diff --git a/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr
new file mode 100644
index 00000000000..6aa1c8a1091
--- /dev/null
+++ b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr
@@ -0,0 +1,16 @@
+error[E0617]: can't pass a function item to a variadic function
+  --> $DIR/fn-item-diagnostic-issue-69232.rs:12:21
+   |
+LL |     unsafe { foo(1, test) };
+   |                     ^^^^
+   |
+   = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+   = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
+help: use a function pointer instead
+   |
+LL |     unsafe { foo(1, test as fn() -> u8) };
+   |                          +++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0617`.
diff --git a/tests/ui/c-variadic/issue-32201.rs b/tests/ui/c-variadic/issue-32201.rs
index f27bb1c2eb5..434711b7523 100644
--- a/tests/ui/c-variadic/issue-32201.rs
+++ b/tests/ui/c-variadic/issue-32201.rs
@@ -7,7 +7,8 @@ fn bar(_: *const u8) {}
 fn main() {
     unsafe {
         foo(0, bar);
-        //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
-        //~| HELP cast the value to `fn(*const u8)`
+        //~^ ERROR can't pass a function item to a variadic function
+        //~| HELP a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+        ////~| HELP use a function pointer instead
     }
 }
diff --git a/tests/ui/c-variadic/issue-32201.stderr b/tests/ui/c-variadic/issue-32201.stderr
index 352db9f62f6..1cd85d7f07a 100644
--- a/tests/ui/c-variadic/issue-32201.stderr
+++ b/tests/ui/c-variadic/issue-32201.stderr
@@ -1,8 +1,15 @@
-error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
+error[E0617]: can't pass a function item to a variadic function
   --> $DIR/issue-32201.rs:9:16
    |
 LL |         foo(0, bar);
-   |                ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
+   |                ^^^
+   |
+   = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+   = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
+help: use a function pointer instead
+   |
+LL |         foo(0, bar as fn(*const u8));
+   |                    ++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0617.rs b/tests/ui/error-codes/E0617.rs
index b71ba0ed88b..4a38174bc6f 100644
--- a/tests/ui/error-codes/E0617.rs
+++ b/tests/ui/error-codes/E0617.rs
@@ -20,7 +20,8 @@ fn main() {
         //~^ ERROR can't pass `u16` to variadic function
         //~| HELP cast the value to `c_uint`
         printf(::std::ptr::null(), printf);
-        //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function
-        //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)`
+        //~^ ERROR can't pass a function item to a variadic function
+        //~| HELP a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+        //~| HELP use a function pointer instead
     }
 }
diff --git a/tests/ui/error-codes/E0617.stderr b/tests/ui/error-codes/E0617.stderr
index ea91ad08292..7193463e028 100644
--- a/tests/ui/error-codes/E0617.stderr
+++ b/tests/ui/error-codes/E0617.stderr
@@ -28,16 +28,18 @@ error[E0617]: can't pass `u16` to variadic function
 LL |         printf(::std::ptr::null(), 0u16);
    |                                    ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint`
 
-error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function
+error[E0617]: can't pass a function item to a variadic function
   --> $DIR/E0617.rs:22:36
    |
 LL |         printf(::std::ptr::null(), printf);
    |                                    ^^^^^^
    |
-help: cast the value to `unsafe extern "C" fn(*const i8, ...)`
+   = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+   = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
+help: use a function pointer instead
    |
 LL |         printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...));
-   |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                                           +++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/generic-associated-types/parse/in-trait-impl.rs b/tests/ui/generic-associated-types/parse/in-trait-impl.rs
index 5ba42be3583..ef67fb18228 100644
--- a/tests/ui/generic-associated-types/parse/in-trait-impl.rs
+++ b/tests/ui/generic-associated-types/parse/in-trait-impl.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 
 impl<T> Baz for T where T: Foo {
     type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
diff --git a/tests/ui/generic-associated-types/parse/in-trait.rs b/tests/ui/generic-associated-types/parse/in-trait.rs
index 913eceec0da..2add908d727 100644
--- a/tests/ui/generic-associated-types/parse/in-trait.rs
+++ b/tests/ui/generic-associated-types/parse/in-trait.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 
 use std::ops::Deref;
 use std::fmt::Debug;
diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.rs b/tests/ui/impl-trait/impl-trait-plus-priority.rs
index 5441a015ac0..5575493a17d 100644
--- a/tests/ui/impl-trait/impl-trait-plus-priority.rs
+++ b/tests/ui/impl-trait/impl-trait-plus-priority.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 
 fn f() -> impl A + {} // OK
 fn f() -> impl A + B {} // OK
diff --git a/tests/ui/parser/assoc/assoc-oddities-1.rs b/tests/ui/parser/assoc/assoc-oddities-1.rs
index 246546ac034..c1b305a4eeb 100644
--- a/tests/ui/parser/assoc/assoc-oddities-1.rs
+++ b/tests/ui/parser/assoc/assoc-oddities-1.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 
 fn main() {
     // following lines below parse and must not fail
diff --git a/tests/ui/parser/assoc/assoc-oddities-2.rs b/tests/ui/parser/assoc/assoc-oddities-2.rs
index aee2af41d62..82cf7d79c0d 100644
--- a/tests/ui/parser/assoc/assoc-oddities-2.rs
+++ b/tests/ui/parser/assoc/assoc-oddities-2.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 
 fn main() {
     // see assoc-oddities-1 for explanation
diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs
index 7cee6def32f..ec0e83c314e 100644
--- a/tests/ui/parser/bounds-type.rs
+++ b/tests/ui/parser/bounds-type.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 //@ edition: 2021
 
 struct S<
diff --git a/tests/ui/parser/impl-qpath.rs b/tests/ui/parser/impl-qpath.rs
index d7c4989b6e4..fed026792c9 100644
--- a/tests/ui/parser/impl-qpath.rs
+++ b/tests/ui/parser/impl-qpath.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 
 impl <*const u8>::AssocTy {} // OK
 impl <Type as Trait>::AssocTy {} // OK
diff --git a/tests/ui/parser/issues/issue-17904.rs b/tests/ui/parser/issues/issue-17904.rs
index 6f77d4bb086..99a3b139898 100644
--- a/tests/ui/parser/issues/issue-17904.rs
+++ b/tests/ui/parser/issues/issue-17904.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Zparse-only
+//@ compile-flags: -Zparse-crate-root-only
 
 struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
 struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
diff --git a/tests/ui/traits/const-traits/syntax.rs b/tests/ui/traits/const-traits/syntax.rs
index 1064713ac59..cfac6e0a93e 100644
--- a/tests/ui/traits/const-traits/syntax.rs
+++ b/tests/ui/traits/const-traits/syntax.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 //@ check-pass
 
 #![feature(const_trait_bound_opt_out)]
diff --git a/tests/ui/traits/const-traits/tilde-const-syntax.rs b/tests/ui/traits/const-traits/tilde-const-syntax.rs
index d65ecae3d06..f9944c426cc 100644
--- a/tests/ui/traits/const-traits/tilde-const-syntax.rs
+++ b/tests/ui/traits/const-traits/tilde-const-syntax.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 //@ check-pass
 
 #![feature(const_trait_impl)]
diff --git a/tests/ui/traits/const-traits/tilde-twice.rs b/tests/ui/traits/const-traits/tilde-twice.rs
index c3f9f8e6764..d341513b8a8 100644
--- a/tests/ui/traits/const-traits/tilde-twice.rs
+++ b/tests/ui/traits/const-traits/tilde-twice.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Z parse-only
+//@ compile-flags: -Z parse-crate-root-only
 
 #![feature(const_trait_impl)]
 
diff --git a/tests/ui/traits/next-solver/dont-remap-tait-substs.rs b/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs
index 904bc179495..904bc179495 100644
--- a/tests/ui/traits/next-solver/dont-remap-tait-substs.rs
+++ b/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs
diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
index 158fefd1538..158fefd1538 100644
--- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
index 158fefd1538..158fefd1538 100644
--- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
index 10b746cc989..10b746cc989 100644
--- a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr
new file mode 100644
index 00000000000..9a28dc093c1
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr
@@ -0,0 +1,34 @@
+error: unconstrained opaque type
+  --> $DIR/no-define-in-wf-check.rs:19:18
+   |
+LL |     type Tait1 = impl Sized;
+   |                  ^^^^^^^^^^
+   |
+   = note: `Tait1` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/no-define-in-wf-check.rs:27:18
+   |
+LL |     type Tait1 = impl Sized;
+   |                  ^^^^^^^^^^
+   |
+   = note: `Tait1` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/no-define-in-wf-check.rs:36:18
+   |
+LL |     type Tait1 = impl Sized;
+   |                  ^^^^^^^^^^
+   |
+   = note: `Tait1` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/no-define-in-wf-check.rs:47:18
+   |
+LL |     type Tait1 = impl Sized;
+   |                  ^^^^^^^^^^
+   |
+   = note: `Tait1` must be used in combination with a concrete type within the same module
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
new file mode 100644
index 00000000000..dd6df097da1
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
@@ -0,0 +1,66 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+// Regression test for trait-system-refactor-initiative#106. We previously
+// tried to define other opaques while checking that opaques are well-formed.
+//
+// This resulted in undesirable ambiguity
+
+#![feature(type_alias_impl_trait)]
+
+mod ex0 {
+    fn foo() -> (impl Sized, impl Sized) {
+        ((), ())
+    }
+}
+mod ex1 {
+    type Tait1 = impl Sized;
+    //[current]~^ ERROR unconstrained opaque type
+    fn foo(x: Tait1) -> impl Sized {
+        let () = x;
+    }
+}
+
+mod ex2 {
+    type Tait1 = impl Sized;
+    //[current]~^ ERROR unconstrained opaque type
+    type Tait2 = impl Sized;
+    fn foo(x: Tait1) -> Tait2 {
+        let () = x;
+    }
+}
+
+mod ex3 {
+    type Tait1 = impl Sized;
+    //[current]~^ ERROR unconstrained opaque type
+    trait Something<T> {}
+    impl<T, U> Something<U> for T {}
+    type Tait2 = impl Something<Tait1>;
+    fn foo(x: Tait1) -> Tait2 {
+        let () = x;
+    }
+}
+
+mod ex4 {
+    type Tait1 = impl Sized;
+    //[current]~^ ERROR unconstrained opaque type
+    trait Trait<U> {
+        type Assoc;
+    }
+
+    impl<T, U> Trait<U> for T {
+        type Assoc = T;
+    }
+
+    // ambiguity when checking that `Tait2` is wf
+    //
+    // ambiguity proving `(): Trait<Tait1>`.
+    type Tait2 = impl Trait<(), Assoc = impl Trait<Tait1>>;
+    fn foo(x: Tait1) -> Tait2 {
+        let () = x;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/select-alias-bound-as-param.rs b/tests/ui/traits/next-solver/opaques/select-alias-bound-as-param.rs
index fd40ef1f872..fd40ef1f872 100644
--- a/tests/ui/traits/next-solver/select-alias-bound-as-param.rs
+++ b/tests/ui/traits/next-solver/opaques/select-alias-bound-as-param.rs