about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/util/parser.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher/tests.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs2
-rw-r--r--compiler/rustc_hir_analysis/locales/en-US.ftl8
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs62
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs2
-rw-r--r--compiler/rustc_incremental/src/assert_module_sources.rs2
-rw-r--r--compiler/rustc_index/src/bit_set.rs2
-rw-r--r--compiler/rustc_infer/locales/en-US.ftl8
-rw-r--r--compiler/rustc_infer/src/infer/at.rs28
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs20
-rw-r--r--compiler/rustc_infer/src/infer/canonical/substitute.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs2
-rw-r--r--compiler/rustc_interface/locales/en-US.ftl2
-rw-r--r--compiler/rustc_lexer/src/lib.rs12
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp36
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs62
-rw-r--r--compiler/rustc_middle/src/infer/mod.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs16
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs9
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs4
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs5
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs4
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs2
-rw-r--r--compiler/rustc_passes/src/liveness/rwu_table.rs2
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs2
-rw-r--r--compiler/rustc_resolve/src/ident.rs2
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs2
-rw-r--r--compiler/rustc_session/locales/en-US.ftl2
-rw-r--r--compiler/rustc_session/src/config.rs4
-rw-r--r--compiler/rustc_span/src/def_id.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs390
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonical/mod.rs240
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs97
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
73 files changed, 965 insertions, 201 deletions
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 81efdaa44b3..3a0af04f9eb 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -225,7 +225,7 @@ impl AssocOp {
             AssignOp(_) | // `{ 42 } +=`
             As | // `{ 42 } as usize`
             // Equal | // `{ 42 } == { 42 }`    Accepting these here would regress incorrect
-            // NotEqual | // `{ 42 } != { 42 }  struct literals parser recovery.
+            // NotEqual | // `{ 42 } != { 42 }` struct literals parser recovery.
             Colon, // `{ 42 }: usize`
         )
     }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 5352a56b165..b20157f2c7c 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1607,7 +1607,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
     }
 
-    /// Given a `parent_def_id`, a list of `lifetimes_in_bounds and a `remapping` hash to be
+    /// Given a `parent_def_id`, a list of `lifetimes_in_bounds` and a `remapping` hash to be
     /// filled, this function creates new definitions for `Param` and `Fresh` lifetimes, inserts the
     /// new definition, adds it to the remapping with the definition of the given lifetime and
     /// returns a list of lifetimes to be lowered afterwards.
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1c561375626..2cc009410f4 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -192,7 +192,7 @@ impl<'a> AstValidator<'a> {
                 // We allow these:
                 //  - `Option<impl Trait>`
                 //  - `option::Option<impl Trait>`
-                //  - `option::Option<T>::Foo<impl Trait>
+                //  - `option::Option<T>::Foo<impl Trait>`
                 //
                 // But not these:
                 //  - `<impl Trait>::Foo`
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 4baf1b6aa87..ffe82b46cfd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -415,7 +415,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
     /// ```
     ///
-    /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
+    /// Here we would be invoked with `fr = 'a` and `outlived_fr = 'b`.
     pub(crate) fn report_region_error(
         &mut self,
         fr: RegionVid,
@@ -949,7 +949,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     .push_span_label(*span, "this has an implicit `'static` lifetime requirement");
                 multi_span.push_span_label(
                     ident.span,
-                    "calling this method introduces the `impl`'s 'static` requirement",
+                    "calling this method introduces the `impl`'s `'static` requirement",
                 );
                 err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
                 err.span_suggestion_verbose(
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 941da2dd3b5..21b5bd7cb94 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -889,7 +889,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// from a universe it can't name; at present, the only way for
     /// this to be true is if `scc` outlives `'static`. This is
     /// actually stricter than necessary: ideally, we'd support bounds
-    /// like `for<'a: 'b`>` that might then allow us to approximate
+    /// like `for<'a: 'b>` that might then allow us to approximate
     /// `'a` with `'b` and not `'static`. But it will have to do for
     /// now.
     fn add_incompatible_universe(&mut self, scc: ConstraintSccIndex) {
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index c361357ca21..8132800f107 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -235,7 +235,7 @@ pub(crate) struct RegionValues<N: Idx> {
     free_regions: SparseBitMatrix<N, RegionVid>,
 
     /// Placeholders represent bound regions -- so something like `'a`
-    /// in for<'a> fn(&'a u32)`.
+    /// in `for<'a> fn(&'a u32)`.
     placeholders: SparseBitMatrix<N, PlaceholderIndex>,
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 1b3ce2e83a9..253c2ca7c76 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1814,8 +1814,6 @@ extern "C" {
     /// Creates a legacy pass manager -- only used for final codegen.
     pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;
 
-    pub fn LLVMInitializePasses();
-
     pub fn LLVMTimeTraceProfilerInitialize();
 
     pub fn LLVMTimeTraceProfilerFinishThread();
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 20b1dd94153..ba58a2e68e9 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -120,8 +120,6 @@ unsafe fn configure_llvm(sess: &Session) {
         llvm::LLVMTimeTraceProfilerInitialize();
     }
 
-    llvm::LLVMInitializePasses();
-
     rustc_llvm::initialize_available_targets();
 
     llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index c65d677e8ea..9ad945359b6 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -457,7 +457,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 assert_eq!(input_len, dest_len, "Return vector length must match input length");
                 assert!(
                     index < dest_len,
-                    "Index `{}` must be in bounds of vector with length {}`",
+                    "Index `{}` must be in bounds of vector with length {}",
                     index,
                     dest_len
                 );
@@ -477,7 +477,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let (input, input_len) = self.operand_to_simd(&args[0])?;
                 assert!(
                     index < input_len,
-                    "index `{}` must be in bounds of vector with length `{}`",
+                    "index `{}` must be in bounds of vector with length {}",
                     index,
                     input_len
                 );
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index e4366f655e4..aa24d9053b9 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -332,7 +332,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
 
     fn check_static(&mut self, def_id: DefId, span: Span) {
         if self.tcx.is_thread_local_static(def_id) {
-            self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef");
+            self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
         }
         self.check_op_spanned(ops::StaticAccess, span)
     }
diff --git a/compiler/rustc_data_structures/src/stable_hasher/tests.rs b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
index b0d66c32a07..724be5888dd 100644
--- a/compiler/rustc_data_structures/src/stable_hasher/tests.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
@@ -150,7 +150,7 @@ fn test_isize_compression() {
         let hash_b = hash(&(b as isize, a as isize));
         assert_ne!(
             hash_a, hash_b,
-            "The hash stayed the same when permuting values `{a}` and `{b}!",
+            "The hash stayed the same when permuting values `{a}` and `{b}`!",
         );
     }
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index b79835be73a..47a8b4bc488 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -282,7 +282,7 @@ pub(super) fn transcribe<'a>(
             }
 
             // There should be no meta-var declarations in the invocation of a macro.
-            mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"),
+            mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl`"),
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/locales/en-US.ftl b/compiler/rustc_hir_analysis/locales/en-US.ftl
index 40b5bc2a32e..1d313945b52 100644
--- a/compiler/rustc_hir_analysis/locales/en-US.ftl
+++ b/compiler/rustc_hir_analysis/locales/en-US.ftl
@@ -147,3 +147,11 @@ hir_analysis_main_function_generic_parameters = `main` function is not allowed t
 
 hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
     .label = C-variadic function must have a compatible calling convention
+
+hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
+    cannot capture late-bound type parameter in a constant
+    .label = parameter defined here
+
+hir_analysis_cannot_capture_late_bound_const_in_anon_const =
+    cannot capture late-bound const parameter in a constant
+    .label = parameter defined here
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index b0dc6b1dcac..691d3f8d942 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1873,7 +1873,7 @@ pub(super) fn check_type_bounds<'tcx>(
     //     type Bar<C> =...
     // }
     //
-    // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>
+    // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
     // - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
     // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
     //    the *trait* with the generic associated type parameters (as bound vars).
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 875c5f1fd00..ffb68abf978 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -437,7 +437,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
             }
 
             // Here we are considering a case of converting
-            // `S<P0...Pn>` to S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
+            // `S<P0...Pn>` to `S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
             // which acts like a pointer to `U`, but carries along some extra data of type `T`:
             //
             //     struct Foo<T, U> {
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index b14e65183aa..65a9052a60a 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -24,6 +24,8 @@ use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use std::fmt;
 
+use crate::errors;
+
 trait RegionExt {
     fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
 
@@ -161,6 +163,15 @@ enum Scope<'a> {
         s: ScopeRef<'a>,
     },
 
+    /// Disallows capturing non-lifetime binders from parent scopes.
+    ///
+    /// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
+    /// since we don't do something more correct like replacing any captured
+    /// late-bound vars with early-bound params in the const's own generics.
+    AnonConstBoundary {
+        s: ScopeRef<'a>,
+    },
+
     Root {
         opt_parent_item: Option<LocalDefId>,
     },
@@ -211,6 +222,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("s", &"..")
                 .finish(),
             Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
+            Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(),
             Scope::Root { opt_parent_item } => {
                 f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
             }
@@ -312,7 +324,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     break (vec![], BinderScopeType::Normal);
                 }
 
-                Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
+                Scope::Elision { s, .. }
+                | Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::AnonConstBoundary { s } => {
                     scope = s;
                 }
 
@@ -1029,6 +1043,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
         self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
     }
+
+    fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+        self.with(Scope::AnonConstBoundary { s: self.scope }, |this| {
+            intravisit::walk_anon_const(this, c);
+        });
+    }
 }
 
 fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
@@ -1275,7 +1295,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Elision { s, .. }
                 | Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
-                | Scope::TraitRefBoundary { s, .. } => {
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
                     scope = s;
                 }
             }
@@ -1340,7 +1361,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 | Scope::Elision { s, .. }
                 | Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
-                | Scope::TraitRefBoundary { s, .. } => {
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
                     scope = s;
                 }
             }
@@ -1359,6 +1381,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         // search.
         let mut late_depth = 0;
         let mut scope = self.scope;
+        let mut crossed_anon_const = false;
         let result = loop {
             match *scope {
                 Scope::Body { s, .. } => {
@@ -1392,10 +1415,36 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 | Scope::TraitRefBoundary { s, .. } => {
                     scope = s;
                 }
+
+                Scope::AnonConstBoundary { s } => {
+                    crossed_anon_const = true;
+                    scope = s;
+                }
             }
         };
 
         if let Some(def) = result {
+            if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
+                let use_span = self.tcx.hir().span(hir_id);
+                let def_span = self.tcx.def_span(param_def_id);
+                match self.tcx.def_kind(param_def_id) {
+                    DefKind::ConstParam => {
+                        self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
+                            use_span,
+                            def_span,
+                        });
+                    }
+                    DefKind::TyParam => {
+                        self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
+                            use_span,
+                            def_span,
+                        });
+                    }
+                    _ => unreachable!(),
+                }
+                return;
+            }
+
             self.map.defs.insert(hir_id, def);
             return;
         }
@@ -1474,7 +1523,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         | Scope::Elision { s, .. }
                         | Scope::ObjectLifetimeDefault { s, .. }
                         | Scope::Supertrait { s, .. }
-                        | Scope::TraitRefBoundary { s, .. } => {
+                        | Scope::TraitRefBoundary { s, .. }
+                        | Scope::AnonConstBoundary { s } => {
                             scope = s;
                         }
                     }
@@ -1710,7 +1760,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
                 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
 
-                Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
+                Scope::Supertrait { s, .. }
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
                     scope = s;
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 203e0f85cad..3e069275775 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -381,3 +381,21 @@ pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
     pub span: Span,
     pub conventions: &'a str,
 }
+
+#[derive(Diagnostic)]
+pub(crate) enum CannotCaptureLateBoundInAnonConst {
+    #[diag(hir_analysis_cannot_capture_late_bound_ty_in_anon_const)]
+    Type {
+        #[primary_span]
+        use_span: Span,
+        #[label]
+        def_span: Span,
+    },
+    #[diag(hir_analysis_cannot_capture_late_bound_const_in_anon_const)]
+    Const {
+        #[primary_span]
+        use_span: Span,
+        #[label]
+        def_span: Span,
+    },
+}
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 34d62987c3b..7ba57b3b7a2 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -315,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     probe::ProbeScope::TraitsInScope,
                     None,
                 ) {
-                    Ok(pick) => pick.self_ty,
+                    Ok(pick) => eraser.fold_ty(pick.self_ty),
                     Err(_) => rcvr_ty,
                 };
                 // Remove one layer of references to account for `&mut self` and
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index bcfc61bffb2..4d3969d28aa 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -636,7 +636,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         // `&&Some(x,)` `place_foo`
         //  `&Some(x,)` `deref { place_foo}`
         //   `Some(x,)` `deref { deref { place_foo }}`
-        //        (x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
+        //       `(x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
         //
         // The above example has no adjustments. If the code were instead the (after adjustments,
         // equivalent) version
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index e8bc50440e2..4a432328c4d 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -2223,7 +2223,7 @@ fn determine_place_ancestry_relation<'tcx>(
 ///     || drop(&*m.a.field_of_a)
 ///     // Here we really do want to capture `*m.a` because that outlives `'static`
 ///
-///     // If we capture `m`, then the closure no longer outlives `'static'
+///     // If we capture `m`, then the closure no longer outlives `'static`
 ///     // it is constrained to `'a`
 /// }
 /// ```
diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs
index b4b0ea00c50..c550e553bb0 100644
--- a/compiler/rustc_incremental/src/assert_module_sources.rs
+++ b/compiler/rustc_incremental/src/assert_module_sources.rs
@@ -18,7 +18,7 @@
 //! the HIR doesn't change as a result of the annotations, which might
 //! perturb the reuse results.
 //!
-//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
+//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]`
 //! allows for doing a more fine-grained check to see if pre- or post-lto data
 //! was re-used.
 
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 15179392c88..cbf169afb18 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1870,7 +1870,7 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
         }
     }
 
-    /// Subtracts `set from `row`. `set` can be either `BitSet` or
+    /// Subtracts `set` from `row`. `set` can be either `BitSet` or
     /// `HybridBitSet`. Has no effect if `row` does not exist.
     ///
     /// Returns true if the row was changed.
diff --git a/compiler/rustc_infer/locales/en-US.ftl b/compiler/rustc_infer/locales/en-US.ftl
index c5b2b6c2d73..e3db44477de 100644
--- a/compiler/rustc_infer/locales/en-US.ftl
+++ b/compiler/rustc_infer/locales/en-US.ftl
@@ -79,7 +79,7 @@ infer_subtype = ...so that the {$requirement ->
     [if_else_different] `if` and `else` have incompatible types
     [no_else] `if` missing an `else` returns `()`
     [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] #[start]` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
     [intristic_correct_type] intrinsic has the correct type
     [method_correct_type] method receiver has the correct type
     *[other] types are compatible
@@ -92,7 +92,7 @@ infer_subtype_2 = ...so that {$requirement ->
     [if_else_different] `if` and `else` have incompatible types
     [no_else] `if` missing an `else` returns `()`
     [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] #[start]` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
     [intristic_correct_type] intrinsic has the correct type
     [method_correct_type] method receiver has the correct type
     *[other] types are compatible
@@ -277,7 +277,7 @@ infer_tid_consider_borrowing = consider borrowing this type parameter in the tra
 infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
 
 infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
-infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement
+infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
 infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
 infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
 
@@ -313,7 +313,7 @@ infer_but_needs_to_satisfy = {$has_param_name ->
         [false] ...and is required to live as long as `'static` here
     }
     .used_here = ...is used here...
-    .introduced_by_bound = 'static` lifetime requirement introduced by this bound
+    .introduced_by_bound = `'static` lifetime requirement introduced by this bound
 
 infer_more_targeted = {$has_param_name ->
     [true] `{$param_name}`
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index c952ddc827a..7d9bae735e5 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -369,6 +369,34 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
     }
 }
 
+impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
+    fn to_trace(
+        _: TyCtxt<'tcx>,
+        cause: &ObligationCause<'tcx>,
+        a_is_expected: bool,
+        a: Self,
+        b: Self,
+    ) -> TypeTrace<'tcx> {
+        use GenericArgKind::*;
+        TypeTrace {
+            cause: cause.clone(),
+            values: match (a.unpack(), b.unpack()) {
+                (Lifetime(a), Lifetime(b)) => Regions(ExpectedFound::new(a_is_expected, a, b)),
+                (Type(a), Type(b)) => Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+                (Const(a), Const(b)) => {
+                    Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
+                }
+
+                (Lifetime(_), Type(_) | Const(_))
+                | (Type(_), Lifetime(_) | Const(_))
+                | (Const(_), Lifetime(_) | Type(_)) => {
+                    bug!("relating different kinds: {a:?} {b:?}")
+                }
+            },
+        }
+    }
+}
+
 impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
     fn to_trace(
         _: TyCtxt<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 7ffd39de781..678c4a0beb6 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -50,7 +50,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
     /// Like [Self::canonicalize_query], but preserves distinct universes. For
     /// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and
-    /// `'?1` is in `U3` would be canonicalized to have ?0` in `U1` and `'?1`
+    /// `'?1` is in `U3` would be canonicalized to have `?0` in `U1` and `'?1`
     /// in `U2`.
     ///
     /// This is used for Chalk integration.
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 8c782a933a5..ce230afdab3 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -30,7 +30,7 @@ use rustc_middle::ty::{self, List, TyCtxt};
 use rustc_span::source_map::Span;
 
 pub use rustc_middle::infer::canonical::*;
-use substitute::CanonicalExt;
+pub use substitute::CanonicalExt;
 
 mod canonicalizer;
 pub mod query_response;
@@ -100,7 +100,11 @@ impl<'tcx> InferCtxt<'tcx> {
     /// variable for it. If this is an existentially quantified
     /// variable, then you'll get a new inference variable; if it is a
     /// universally quantified variable, you get a placeholder.
-    fn instantiate_canonical_var(
+    ///
+    /// FIXME(-Ztrait-solver=next): This is public because it's used by the
+    /// new trait solver which has a different canonicalization routine.
+    /// We should somehow deduplicate all of this.
+    pub fn instantiate_canonical_var(
         &self,
         span: Span,
         cv_info: CanonicalVarInfo<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 832af91a431..436d29c2449 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -151,11 +151,21 @@ impl<'tcx> InferCtxt<'tcx> {
         })
     }
 
-    /// FIXME: This method should only be used for canonical queries and therefore be private.
-    ///
-    /// As the new solver does canonicalization slightly differently, this is also used there
-    /// for now. This should hopefully change fairly soon.
-    pub fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    /// Used by the new solver as that one takes the opaque types at the end of a probe
+    /// to deal with multiple candidates without having to recompute them.
+    pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+        self.inner
+            .borrow()
+            .opaque_type_storage
+            .opaque_types
+            .iter()
+            .map(|&(k, ref v)| {
+                (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty)
+            })
+            .collect()
+    }
+
+    fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
         std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
             .into_iter()
             .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs
index c5c6fc41b9e..cac3b407251 100644
--- a/compiler/rustc_infer/src/infer/canonical/substitute.rs
+++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs
@@ -11,7 +11,9 @@ use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, TyCtxt};
 
-pub(super) trait CanonicalExt<'tcx, V> {
+/// FIXME(-Ztrait-solver=next): This or public because it is shared with the
+/// new trait solver implementation. We should deduplicate canonicalization.
+pub trait CanonicalExt<'tcx, V> {
     /// Instantiate the wrapped value, replacing each canonical value
     /// with the value given in `var_values`.
     fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 79efc1ce7bf..bf6af57c66a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1690,7 +1690,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 format!("{name} is defined in the current crate")
                             } else {
                                 let crate_name = self.tcx.crate_name(defid.krate);
-                                format!("{name} is defined in crate `{crate_name}")
+                                format!("{name} is defined in crate `{crate_name}`")
                             };
                             diagnostic.span_note(def_span, msg);
                         };
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 a499018d3a2..2c480355085 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -70,7 +70,7 @@ pub enum RegionResolutionError<'tcx> {
     /// `o` requires that `a <= b`, but this does not hold
     ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
 
-    /// `GenericBoundFailure(p, s, a)
+    /// `GenericBoundFailure(p, s, a)`:
     ///
     /// The parameter/associated-type `p` must be known to outlive the lifetime
     /// `a` (but none of the known bounds are sufficient).
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 6e413a7f412..573cd91a2a2 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -50,7 +50,7 @@ where
     ///
     /// - Covariant means `a <: b`.
     /// - Contravariant means `b <: a`.
-    /// - Invariant means `a == b.
+    /// - Invariant means `a == b`.
     /// - Bivariant means that it doesn't matter.
     ambient_variance: ty::Variance,
 
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 33514eedfc3..872f617474c 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -249,7 +249,7 @@ pub enum VerifyBound<'tcx> {
 /// in that case we can show `'b: 'c`. But if `'?x` winds up being something
 /// else, the bound isn't relevant.
 ///
-/// In the [`VerifyBound`], this struct is enclosed in `Binder to account
+/// In the [`VerifyBound`], this struct is enclosed in `Binder` to account
 /// for cases like
 ///
 /// ```rust
diff --git a/compiler/rustc_interface/locales/en-US.ftl b/compiler/rustc_interface/locales/en-US.ftl
index da58492ccf2..37994899a20 100644
--- a/compiler/rustc_interface/locales/en-US.ftl
+++ b/compiler/rustc_interface/locales/en-US.ftl
@@ -33,7 +33,7 @@ interface_rustc_error_fatal =
     fatal error triggered by #[rustc_error]
 
 interface_rustc_error_unexpected_annotation =
-    unexpected annotation used with `#[rustc_error(...)]!
+    unexpected annotation used with `#[rustc_error(...)]`!
 
 interface_failed_writing_file =
     failed to write file {$path}: {$error}"
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index e6f04fe0aaa..322ec31fb2c 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -166,15 +166,17 @@ pub enum DocStyle {
     Inner,
 }
 
-// Note that the suffix is *not* considered when deciding the `LiteralKind` in
-// this type. This means that float literals like `1f32` are classified by this
-// type as `Int`. (Compare against `rustc_ast::token::LitKind` and
-// `rustc_ast::ast::LitKind.)
+/// Enum representing the literal types supported by the lexer.
+///
+/// Note that the suffix is *not* considered when deciding the `LiteralKind` in
+/// this type. This means that float literals like `1f32` are classified by this
+/// type as `Int`. (Compare against `rustc_ast::token::LitKind` and
+/// `rustc_ast::ast::LitKind`).
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum LiteralKind {
     /// "12_u8", "0o100", "0b120i99", "1f32".
     Int { base: Base, empty_int: bool },
-    /// "12.34f32", "1e3", but not "1f32`.
+    /// "12.34f32", "1e3", but not "1f32".
     Float { base: Base, empty_exponent: bool },
     /// "'a'", "'\\'", "'''", "';"
     Char { terminated: bool },
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 59540aaf18f..5b2100b5da9 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1288,7 +1288,7 @@ declare_lint! {
 }
 
 declare_lint_pass!(
-    /// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
+    /// Explains corresponding feature flag must be enabled for the `#[track_caller]` attribute to
     /// do anything
     UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
 );
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 0a42265a6ba..4761ce83fab 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -9,7 +9,6 @@
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
-#include "llvm/InitializePasses.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -58,22 +57,6 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
 
-extern "C" void LLVMInitializePasses() {
-  PassRegistry &Registry = *PassRegistry::getPassRegistry();
-  initializeCore(Registry);
-  initializeCodeGen(Registry);
-  initializeScalarOpts(Registry);
-  initializeVectorization(Registry);
-  initializeIPO(Registry);
-  initializeAnalysis(Registry);
-  initializeTransformUtils(Registry);
-  initializeInstCombine(Registry);
-#if LLVM_VERSION_LT(16, 0)
-  initializeInstrumentation(Registry);
-#endif
-  initializeTarget(Registry);
-}
-
 extern "C" void LLVMTimeTraceProfilerInitialize() {
   timeTraceProfilerInitialize(
       /* TimeTraceGranularity */ 0,
@@ -1004,23 +987,8 @@ LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
 }
 
 extern "C" void LLVMRustPrintPasses() {
-  LLVMInitializePasses();
-  struct MyListener : PassRegistrationListener {
-    void passEnumerate(const PassInfo *Info) {
-      StringRef PassArg = Info->getPassArgument();
-      StringRef PassName = Info->getPassName();
-      if (!PassArg.empty()) {
-        // These unsigned->signed casts could theoretically overflow, but
-        // realistically never will (and even if, the result is implementation
-        // defined rather plain UB).
-        printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
-               (int)PassName.size(), PassName.data());
-      }
-    }
-  } Listener;
-
-  PassRegistry *PR = PassRegistry::getPassRegistry();
-  PR->enumerateWith(&Listener);
+  PassBuilder PB;
+  PB.printPassNames(outs());
 }
 
 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index ccb07804b96..3ab01f7809b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1621,7 +1621,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn encode_info_for_closure(&mut self, def_id: LocalDefId) {
         // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
-        // including on the signature, which is inferred in `typeck.
+        // including on the signature, which is inferred in `typeck`.
         let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id);
         let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
         let ty = typeck_result.node_type(hir_id);
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 8712514a384..7f8fc17744d 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -123,6 +123,11 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
         self.kind.universe()
     }
 
+    #[must_use]
+    pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
+        CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
+    }
+
     pub fn is_existential(&self) -> bool {
         match self.kind {
             CanonicalVarKind::Ty(_) => true,
@@ -133,6 +138,28 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
             CanonicalVarKind::PlaceholderConst(_, _) => false,
         }
     }
+
+    pub fn is_region(&self) -> bool {
+        match self.kind {
+            CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
+            CanonicalVarKind::Ty(_)
+            | CanonicalVarKind::PlaceholderTy(_)
+            | CanonicalVarKind::Const(_, _)
+            | CanonicalVarKind::PlaceholderConst(_, _) => false,
+        }
+    }
+
+    pub fn expect_anon_placeholder(self) -> u32 {
+        match self.kind {
+            CanonicalVarKind::Ty(_)
+            | CanonicalVarKind::Region(_)
+            | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
+
+            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
+            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
+        }
+    }
 }
 
 /// Describes the "kind" of the canonical variable. This is a "kind"
@@ -177,6 +204,38 @@ impl<'tcx> CanonicalVarKind<'tcx> {
             CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
         }
     }
+
+    /// Replaces the universe of this canonical variable with `ui`.
+    ///
+    /// In case this is a float or int variable, this causes an ICE if
+    /// the updated universe is not the root.
+    pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
+        match self {
+            CanonicalVarKind::Ty(kind) => match kind {
+                CanonicalTyVarKind::General(_) => {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
+                }
+                CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => {
+                    assert_eq!(ui, ty::UniverseIndex::ROOT);
+                    CanonicalVarKind::Ty(kind)
+                }
+            },
+            CanonicalVarKind::PlaceholderTy(placeholder) => {
+                CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
+            }
+            CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
+            CanonicalVarKind::PlaceholderRegion(placeholder) => {
+                CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
+            }
+            CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
+            CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
+                CanonicalVarKind::PlaceholderConst(
+                    ty::Placeholder { universe: ui, ..placeholder },
+                    ty,
+                )
+            }
+        }
+    }
 }
 
 /// Rust actually has more than one category of type variables;
@@ -213,7 +272,8 @@ pub struct QueryResponse<'tcx, R> {
     pub value: R,
 }
 
-#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct QueryRegionConstraints<'tcx> {
     pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
     pub member_constraints: Vec<MemberConstraint<'tcx>>,
diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs
index 38868c21049..2db59f37f40 100644
--- a/compiler/rustc_middle/src/infer/mod.rs
+++ b/compiler/rustc_middle/src/infer/mod.rs
@@ -12,7 +12,8 @@ use rustc_span::Span;
 /// ```text
 /// R0 member of [O1..On]
 /// ```
-#[derive(Debug, Clone, HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct MemberConstraint<'tcx> {
     /// The `DefId` and substs of the opaque type causing this constraint.
     /// Used for error reporting.
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 0d78c6135b3..99cdb769da1 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2908,7 +2908,7 @@ fn pretty_print_const_value<'tcx>(
             // the `destructure_const` query with an empty `ty::ParamEnv` without
             // introducing ICEs (e.g. via `layout_of`) from missing bounds.
             // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
-            // to be able to destructure the tuple into `(0u8, *mut T)
+            // to be able to destructure the tuple into `(0u8, *mut T)`
             //
             // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
             // correct `ty::ParamEnv` to allow printing *all* constant values.
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 1610ae1ce14..28a3b51b7fc 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -11,7 +11,7 @@ use std::io::{self, Write};
 pub const TOOLTIP_INDENT: &str = "    ";
 
 const CARET: char = '\u{2038}'; // Unicode `CARET`
-const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET
+const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET`
 const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET`
 const NEW_LINE_SPAN: &str = "</span>\n<span class=\"line\">";
 const HEADER: &str = r#"<!DOCTYPE html>
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 51feae3cf8a..5133da3429a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1672,7 +1672,7 @@ rustc_queries! {
 
     /// Does lifetime resolution on items. Importantly, we can't resolve
     /// lifetimes directly on things like trait methods, because of trait params.
-    /// See `rustc_resolve::late::lifetimes for details.
+    /// See `rustc_resolve::late::lifetimes` for details.
     query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars {
         arena_cache
         desc { "resolving lifetimes" }
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index c5bf9717f03..bd43867a3da 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -2,6 +2,7 @@ use std::ops::ControlFlow;
 
 use rustc_data_structures::intern::Interned;
 
+use crate::infer::canonical::QueryRegionConstraints;
 use crate::ty::{
     FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
 };
@@ -18,20 +19,25 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
 }
 
 /// Additional constraints returned on success.
-#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
+#[derive(Debug, PartialEq, Eq, Clone, Hash, Default, TypeFoldable, TypeVisitable)]
 pub struct ExternalConstraintsData<'tcx> {
     // FIXME: implement this.
-    pub regions: (),
+    pub region_constraints: QueryRegionConstraints<'tcx>,
     pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
 }
 
+// FIXME: Having to clone `region_constraints` for folding feels bad and
+// probably isn't great wrt performance.
+//
+// Not sure how to fix this, maybe we should also intern `opaque_types` and
+// `region_constraints` here or something.
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
     fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
         Ok(FallibleTypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
-            regions: (),
+            region_constraints: self.region_constraints.clone().try_fold_with(folder)?,
             opaque_types: self
                 .opaque_types
                 .iter()
@@ -42,7 +48,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
 
     fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
         TypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
-            regions: (),
+            region_constraints: self.region_constraints.clone().fold_with(folder),
             opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
         })
     }
@@ -53,7 +59,7 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
         &self,
         visitor: &mut V,
     ) -> std::ops::ControlFlow<V::BreakTy> {
-        self.regions.visit_with(visitor)?;
+        self.region_constraints.visit_with(visitor)?;
         self.opaque_types.visit_with(visitor)?;
         ControlFlow::Continue(())
     }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 884ae7f5da2..527ec9f6e1c 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -16,7 +16,7 @@ pub use int::*;
 pub use kind::*;
 pub use valtree::*;
 
-/// Use this rather than `ConstData, whenever possible.
+/// Use this rather than `ConstData`, whenever possible.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 0333198c203..e9e121f9c9b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -310,7 +310,7 @@ pub struct CommonLifetimes<'tcx> {
     pub re_vars: Vec<Region<'tcx>>,
 
     /// Pre-interned values of the form:
-    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })
+    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })`
     /// for small values of `i` and `v`.
     pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
 }
@@ -2187,7 +2187,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // Actually intern type lists as lists of `GenericArg`s.
         //
         // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
-        // as explained in ty_slice_as_generic_arg`. With this,
+        // as explained in `ty_slice_as_generic_arg`. With this,
         // we guarantee that even when transmuting between `List<Ty<'tcx>>`
         // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
         // lists is upheld.
@@ -2450,7 +2450,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
         self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
     }
 
-    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
+    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
     /// ensure it gets used.
     #[track_caller]
     pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 355b8d8b431..92a040068dd 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -105,7 +105,7 @@ impl<'tcx> VariantDef {
 impl<'tcx> Ty<'tcx> {
     pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> {
         match self.kind() {
-            // For now, union`s are always considered inhabited
+            // For now, unions are always considered inhabited
             Adt(adt, _) if adt.is_union() => InhabitedPredicate::True,
             // Non-exhaustive ADTs from other crates are always considered inhabited
             Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 090272a6fa6..9a517d2d2b4 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -93,7 +93,7 @@ impl IntegerExt for Integer {
             if discr < fit {
                 bug!(
                     "Integer::repr_discr: `#[repr]` hint too small for \
-                      discriminant range of enum `{}",
+                      discriminant range of enum `{}`",
                     ty
                 )
             }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 5df01b8abc3..dce18a5850f 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -710,7 +710,7 @@ impl<'tcx> Predicate<'tcx> {
         //   The substitution from the input trait-ref is therefore going to be
         //   `'a => 'x` (where `'x` has a DB index of 1).
         // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
-        //   early-bound parameter and `'b' is a late-bound parameter with a
+        //   early-bound parameter and `'b` is a late-bound parameter with a
         //   DB index of 1.
         // - If we replace `'a` with `'x` from the input, it too will have
         //   a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
@@ -2444,7 +2444,7 @@ impl<'tcx> TyCtxt<'tcx> {
         None
     }
 
-    /// Check if the given `DefId` is `#\[automatically_derived\], *and*
+    /// Check if the given `DefId` is `#\[automatically_derived\]`, *and*
     /// whether it was produced by expanding a builtin derive macro.
     pub fn is_builtin_derived(self, def_id: DefId) -> bool {
         if self.is_automatically_derived(def_id)
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index ba714541c9e..e6a73e8bb1c 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -107,6 +107,15 @@ impl BoundRegionKind {
             _ => None,
         }
     }
+
+    pub fn expect_anon(&self) -> u32 {
+        match *self {
+            BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => {
+                bug!("expected anon region: {self:?}")
+            }
+            BoundRegionKind::BrAnon(idx, _) => idx,
+        }
+    }
 }
 
 pub trait Article {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 2f63333d46b..cfacb5ea327 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -55,7 +55,7 @@ pub fn as_constant_inner<'tcx>(
                         ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
                     }
                     Err(LitToConstError::TypeError) => {
-                        bug!("encountered type error in `lit_to_mir_constant")
+                        bug!("encountered type error in `lit_to_mir_constant`")
                     }
                 };
 
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index fa5f392fa74..536745d2cfe 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -74,7 +74,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
         //
         // `unsafe { *FOO = 0; *BAR.field = 1; }`
         // `unsafe { &mut *FOO }`
-        // `unsafe { (*ARRAY)[0] = val; }
+        // `unsafe { (*ARRAY)[0] = val; }`
         if !place.projection.iter().any(|p| matches!(p, PlaceElem::Deref)) {
             let source_info = self.body.source_info(location);
             let lint_root = self.body.source_scopes[source_info.scope]
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index f973c1ed28f..8ee316773ae 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -407,7 +407,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
                 if self.prev().is_macro_expansion() && self.curr().is_macro_expansion() {
                     // Macros that expand to include branching (such as
                     // `assert_eq!()`, `assert_ne!()`, `info!()`, `debug!()`, or
-                    // `trace!()) typically generate callee spans with identical
+                    // `trace!()`) typically generate callee spans with identical
                     // ranges (typically the full span of the macro) for all
                     // `BasicBlocks`. This makes it impossible to distinguish
                     // the condition (`if val1 != val2`) from the optional
@@ -694,7 +694,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
     /// `prev.span.hi()` will be greater than (further right of) `prev_original_span.hi()`.
     /// If prev.span() was split off to the right of a closure, prev.span().lo() will be
     /// greater than prev_original_span.lo(). The actual span of `prev_original_span` is
-    /// not as important as knowing that `prev()` **used to have the same span** as `curr(),
+    /// not as important as knowing that `prev()` **used to have the same span** as `curr()`,
     /// which means their sort order is still meaningful for determining the dominator
     /// relationship.
     ///
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 4193eb7d6e8..cdd28ae0c01 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -248,7 +248,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
 
     // N.B., this `borrow()` is guaranteed to be valid (i.e., the value
     // cannot yet be stolen), because `mir_promoted()`, which steals
-    // from `mir_const(), forces this query to execute before
+    // from `mir_const()`, forces this query to execute before
     // performing the steal.
     let body = &tcx.mir_const(def).borrow();
 
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 2f02d00ec9f..c6e7468aab4 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -68,8 +68,11 @@ fn lower_slice_len_call<'tcx>(
                 ty::FnDef(fn_def_id, _) if fn_def_id == &slice_len_fn_item_def_id => {
                     // perform modifications
                     // from something like `_5 = core::slice::<impl [u8]>::len(move _6) -> bb1`
-                    // into `_5 = Len(*_6)
+                    // into:
+                    // ```
+                    // _5 = Len(*_6)
                     // goto bb1
+                    // ```
 
                     // make new RValue for Len
                     let deref_arg = tcx.mk_place_deref(arg);
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index dbd3b76786f..b0ab0f10624 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -134,11 +134,11 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
             // Process the replace ranges, starting from the highest start
             // position and working our way back. If have tokens like:
             //
-            // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }`
+            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
             //
             // Then we will generate replace ranges for both
             // the `#[cfg(FALSE)] field: bool` and the entire
-            // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }`
+            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
             //
             // By starting processing from the replace range with the greatest
             // start position, we ensure that any replace range which encloses
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index b1b79fe4e05..da82e4724d1 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -335,7 +335,7 @@ impl TokenCursor {
             num_of_hashes = cmp::max(num_of_hashes, count);
         }
 
-        // `/// foo` becomes `doc = r"foo".
+        // `/// foo` becomes `doc = r"foo"`.
         let delim_span = DelimSpan::from_single(span);
         let body = TokenTree::Delimited(
             delim_span,
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 51a19c8e3c0..5e2d2d3e5a7 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -646,7 +646,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     // `UseTree` has one inline use (in `ast::ItemKind::Use`) and one
-    // non-inline use (in `ast::UseTreeKind::Nested). The former case is more
+    // non-inline use (in `ast::UseTreeKind::Nested`). The former case is more
     // common, so we don't implement `visit_use_tree` and tolerate the missed
     // coverage in the latter case.
 
diff --git a/compiler/rustc_passes/src/liveness/rwu_table.rs b/compiler/rustc_passes/src/liveness/rwu_table.rs
index 6d5983f53dc..053bf5c234a 100644
--- a/compiler/rustc_passes/src/liveness/rwu_table.rs
+++ b/compiler/rustc_passes/src/liveness/rwu_table.rs
@@ -9,7 +9,7 @@ pub(super) struct RWU {
 }
 
 /// Conceptually, this is like a `Vec<Vec<RWU>>`. But the number of
-/// RWU`s can get very large, so it uses a more compact representation.
+/// RWU's can get very large, so it uses a more compact representation.
 pub(super) struct RWUTable {
     /// Total number of live nodes.
     live_nodes: usize,
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 70c481fb0ee..46e34462cf2 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -333,7 +333,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
                 },
             );
 
-            // `Encode the file footer.
+            // Encode the file footer.
             let footer_pos = encoder.position() as u64;
             encoder.encode_tagged(
                 TAG_FILE_FOOTER,
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index ba7f04239c3..52f0b65fad6 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -368,7 +368,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     /// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
     /// expansion and import resolution (perhaps they can be merged in the future).
     /// The function is used for resolving initial segments of macro paths (e.g., `foo` in
-    /// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
+    /// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
     #[instrument(level = "debug", skip(self, scope_set))]
     pub(crate) fn early_resolve_ident_in_lexical_scope(
         &mut self,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 36415936bdc..b8ddc455257 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -878,7 +878,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         );
         let is_assoc_fn = self.self_type_is_available();
         if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
-            // The current function has a `self' parameter, but we were unable to resolve
+            // The current function has a `self` parameter, but we were unable to resolve
             // a reference to `self`. This can only happen if the `self` identifier we
             // are resolving came from a different hygiene context.
             if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) {
diff --git a/compiler/rustc_session/locales/en-US.ftl b/compiler/rustc_session/locales/en-US.ftl
index fe553edab42..ff53f22d43f 100644
--- a/compiler/rustc_session/locales/en-US.ftl
+++ b/compiler/rustc_session/locales/en-US.ftl
@@ -5,7 +5,7 @@ session_incorrect_cgu_reuse_type =
     }`{$expected_reuse}`
 
 session_cgu_not_recorded =
-    CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded`
+    CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
 
 session_feature_gate_error = {$explain}
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 295e93f6103..d4e4ace889b 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2245,7 +2245,7 @@ pub fn parse_externs(
                 early_error(
                     error_format,
                     "the `-Z unstable-options` flag must also be passed to \
-                     enable `--extern options",
+                     enable `--extern` options",
                 );
             }
             for opt in opts.split(',') {
@@ -2792,7 +2792,7 @@ pub enum PpMode {
     HirTree,
     /// `-Zunpretty=thir-tree`
     ThirTree,
-    /// `-Zunpretty=`thir-flat`
+    /// `-Zunpretty=thir-flat`
     ThirFlat,
     /// `-Zunpretty=mir`
     Mir,
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 2340d501d5a..162c15574b5 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -235,7 +235,7 @@ impl<D: Decoder> Decodable<D> for DefIndex {
 pub struct DefId {
     // cfg-ing the order of fields so that the `DefIndex` which is high entropy always ends up in
     // the lower bits no matter the endianness. This allows the compiler to turn that `Hash` impl
-    // into a direct call to 'u64::hash(_)`.
+    // into a direct call to `u64::hash(_)`.
     #[cfg(not(all(target_pointer_width = "64", target_endian = "big")))]
     pub index: DefIndex,
     pub krate: CrateNum,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index fb579e4ff77..6272bf7f25e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1954,7 +1954,7 @@ impl Interner {
         let name = Symbol::new(inner.strings.len() as u32);
 
         // SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
-        // and immediately convert the clone back to `&[u8], all because there
+        // and immediately convert the clone back to `&[u8]`, all because there
         // is no `inner.arena.alloc_str()` method. This is clearly safe.
         let string: &str =
             unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) };
diff --git a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
new file mode 100644
index 00000000000..c048d4a2aad
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
@@ -0,0 +1,390 @@
+use std::cmp::Ordering;
+
+use crate::infer::InferCtxt;
+use rustc_middle::infer::canonical::Canonical;
+use rustc_middle::infer::canonical::CanonicalTyVarKind;
+use rustc_middle::infer::canonical::CanonicalVarInfo;
+use rustc_middle::infer::canonical::CanonicalVarInfos;
+use rustc_middle::infer::canonical::CanonicalVarKind;
+use rustc_middle::ty::BoundRegionKind::BrAnon;
+use rustc_middle::ty::BoundTyKind;
+use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::TypeVisitableExt;
+use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+
+/// Whether we're canonicalizing a query input or the query reponse.
+///
+/// When canonicalizing an input we're in the context of the caller
+/// while canonicalizing the response happens in the context of the
+/// query.
+#[derive(Debug, Clone, Copy)]
+pub enum CanonicalizeMode {
+    Input,
+    /// FIXME: We currently return region constraints refering to
+    /// placeholders and inference variables from a binder instantiated
+    /// inside of the query.
+    ///
+    /// In the long term we should eagerly deal with these constraints
+    /// inside of the query and only propagate constraints which are
+    /// actually nameable by the caller.
+    Response {
+        /// The highest universe nameable by the caller.
+        ///
+        /// All variables in a universe nameable by the caller get mapped
+        /// to the root universe in the response and then mapped back to
+        /// their correct universe when applying the query response in the
+        /// context of the caller.
+        ///
+        /// This doesn't work for universes created inside of the query so
+        /// we do remember their universe in the response.
+        max_input_universe: ty::UniverseIndex,
+    },
+}
+
+pub struct Canonicalizer<'a, 'tcx> {
+    infcx: &'a InferCtxt<'tcx>,
+    canonicalize_mode: CanonicalizeMode,
+
+    variables: &'a mut Vec<ty::GenericArg<'tcx>>,
+    primitive_var_infos: Vec<CanonicalVarInfo<'tcx>>,
+    binder_index: ty::DebruijnIndex,
+}
+
+impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
+    #[instrument(level = "debug", skip(infcx), ret)]
+    pub fn canonicalize<T: TypeFoldable<TyCtxt<'tcx>>>(
+        infcx: &'a InferCtxt<'tcx>,
+        canonicalize_mode: CanonicalizeMode,
+        variables: &'a mut Vec<ty::GenericArg<'tcx>>,
+        value: T,
+    ) -> Canonical<'tcx, T> {
+        let mut canonicalizer = Canonicalizer {
+            infcx,
+            canonicalize_mode,
+
+            variables,
+            primitive_var_infos: Vec::new(),
+            binder_index: ty::INNERMOST,
+        };
+
+        let value = value.fold_with(&mut canonicalizer);
+        assert!(!value.needs_infer());
+        assert!(!value.has_placeholders());
+
+        let (max_universe, variables) = canonicalizer.finalize();
+
+        Canonical { max_universe, variables, value }
+    }
+
+    fn finalize(self) -> (ty::UniverseIndex, CanonicalVarInfos<'tcx>) {
+        let mut var_infos = self.primitive_var_infos;
+        // See the rustc-dev-guide section about how we deal with universes
+        // during canonicalization in the new solver.
+        match self.canonicalize_mode {
+            // We try to deduplicate as many query calls as possible and hide
+            // all information which should not matter for the solver.
+            //
+            // For this we compress universes as much as possible.
+            CanonicalizeMode::Input => {}
+            // When canonicalizing a response we map a universes already entered
+            // by the caller to the root universe and only return useful universe
+            // information for placeholders and inference variables created inside
+            // of the query.
+            CanonicalizeMode::Response { max_input_universe } => {
+                for var in var_infos.iter_mut() {
+                    let uv = var.universe();
+                    let new_uv = ty::UniverseIndex::from(
+                        uv.index().saturating_sub(max_input_universe.index()),
+                    );
+                    *var = var.with_updated_universe(new_uv);
+                }
+                let max_universe = var_infos
+                    .iter()
+                    .map(|info| info.universe())
+                    .max()
+                    .unwrap_or(ty::UniverseIndex::ROOT);
+
+                let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
+                return (max_universe, var_infos);
+            }
+        }
+
+        // Given a `var_infos` with existentials `En` and universals `Un` in
+        // universes `n`, this algorithm compresses them in place so that:
+        //
+        // - the new universe indices are as small as possible
+        // - we only create a new universe if we would otherwise put a placeholder in
+        //   the same compressed universe as an existential which cannot name it
+        //
+        // Let's walk through an example:
+        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 0
+        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 1
+        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 1, next_orig_uv: 2
+        // - var_infos: [E0, U1, E5, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 5
+        // - var_infos: [E0, U1, E1, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 6
+        // - var_infos: [E0, U1, E1, U1, E1, E2, U2], curr_compressed_uv: 2, next_orig_uv: -
+        //
+        // This algorithm runs in `O(n²)` where `n` is the number of different universe
+        // indices in the input. This should be fine as `n` is expected to be small.
+        let mut curr_compressed_uv = ty::UniverseIndex::ROOT;
+        let mut existential_in_new_uv = false;
+        let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
+        while let Some(orig_uv) = next_orig_uv.take() {
+            let mut update_uv = |var: &mut CanonicalVarInfo<'tcx>, orig_uv, is_existential| {
+                let uv = var.universe();
+                match uv.cmp(&orig_uv) {
+                    Ordering::Less => (), // Already updated
+                    Ordering::Equal => {
+                        if is_existential {
+                            existential_in_new_uv = true;
+                        } else if existential_in_new_uv {
+                            //  `var` is a placeholder from a universe which is not nameable
+                            // by an existential which we already put into the compressed
+                            // universe `curr_compressed_uv`. We therefore have to create a
+                            // new universe for `var`.
+                            curr_compressed_uv = curr_compressed_uv.next_universe();
+                            existential_in_new_uv = false;
+                        }
+
+                        *var = var.with_updated_universe(curr_compressed_uv);
+                    }
+                    Ordering::Greater => {
+                        // We can ignore this variable in this iteration. We only look at
+                        // universes which actually occur in the input for performance.
+                        //
+                        // For this we set `next_orig_uv` to the next smallest, not yet compressed,
+                        // universe of the input.
+                        if next_orig_uv.map_or(true, |curr_next_uv| uv.cannot_name(curr_next_uv)) {
+                            next_orig_uv = Some(uv);
+                        }
+                    }
+                }
+            };
+
+            // For each universe which occurs in the input, we first iterate over all
+            // placeholders and then over all inference variables.
+            //
+            // Whenever we compress the universe of a placeholder, no existential with
+            // an already compressed universe can name that placeholder.
+            for is_existential in [false, true] {
+                for var in var_infos.iter_mut() {
+                    // We simply put all regions from the input into the highest
+                    // compressed universe, so we only deal with them at the end.
+                    if !var.is_region() {
+                        if is_existential == var.is_existential() {
+                            update_uv(var, orig_uv, is_existential)
+                        }
+                    }
+                }
+            }
+        }
+
+        for var in var_infos.iter_mut() {
+            if var.is_region() {
+                assert!(var.is_existential());
+                *var = var.with_updated_universe(curr_compressed_uv);
+            }
+        }
+
+        let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
+        (curr_compressed_uv, var_infos)
+    }
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
+    fn interner(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
+    where
+        T: TypeFoldable<TyCtxt<'tcx>>,
+    {
+        self.binder_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.binder_index.shift_out(1);
+        t
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        let r = self.infcx.shallow_resolve(r);
+        let kind = match *r {
+            ty::ReLateBound(..) => return r,
+
+            ty::ReStatic => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+                CanonicalizeMode::Response { .. } => return r,
+            },
+
+            ty::ReErased | ty::ReFree(_) | ty::ReEarlyBound(_) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+                CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"),
+            },
+
+            ty::RePlaceholder(placeholder) => match self.canonicalize_mode {
+                // We canonicalize placeholder regions as existentials in query inputs.
+                CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+                CanonicalizeMode::Response { max_input_universe } => {
+                    // If we have a placeholder region inside of a query, it must be from
+                    // a new universe.
+                    if max_input_universe.can_name(placeholder.universe) {
+                        bug!("new placeholder in universe {max_input_universe:?}: {r:?}");
+                    }
+                    CanonicalVarKind::PlaceholderRegion(placeholder)
+                }
+            },
+
+            ty::ReVar(_) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+                CanonicalizeMode::Response { .. } => {
+                    CanonicalVarKind::Region(self.infcx.universe_of_region(r))
+                }
+            },
+
+            ty::ReError(_) => return r,
+        };
+
+        let existing_bound_var = match self.canonicalize_mode {
+            CanonicalizeMode::Input => None,
+            CanonicalizeMode::Response { .. } => {
+                self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from)
+            }
+        };
+        let var = existing_bound_var.unwrap_or_else(|| {
+            let var = ty::BoundVar::from(self.variables.len());
+            self.variables.push(r.into());
+            self.primitive_var_infos.push(CanonicalVarInfo { kind });
+            var
+        });
+        let br = ty::BoundRegion { var, kind: BrAnon(var.as_u32(), None) };
+        self.interner().mk_re_late_bound(self.binder_index, br)
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        let kind = match *t.kind() {
+            ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
+                Ok(t) => return self.fold_ty(t),
+                Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
+            },
+            ty::Infer(ty::IntVar(_)) => {
+                let nt = self.infcx.shallow_resolve(t);
+                if nt != t {
+                    return self.fold_ty(nt);
+                } else {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+                }
+            }
+            ty::Infer(ty::FloatVar(_)) => {
+                let nt = self.infcx.shallow_resolve(t);
+                if nt != t {
+                    return self.fold_ty(nt);
+                } else {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+                }
+            }
+            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+                bug!("fresh var during canonicalization: {t:?}")
+            }
+            ty::Placeholder(placeholder) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
+                    universe: placeholder.universe,
+                    name: BoundTyKind::Anon(self.variables.len() as u32),
+                }),
+                CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
+            },
+            ty::Param(_) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
+                    universe: ty::UniverseIndex::ROOT,
+                    name: ty::BoundTyKind::Anon(self.variables.len() as u32),
+                }),
+                CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"),
+            },
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Adt(_, _)
+            | ty::Foreign(_)
+            | ty::Str
+            | ty::Array(_, _)
+            | ty::Slice(_)
+            | ty::RawPtr(_)
+            | ty::Ref(_, _, _)
+            | ty::FnDef(_, _)
+            | ty::FnPtr(_)
+            | ty::Dynamic(_, _, _)
+            | ty::Closure(_, _)
+            | ty::Generator(_, _, _)
+            | ty::GeneratorWitness(_)
+            | ty::GeneratorWitnessMIR(..)
+            | ty::Never
+            | ty::Tuple(_)
+            | ty::Alias(_, _)
+            | ty::Bound(_, _)
+            | ty::Error(_) => return t.super_fold_with(self),
+        };
+
+        let var = ty::BoundVar::from(
+            self.variables.iter().position(|&v| v == t.into()).unwrap_or_else(|| {
+                let var = self.variables.len();
+                self.variables.push(t.into());
+                self.primitive_var_infos.push(CanonicalVarInfo { kind });
+                var
+            }),
+        );
+        let bt = ty::BoundTy { var, kind: BoundTyKind::Anon(var.index() as u32) };
+        self.interner().mk_bound(self.binder_index, bt)
+    }
+
+    fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+        let kind = match c.kind() {
+            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => match self.infcx.probe_const_var(vid)
+            {
+                Ok(c) => return self.fold_const(c),
+                Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
+            },
+            ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
+                bug!("fresh var during canonicalization: {c:?}")
+            }
+            ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
+                    ty::Placeholder {
+                        universe: placeholder.universe,
+                        name: ty::BoundVar::from(self.variables.len()),
+                    },
+                    c.ty(),
+                ),
+                CanonicalizeMode::Response { .. } => {
+                    CanonicalVarKind::PlaceholderConst(placeholder, c.ty())
+                }
+            },
+            ty::ConstKind::Param(_) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
+                    ty::Placeholder {
+                        universe: ty::UniverseIndex::ROOT,
+                        name: ty::BoundVar::from(self.variables.len()),
+                    },
+                    c.ty(),
+                ),
+                CanonicalizeMode::Response { .. } => bug!("param ty in response: {c:?}"),
+            },
+            ty::ConstKind::Bound(_, _)
+            | ty::ConstKind::Unevaluated(_)
+            | ty::ConstKind::Value(_)
+            | ty::ConstKind::Error(_)
+            | ty::ConstKind::Expr(_) => return c.super_fold_with(self),
+        };
+
+        let var = ty::BoundVar::from(
+            self.variables.iter().position(|&v| v == c.into()).unwrap_or_else(|| {
+                let var = self.variables.len();
+                self.variables.push(c.into());
+                self.primitive_var_infos.push(CanonicalVarInfo { kind });
+                var
+            }),
+        );
+        self.interner().mk_const(ty::ConstKind::Bound(self.binder_index, var), c.ty())
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/canonical/mod.rs b/compiler/rustc_trait_selection/src/solve/canonical/mod.rs
new file mode 100644
index 00000000000..8c3be8da16b
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/canonical/mod.rs
@@ -0,0 +1,240 @@
+/// Canonicalization is used to separate some goal from its context,
+/// throwing away unnecessary information in the process.
+///
+/// This is necessary to cache goals containing inference variables
+/// and placeholders without restricting them to the current `InferCtxt`.
+///
+/// Canonicalization is fairly involved, for more details see the relevant
+/// section of the [rustc-dev-guide][c].
+///
+/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
+use self::canonicalize::{CanonicalizeMode, Canonicalizer};
+use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
+use super::{CanonicalResponse, ExternalConstraints, QueryResult, Response};
+use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
+use rustc_infer::infer::canonical::CanonicalVarValues;
+use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::solve::ExternalConstraintsData;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::ty::{self, GenericArgKind};
+use rustc_span::DUMMY_SP;
+use std::iter;
+use std::ops::Deref;
+
+mod canonicalize;
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+    /// Canonicalizes the goal remembering the original values
+    /// for each bound variable.
+    pub(super) fn canonicalize_goal(
+        &self,
+        goal: Goal<'tcx, ty::Predicate<'tcx>>,
+    ) -> (Vec<ty::GenericArg<'tcx>>, CanonicalGoal<'tcx>) {
+        let mut orig_values = Default::default();
+        let canonical_goal = Canonicalizer::canonicalize(
+            self.infcx,
+            CanonicalizeMode::Input,
+            &mut orig_values,
+            goal,
+        );
+        (orig_values, canonical_goal)
+    }
+
+    /// To return the constraints of a canonical query to the caller, we canonicalize:
+    ///
+    /// - `var_values`: a map from bound variables in the canonical goal to
+    ///   the values inferred while solving the instantiated goal.
+    /// - `external_constraints`: additional constraints which aren't expressable
+    ///   using simple unification of inference variables.
+    #[instrument(level = "debug", skip(self))]
+    pub(super) fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> {
+        let external_constraints = self.compute_external_query_constraints()?;
+
+        let response = Response { var_values: self.var_values, external_constraints, certainty };
+        let canonical = Canonicalizer::canonicalize(
+            self.infcx,
+            CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
+            &mut Default::default(),
+            response,
+        );
+        Ok(canonical)
+    }
+
+    #[instrument(level = "debug", skip(self), ret)]
+    fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
+        // Cannot use `take_registered_region_obligations` as we may compute the response
+        // inside of a `probe` whenever we have multiple choices inside of the solver.
+        let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
+        let region_constraints = self.infcx.with_region_constraints(|region_constraints| {
+            make_query_region_constraints(
+                self.tcx(),
+                region_obligations
+                    .iter()
+                    .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
+                region_constraints,
+            )
+        });
+        let opaque_types = self.infcx.clone_opaque_types_for_query_response();
+        Ok(self
+            .tcx()
+            .mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types }))
+    }
+
+    /// After calling a canonical query, we apply the constraints returned
+    /// by the query using this function.
+    ///
+    /// This happens in three steps:
+    /// - we instantiate the bound variables of the query response
+    /// - we unify the `var_values` of the response with the `original_values`
+    /// - we apply the `external_constraints` returned by the query
+    pub(super) fn instantiate_and_apply_query_response(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        original_values: Vec<ty::GenericArg<'tcx>>,
+        response: CanonicalResponse<'tcx>,
+    ) -> Result<Certainty, NoSolution> {
+        let substitution = self.compute_query_response_substitution(&original_values, &response);
+
+        let Response { var_values, external_constraints, certainty } =
+            response.substitute(self.tcx(), &substitution);
+
+        self.unify_query_var_values(param_env, &original_values, var_values)?;
+
+        // FIXME: implement external constraints.
+        let ExternalConstraintsData { region_constraints, opaque_types: _ } =
+            external_constraints.deref();
+        self.register_region_constraints(region_constraints);
+
+        Ok(certainty)
+    }
+
+    /// This returns the substitutions to instantiate the bound variables of
+    /// the canonical reponse. This depends on the `original_values` for the
+    /// bound variables.
+    fn compute_query_response_substitution(
+        &self,
+        original_values: &[ty::GenericArg<'tcx>],
+        response: &CanonicalResponse<'tcx>,
+    ) -> CanonicalVarValues<'tcx> {
+        // FIXME: Longterm canonical queries should deal with all placeholders
+        // created inside of the query directly instead of returning them to the
+        // caller.
+        let prev_universe = self.infcx.universe();
+        let universes_created_in_query = response.max_universe.index() + 1;
+        for _ in 0..universes_created_in_query {
+            self.infcx.create_next_universe();
+        }
+
+        let var_values = response.value.var_values;
+        assert_eq!(original_values.len(), var_values.len());
+
+        // If the query did not make progress with constraining inference variables,
+        // we would normally create a new inference variables for bound existential variables
+        // only then unify this new inference variable with the inference variable from
+        // the input.
+        //
+        // We therefore instantiate the existential variable in the canonical response with the
+        // inference variable of the input right away, which is more performant.
+        let mut opt_values = vec![None; response.variables.len()];
+        for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
+            match result_value.unpack() {
+                GenericArgKind::Type(t) => {
+                    if let &ty::Bound(debruijn, b) = t.kind() {
+                        assert_eq!(debruijn, ty::INNERMOST);
+                        opt_values[b.var.index()] = Some(*original_value);
+                    }
+                }
+                GenericArgKind::Lifetime(r) => {
+                    if let ty::ReLateBound(debruijn, br) = *r {
+                        assert_eq!(debruijn, ty::INNERMOST);
+                        opt_values[br.var.index()] = Some(*original_value);
+                    }
+                }
+                GenericArgKind::Const(c) => {
+                    if let ty::ConstKind::Bound(debrujin, b) = c.kind() {
+                        assert_eq!(debrujin, ty::INNERMOST);
+                        opt_values[b.index()] = Some(*original_value);
+                    }
+                }
+            }
+        }
+
+        let var_values = self.tcx().mk_substs_from_iter(response.variables.iter().enumerate().map(
+            |(index, info)| {
+                if info.universe() != ty::UniverseIndex::ROOT {
+                    // A variable from inside a binder of the query. While ideally these shouldn't
+                    // exist at all (see the FIXME at the start of this method), we have to deal with
+                    // them for now.
+                    self.infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| {
+                        ty::UniverseIndex::from(prev_universe.index() + idx.index())
+                    })
+                } else if info.is_existential() {
+                    // As an optimization we sometimes avoid creating a new inference variable here.
+                    //
+                    // All new inference variables we create start out in the current universe of the caller.
+                    // This is conceptionally wrong as these inference variables would be able to name
+                    // more placeholders then they should be able to. However the inference variables have
+                    // to "come from somewhere", so by equating them with the original values of the caller
+                    // later on, we pull them down into their correct universe again.
+                    if let Some(v) = opt_values[index] {
+                        v
+                    } else {
+                        self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)
+                    }
+                } else {
+                    // For placeholders which were already part of the input, we simply map this
+                    // universal bound variable back the placeholder of the input.
+                    original_values[info.expect_anon_placeholder() as usize]
+                }
+            },
+        ));
+
+        CanonicalVarValues { var_values }
+    }
+
+    #[instrument(level = "debug", skip(self, param_env), ret)]
+    fn unify_query_var_values(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        original_values: &[ty::GenericArg<'tcx>],
+        var_values: CanonicalVarValues<'tcx>,
+    ) -> Result<(), NoSolution> {
+        assert_eq!(original_values.len(), var_values.len());
+        for (&orig, response) in iter::zip(original_values, var_values.var_values) {
+            // This can fail due to the occurs check, see
+            // `tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs` for an example
+            // where that can happen.
+            //
+            // FIXME: To deal with #105787 I also expect us to emit nested obligations here at
+            // some point. We can figure out how to deal with this once we actually have
+            // an ICE.
+            let nested_goals = self.eq(param_env, orig, response)?;
+            assert!(nested_goals.is_empty(), "{nested_goals:?}");
+        }
+
+        Ok(())
+    }
+
+    fn register_region_constraints(&mut self, region_constraints: &QueryRegionConstraints<'tcx>) {
+        for &(ty::OutlivesPredicate(lhs, rhs), _) in &region_constraints.outlives {
+            match lhs.unpack() {
+                GenericArgKind::Lifetime(lhs) => self.infcx.region_outlives_predicate(
+                    &ObligationCause::dummy(),
+                    ty::Binder::dummy(ty::OutlivesPredicate(lhs, rhs)),
+                ),
+                GenericArgKind::Type(lhs) => self.infcx.register_region_obligation_with_cause(
+                    lhs,
+                    rhs,
+                    &ObligationCause::dummy(),
+                ),
+                GenericArgKind::Const(_) => bug!("const outlives: {lhs:?}: {rhs:?}"),
+            }
+        }
+
+        for member_constraint in &region_constraints.member_constraints {
+            // FIXME: Deal with member constraints :<
+            let _ = member_constraint;
+        }
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index c8097e81953..95612674eb9 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -19,8 +19,17 @@ use super::Goal;
 pub struct EvalCtxt<'a, 'tcx> {
     // FIXME: should be private.
     pub(super) infcx: &'a InferCtxt<'tcx>,
-
     pub(super) var_values: CanonicalVarValues<'tcx>,
+    /// The highest universe index nameable by the caller.
+    ///
+    /// When we enter a new binder inside of the query we create new universes
+    /// which the caller cannot name. We have to be careful with variables from
+    /// these new universes when creating the query response.
+    ///
+    /// Both because these new universes can prevent us from reaching a fixpoint
+    /// if we have a coinductive cycle and because that's the only way we can return
+    /// new placeholders to the caller.
+    pub(super) max_input_universe: ty::UniverseIndex,
 
     pub(super) search_graph: &'a mut SearchGraph<'tcx>,
 
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 71f536dd3cb..57b6a452737 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -19,11 +19,9 @@ use std::mem;
 
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
-use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::Obligation;
-use rustc_middle::infer::canonical::Certainty as OldCertainty;
 use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{
@@ -35,6 +33,7 @@ use crate::solve::search_graph::OverflowHandler;
 use crate::traits::ObligationCause;
 
 mod assembly;
+mod canonical;
 mod eval_ctxt;
 mod fulfill;
 mod project_goals;
@@ -89,11 +88,8 @@ trait CanonicalResponseExt {
 
 impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> {
     fn has_no_inference_or_external_constraints(&self) -> bool {
-        // so that we get a compile error when regions are supported
-        // so this code can be checked for being correct
-        let _: () = self.value.external_constraints.regions;
-
-        self.value.var_values.is_identity()
+        self.value.external_constraints.region_constraints.is_empty()
+            && self.value.var_values.is_identity()
             && self.value.external_constraints.opaque_types.is_empty()
     }
 }
@@ -169,6 +165,8 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
         let result = EvalCtxt {
             search_graph: &mut search_graph,
             infcx: self,
+            // Only relevant when canonicalizing the response.
+            max_input_universe: ty::UniverseIndex::ROOT,
             var_values: CanonicalVarValues::dummy(),
             in_projection_eq_hack: false,
         }
@@ -201,36 +199,33 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         search_graph.with_new_goal(tcx, canonical_goal, |search_graph| {
             let (ref infcx, goal, var_values) =
                 tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
-            let mut ecx =
-                EvalCtxt { infcx, var_values, search_graph, in_projection_eq_hack: false };
+            let mut ecx = EvalCtxt {
+                infcx,
+                var_values,
+                max_input_universe: canonical_goal.max_universe,
+                search_graph,
+                in_projection_eq_hack: false,
+            };
             ecx.compute_goal(goal)
         })
     }
 
-    fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> {
-        let external_constraints = compute_external_query_constraints(self.infcx)?;
-
-        Ok(self.infcx.canonicalize_response(Response {
-            var_values: self.var_values,
-            external_constraints,
-            certainty,
-        }))
-    }
-
     /// Recursively evaluates `goal`, returning whether any inference vars have
     /// been constrained and the certainty of the result.
     fn evaluate_goal(
         &mut self,
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
     ) -> Result<(bool, Certainty), NoSolution> {
-        let mut orig_values = OriginalQueryValues::default();
-        let canonical_goal = self.infcx.canonicalize_query(goal, &mut orig_values);
+        let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
         let canonical_response =
             EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
 
         let has_changed = !canonical_response.value.var_values.is_identity();
-        let certainty =
-            instantiate_canonical_query_response(self.infcx, &orig_values, canonical_response);
+        let certainty = self.instantiate_and_apply_query_response(
+            goal.param_env,
+            orig_values,
+            canonical_response,
+        )?;
 
         // Check that rerunning this query with its inference constraints applied
         // doesn't result in new inference constraints and has the same result.
@@ -244,8 +239,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             && !self.in_projection_eq_hack
             && !self.search_graph.in_cycle()
         {
-            let mut orig_values = OriginalQueryValues::default();
-            let canonical_goal = self.infcx.canonicalize_query(goal, &mut orig_values);
+            let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
             let canonical_response =
                 EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
             if !canonical_response.value.var_values.is_identity() {
@@ -316,15 +310,21 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
 
     fn compute_type_outlives_goal(
         &mut self,
-        _goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>,
+        goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>,
     ) -> QueryResult<'tcx> {
+        let ty::OutlivesPredicate(ty, lt) = goal.predicate;
+        self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy());
         self.make_canonical_response(Certainty::Yes)
     }
 
     fn compute_region_outlives_goal(
         &mut self,
-        _goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>,
+        goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>,
     ) -> QueryResult<'tcx> {
+        self.infcx.region_outlives_predicate(
+            &ObligationCause::dummy(),
+            ty::Binder::dummy(goal.predicate),
+        );
         self.make_canonical_response(Certainty::Yes)
     }
 
@@ -561,49 +561,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     }
 }
 
-#[instrument(level = "debug", skip(infcx), ret)]
-fn compute_external_query_constraints<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-) -> Result<ExternalConstraints<'tcx>, NoSolution> {
-    let region_obligations = infcx.take_registered_region_obligations();
-    let opaque_types = infcx.take_opaque_types_for_query_response();
-    Ok(infcx.tcx.mk_external_constraints(ExternalConstraintsData {
-        // FIXME: Now that's definitely wrong :)
-        //
-        // Should also do the leak check here I think
-        regions: drop(region_obligations),
-        opaque_types,
-    }))
-}
-
-fn instantiate_canonical_query_response<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-    original_values: &OriginalQueryValues<'tcx>,
-    response: CanonicalResponse<'tcx>,
-) -> Certainty {
-    let Ok(InferOk { value, obligations }) = infcx
-        .instantiate_query_response_and_region_obligations(
-            &ObligationCause::dummy(),
-            ty::ParamEnv::empty(),
-            original_values,
-            &response.unchecked_map(|resp| QueryResponse {
-                var_values: resp.var_values,
-                region_constraints: QueryRegionConstraints::default(),
-                certainty: match resp.certainty {
-                    Certainty::Yes => OldCertainty::Proven,
-                    Certainty::Maybe(_) => OldCertainty::Ambiguous,
-                },
-                // FIXME: This to_owned makes me sad, but we should eventually impl
-                // `instantiate_query_response_and_region_obligations` separately
-                // instead of piggybacking off of the old implementation.
-                opaque_types: resp.external_constraints.opaque_types.to_owned(),
-                value: resp.certainty,
-            }),
-        ) else { bug!(); };
-    assert!(obligations.is_empty());
-    value
-}
-
 pub(super) fn response_no_constraints<'tcx>(
     tcx: TyCtxt<'tcx>,
     goal: Canonical<'tcx, impl Sized>,
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 88fd8bb8bd0..33c66d072e9 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -77,10 +77,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let nested_goals = self
             .eq(goal.param_env, goal.predicate.term, normalized_alias.into())
             .expect("failed to unify with unconstrained term");
-        let rhs_certainty =
+
+        let unify_certainty =
             self.evaluate_all(nested_goals).expect("failed to unify with unconstrained term");
 
-        self.make_canonical_response(normalization_certainty.unify_and(rhs_certainty))
+        self.make_canonical_response(normalization_certainty.unify_and(unify_certainty))
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 013db2edb39..870ecc2a970 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1175,7 +1175,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 /// paths you want to take. To make things worse, it was possible for
 /// cycles to arise, where you basically had a setup like `<MyType<$0>
 /// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
-/// Trait>::Foo> to `[type error]` would lead to an obligation of
+/// Trait>::Foo>` to `[type error]` would lead to an obligation of
 /// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
 /// an error for this obligation, but we legitimately should not,
 /// because it contains `[type error]`. Yuck! (See issue #29857 for
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 4ad13dcb645..e91057356a2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -339,7 +339,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // Essentially any user-written impl will match with an error type,
         // so creating `ImplCandidates` isn't useful. However, we might
-        // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
+        // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized`)
         // This helps us avoid overflow: see issue #72839
         // Since compilation is already guaranteed to fail, this is just
         // to try to show the 'nicest' possible errors to the user.
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 01c1ad3a4ce..4377de15829 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -151,7 +151,7 @@ struct TraitObligationStack<'prev, 'tcx> {
     /// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`
     /// is `EvaluatedToOk`; this is because they were only considered
     /// ok on the premise that if `A: AutoTrait` held, but we indeed
-    /// encountered a problem (later on) with `A: AutoTrait. So we
+    /// encountered a problem (later on) with `A: AutoTrait`. So we
     /// currently set a flag on the stack node for `B: AutoTrait` (as
     /// well as the second instance of `A: AutoTrait`) to suppress
     /// caching.
@@ -727,7 +727,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             // Otherwise, we can say that `T: NonAutoTrait` is
                             // true.
                             // Let's imagine we have a predicate stack like
-                            //         `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto
+                            //         `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto`
                             // depth   ^1                    ^2                 ^3
                             // and the current predicate is `WF(T)`. `wf_args`
                             // would contain `(T, 1)`. We want to check all