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/ast.rs4
-rw-r--r--compiler/rustc_ast/src/format.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs1
-rw-r--r--compiler/rustc_ast/src/visit.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs27
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs13
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs49
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs4
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs5
-rw-r--r--compiler/rustc_borrowck/src/constraint_generation.rs6
-rw-r--r--compiler/rustc_borrowck/src/constraints/graph.rs32
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/find_use.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs6
-rw-r--r--compiler/rustc_borrowck/src/lib.rs10
-rw-r--r--compiler/rustc_borrowck/src/nll.rs23
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs23
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs45
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs19
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs16
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs63
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs62
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs10
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs12
-rw-r--r--compiler/rustc_data_structures/Cargo.toml1
-rw-r--r--compiler/rustc_data_structures/src/sso/either_iter.rs73
-rw-r--r--compiler/rustc_data_structures/src/sso/map.rs70
-rw-r--r--compiler/rustc_data_structures/src/sso/mod.rs1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs77
-rw-r--r--compiler/rustc_errors/src/emitter.rs50
-rw-r--r--compiler/rustc_errors/src/lib.rs3
-rw-r--r--compiler/rustc_expand/messages.ftl2
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs7
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs40
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs27
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs45
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs28
-rw-r--r--compiler/rustc_infer/messages.ftl3
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs6
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs123
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs106
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs4
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs142
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs105
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs47
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs6
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs6
-rw-r--r--compiler/rustc_infer/src/traits/structural_impls.rs3
-rw-r--r--compiler/rustc_lexer/src/lib.rs43
-rw-r--r--compiler/rustc_lexer/src/tests.rs2
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/internal.rs6
-rw-r--r--compiler/rustc_lint/src/let_underscore.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs4
-rw-r--r--compiler/rustc_lint/src/lints.rs14
-rw-r--r--compiler/rustc_lint/src/non_ascii_idents.rs6
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs2
-rw-r--r--compiler/rustc_log/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs2
-rw-r--r--compiler/rustc_middle/src/macros.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs5
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs1
-rw-r--r--compiler/rustc_middle/src/query/erase.rs2
-rw-r--r--compiler/rustc_middle/src/query/keys.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs5
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs100
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/errors.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs16
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs16
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs7
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs7
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs2
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/lexer/diagnostics.rs6
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs9
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs4
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/path.rs25
-rw-r--r--compiler/rustc_parse_format/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/dead.rs62
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs2
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs44
-rw-r--r--compiler/rustc_resolve/messages.ftl2
-rw-r--r--compiler/rustc_resolve/src/late.rs3
-rw-r--r--compiler/rustc_resolve/src/lib.rs3
-rw-r--r--compiler/rustc_session/src/config.rs2
-rw-r--r--compiler/rustc_span/src/edit_distance.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs2
-rw-r--r--compiler/rustc_target/src/asm/m68k.rs81
-rw-r--r--compiler/rustc_target/src/asm/mod.rs24
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonicalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs29
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs4
-rw-r--r--compiler/rustc_ty_utils/messages.ftl4
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs2
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
150 files changed, 1123 insertions, 1201 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index fb9d71b52a8..df1a716755b 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -167,9 +167,6 @@ pub enum GenericArgs {
     AngleBracketed(AngleBracketedArgs),
     /// The `(A, B)` and `C` in `Foo(A, B) -> C`.
     Parenthesized(ParenthesizedArgs),
-    /// Associated return type bounds, like `T: Trait<method(..): Send>`
-    /// which applies the `Send` bound to the return-type of `method`.
-    ReturnTypeNotation(Span),
 }
 
 impl GenericArgs {
@@ -181,7 +178,6 @@ impl GenericArgs {
         match self {
             AngleBracketed(data) => data.span,
             Parenthesized(data) => data.span,
-            ReturnTypeNotation(span) => *span,
         }
     }
 }
diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs
index 356b9bb6371..699946f307b 100644
--- a/compiler/rustc_ast/src/format.rs
+++ b/compiler/rustc_ast/src/format.rs
@@ -94,7 +94,7 @@ impl FormatArguments {
         }
         if !matches!(arg.kind, FormatArgumentKind::Captured(..)) {
             // This is an explicit argument.
-            // Make sure that all arguments so far are explcit.
+            // Make sure that all arguments so far are explicit.
             assert_eq!(
                 self.num_explicit_args,
                 self.arguments.len(),
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 2424073ae53..694d31d8f1f 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -561,7 +561,6 @@ pub fn noop_visit_generic_args<T: MutVisitor>(generic_args: &mut GenericArgs, vi
     match generic_args {
         GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
         GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
-        GenericArgs::ReturnTypeNotation(_span) => {}
     }
 }
 
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 3b08467fde2..ac9b321b71c 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -482,7 +482,6 @@ where
             walk_list!(visitor, visit_ty, &data.inputs);
             walk_fn_ret_ty(visitor, &data.output);
         }
-        GenericArgs::ReturnTypeNotation(_span) => {}
     }
 }
 
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index f4e55619ebb..3e9f9b43623 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -137,7 +137,7 @@ pub struct AsyncNonMoveClosureNotSupported {
 
 #[derive(Diagnostic, Clone, Copy)]
 #[diag(ast_lowering_functional_record_update_destructuring_assignment)]
-pub struct FunctionalRecordUpdateDestructuringAssignemnt {
+pub struct FunctionalRecordUpdateDestructuringAssignment {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub span: Span,
@@ -353,13 +353,7 @@ pub enum BadReturnTypeNotation {
     #[diag(ast_lowering_bad_return_type_notation_inputs)]
     Inputs {
         #[primary_span]
-        #[suggestion(code = "(..)", applicability = "maybe-incorrect")]
-        span: Span,
-    },
-    #[diag(ast_lowering_bad_return_type_notation_needs_dots)]
-    NeedsDots {
-        #[primary_span]
-        #[suggestion(code = "(..)", applicability = "maybe-incorrect")]
+        #[suggestion(code = "()", applicability = "maybe-incorrect")]
         span: Span,
     },
     #[diag(ast_lowering_bad_return_type_notation_output)]
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 3247802345b..1b1c4765bc0 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1,6 +1,6 @@
 use super::errors::{
     AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
-    BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt,
+    BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignment,
     GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure,
     UnderscoreExprLhsAssign,
 };
@@ -434,7 +434,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
         // condition in this case.
         //
-        // In order to mantain the drop behavior for the non `let` parts of the condition,
+        // In order to maintain the drop behavior for the non `let` parts of the condition,
         // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
         // gets transformed into `if { let _t = foo; _t } && let pat = val`
         match &cond.kind {
@@ -1232,7 +1232,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 let fields_omitted = match &se.rest {
                     StructRest::Base(e) => {
-                        self.tcx.sess.emit_err(FunctionalRecordUpdateDestructuringAssignemnt {
+                        self.tcx.sess.emit_err(FunctionalRecordUpdateDestructuringAssignment {
                             span: e.span,
                         });
                         true
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index ca659db4dbe..f7ae96b7c4a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -987,15 +987,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 GenericArgs::AngleBracketed(data) => {
                     self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
                 }
-                &GenericArgs::ReturnTypeNotation(span) => GenericArgsCtor {
-                    args: Default::default(),
-                    bindings: &[],
-                    parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
-                    span,
-                },
                 GenericArgs::Parenthesized(data) => {
-                    if let Some(start_char) = constraint.ident.as_str().chars().next()
-                        && start_char.is_ascii_lowercase()
+                    if data.inputs.is_empty() && matches!(data.output, FnRetTy::Default(..)) {
+                        let parenthesized = if self.tcx.features().return_type_notation {
+                            hir::GenericArgsParentheses::ReturnTypeNotation
+                        } else {
+                            self.emit_bad_parenthesized_trait_in_assoc_ty(data);
+                            hir::GenericArgsParentheses::No
+                        };
+                        GenericArgsCtor {
+                            args: Default::default(),
+                            bindings: &[],
+                            parenthesized,
+                            span: data.inputs_span,
+                        }
+                    } else if let Some(first_char) = constraint.ident.as_str().chars().next()
+                        && first_char.is_ascii_lowercase()
                     {
                         let mut err = if !data.inputs.is_empty() {
                             self.tcx.sess.create_err(errors::BadReturnTypeNotation::Inputs {
@@ -1006,9 +1013,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 span: data.inputs_span.shrink_to_hi().to(ty.span),
                             })
                         } else {
-                            self.tcx.sess.create_err(errors::BadReturnTypeNotation::NeedsDots {
-                                span: data.inputs_span,
-                            })
+                            unreachable!("inputs are empty and return type is not provided")
                         };
                         if !self.tcx.features().return_type_notation
                             && self.tcx.sess.is_nightly_build()
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 1c47a969696..8eb84c036a0 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -13,7 +13,6 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
 use smallvec::{smallvec, SmallVec};
-use thin_vec::ThinVec;
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     #[instrument(level = "trace", skip(self))]
@@ -219,18 +218,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         )
                     }
                 },
-                &GenericArgs::ReturnTypeNotation(span) => {
-                    self.tcx.sess.emit_err(GenericTypeWithParentheses { span, sub: None });
-                    (
-                        self.lower_angle_bracketed_parameter_data(
-                            &AngleBracketedArgs { span, args: ThinVec::default() },
-                            param_mode,
-                            itctx,
-                        )
-                        .0,
-                        false,
-                    )
-                }
             }
         } else {
             (
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index e7cdfeca6f9..c79626ccd76 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1080,7 +1080,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.with_impl_trait(None, |this| this.visit_ty(ty));
                 }
             }
-            GenericArgs::ReturnTypeNotation(_span) => {}
         }
     }
 
@@ -1391,7 +1390,6 @@ fn deny_equality_constraints(
                                     match &mut assoc_path.segments[len].args {
                                         Some(args) => match args.deref_mut() {
                                             GenericArgs::Parenthesized(_) => continue,
-                                            GenericArgs::ReturnTypeNotation(_span) => continue,
                                             GenericArgs::AngleBracketed(args) => {
                                                 args.args.push(arg);
                                             }
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 007d64f681f..17bcd24ee39 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -121,24 +121,34 @@ impl<'a> PostExpansionVisitor<'a> {
     }
 
     /// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
-    fn check_impl_trait(&self, ty: &ast::Ty) {
+    fn check_impl_trait(&self, ty: &ast::Ty, in_associated_ty: bool) {
         struct ImplTraitVisitor<'a> {
             vis: &'a PostExpansionVisitor<'a>,
+            in_associated_ty: bool,
         }
         impl Visitor<'_> for ImplTraitVisitor<'_> {
             fn visit_ty(&mut self, ty: &ast::Ty) {
                 if let ast::TyKind::ImplTrait(..) = ty.kind {
-                    gate_feature_post!(
-                        &self.vis,
-                        type_alias_impl_trait,
-                        ty.span,
-                        "`impl Trait` in type aliases is unstable"
-                    );
+                    if self.in_associated_ty {
+                        gate_feature_post!(
+                            &self.vis,
+                            impl_trait_in_assoc_type,
+                            ty.span,
+                            "`impl Trait` in associated types is unstable"
+                        );
+                    } else {
+                        gate_feature_post!(
+                            &self.vis,
+                            type_alias_impl_trait,
+                            ty.span,
+                            "`impl Trait` in type aliases is unstable"
+                        );
+                    }
                 }
                 visit::walk_ty(self, ty);
             }
         }
-        ImplTraitVisitor { vis: self }.visit_ty(ty);
+        ImplTraitVisitor { vis: self, in_associated_ty }.visit_ty(ty);
     }
 
     fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
@@ -294,7 +304,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             }
 
             ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
-                self.check_impl_trait(&ty)
+                self.check_impl_trait(&ty, false)
             }
 
             _ => {}
@@ -485,20 +495,23 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
     fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) {
         if let AssocConstraintKind::Bound { .. } = constraint.kind {
-            if let Some(args) = constraint.gen_args.as_ref()
-                && matches!(
-                    args,
-                    ast::GenericArgs::ReturnTypeNotation(..)
-                )
+            if let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref()
+                && args.inputs.is_empty()
+                && matches!(args.output, ast::FnRetTy::Default(..))
             {
-                // RTN is gated below with a `gate_all`.
+                gate_feature_post!(
+                    &self,
+                    return_type_notation,
+                    constraint.span,
+                    "return type notation is experimental"
+                );
             } else {
                 gate_feature_post!(
                     &self,
                     associated_type_bounds,
                     constraint.span,
                     "associated type bounds are unstable"
-                )
+                );
             }
         }
         visit::walk_assoc_constraint(self, constraint)
@@ -517,7 +530,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     );
                 }
                 if let Some(ty) = ty {
-                    self.check_impl_trait(ty);
+                    self.check_impl_trait(ty, true);
                 }
                 false
             }
@@ -589,7 +602,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
     gate_all!(yeet_expr, "`do yeet` expression is experimental");
     gate_all!(dyn_star, "`dyn*` trait objects are experimental");
     gate_all!(const_closures, "const closures are experimental");
-    gate_all!(return_type_notation, "return type notation is experimental");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
@@ -605,6 +617,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
 
     gate_all!(trait_alias, "trait aliases are experimental");
     gate_all!(associated_type_bounds, "associated type bounds are unstable");
+    gate_all!(return_type_notation, "return type notation is experimental");
     gate_all!(decl_macro, "`macro` is experimental");
     gate_all!(box_patterns, "box pattern syntax is experimental");
     gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 1f6838a0278..849336c8669 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -936,10 +936,6 @@ impl<'a> PrintState<'a> for State<'a> {
                 self.word(")");
                 self.print_fn_ret_ty(&data.output);
             }
-
-            ast::GenericArgs::ReturnTypeNotation(_span) => {
-                self.word("(..)");
-            }
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index fa0552e012d..4824f6346d4 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -1,6 +1,5 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-use crate::nll::ToRegionVid;
 use crate::path_utils::allow_two_phase_borrow;
 use crate::place_ext::PlaceExt;
 use crate::BorrowIndex;
@@ -204,7 +203,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
                 return;
             }
 
-            let region = region.to_region_vid();
+            let region = region.as_var();
 
             let borrow = BorrowData {
                 kind,
@@ -279,7 +278,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
             let borrow_data = &self.location_map[&location];
             assert_eq!(borrow_data.reserve_location, location);
             assert_eq!(borrow_data.kind, kind);
-            assert_eq!(borrow_data.region, region.to_region_vid());
+            assert_eq!(borrow_data.region, region.as_var());
             assert_eq!(borrow_data.borrowed_place, place);
         }
 
diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index 1427f5cb31d..2aa09a3f26c 100644
--- a/compiler/rustc_borrowck/src/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -12,8 +12,8 @@ use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
 
 use crate::{
-    borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid,
-    places_conflict, region_infer::values::LivenessValues,
+    borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict,
+    region_infer::values::LivenessValues,
 };
 
 pub(super) fn generate_constraints<'tcx>(
@@ -170,7 +170,7 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
         debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location);
 
         self.infcx.tcx.for_each_free_region(&live_ty, |live_region| {
-            let vid = live_region.to_region_vid();
+            let vid = live_region.as_var();
             self.liveness_constraints.add_element(vid, location);
         });
     }
diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs
index c780d047992..f5a34cb0561 100644
--- a/compiler/rustc_borrowck/src/constraints/graph.rs
+++ b/compiler/rustc_borrowck/src/constraints/graph.rs
@@ -13,7 +13,7 @@ use crate::{
 /// The construct graph organizes the constraints by their end-points.
 /// It can be used to view a `R1: R2` constraint as either an edge `R1
 /// -> R2` or `R2 -> R1` depending on the direction type `D`.
-pub(crate) struct ConstraintGraph<D: ConstraintGraphDirecton> {
+pub(crate) struct ConstraintGraph<D: ConstraintGraphDirection> {
     _direction: D,
     first_constraints: IndexVec<RegionVid, Option<OutlivesConstraintIndex>>,
     next_constraints: IndexVec<OutlivesConstraintIndex, Option<OutlivesConstraintIndex>>,
@@ -25,7 +25,7 @@ pub(crate) type ReverseConstraintGraph = ConstraintGraph<Reverse>;
 
 /// Marker trait that controls whether a `R1: R2` constraint
 /// represents an edge `R1 -> R2` or `R2 -> R1`.
-pub(crate) trait ConstraintGraphDirecton: Copy + 'static {
+pub(crate) trait ConstraintGraphDirection: Copy + 'static {
     fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid;
     fn end_region(c: &OutlivesConstraint<'_>) -> RegionVid;
     fn is_normal() -> bool;
@@ -38,7 +38,7 @@ pub(crate) trait ConstraintGraphDirecton: Copy + 'static {
 #[derive(Copy, Clone, Debug)]
 pub(crate) struct Normal;
 
-impl ConstraintGraphDirecton for Normal {
+impl ConstraintGraphDirection for Normal {
     fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sup
     }
@@ -59,7 +59,7 @@ impl ConstraintGraphDirecton for Normal {
 #[derive(Copy, Clone, Debug)]
 pub(crate) struct Reverse;
 
-impl ConstraintGraphDirecton for Reverse {
+impl ConstraintGraphDirection for Reverse {
     fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sub
     }
@@ -73,7 +73,7 @@ impl ConstraintGraphDirecton for Reverse {
     }
 }
 
-impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
+impl<D: ConstraintGraphDirection> ConstraintGraph<D> {
     /// Creates a "dependency graph" where each region constraint `R1:
     /// R2` is treated as an edge `R1 -> R2`. We use this graph to
     /// construct SCCs for region inference but also for error
@@ -133,7 +133,7 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     }
 }
 
-pub(crate) struct Edges<'s, 'tcx, D: ConstraintGraphDirecton> {
+pub(crate) struct Edges<'s, 'tcx, D: ConstraintGraphDirection> {
     graph: &'s ConstraintGraph<D>,
     constraints: &'s OutlivesConstraintSet<'tcx>,
     pointer: Option<OutlivesConstraintIndex>,
@@ -141,7 +141,7 @@ pub(crate) struct Edges<'s, 'tcx, D: ConstraintGraphDirecton> {
     static_region: RegionVid,
 }
 
-impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirection> Iterator for Edges<'s, 'tcx, D> {
     type Item = OutlivesConstraint<'tcx>;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -174,13 +174,13 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
 /// This struct brings together a constraint set and a (normal, not
 /// reverse) constraint graph. It implements the graph traits and is
 /// usd for doing the SCC computation.
-pub(crate) struct RegionGraph<'s, 'tcx, D: ConstraintGraphDirecton> {
+pub(crate) struct RegionGraph<'s, 'tcx, D: ConstraintGraphDirection> {
     set: &'s OutlivesConstraintSet<'tcx>,
     constraint_graph: &'s ConstraintGraph<D>,
     static_region: RegionVid,
 }
 
-impl<'s, 'tcx, D: ConstraintGraphDirecton> RegionGraph<'s, 'tcx, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirection> RegionGraph<'s, 'tcx, D> {
     /// Creates a "dependency graph" where each region constraint `R1:
     /// R2` is treated as an edge `R1 -> R2`. We use this graph to
     /// construct SCCs for region inference but also for error
@@ -202,11 +202,11 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> RegionGraph<'s, 'tcx, D> {
     }
 }
 
-pub(crate) struct Successors<'s, 'tcx, D: ConstraintGraphDirecton> {
+pub(crate) struct Successors<'s, 'tcx, D: ConstraintGraphDirection> {
     edges: Edges<'s, 'tcx, D>,
 }
 
-impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Successors<'s, 'tcx, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirection> Iterator for Successors<'s, 'tcx, D> {
     type Item = RegionVid;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -214,23 +214,25 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Successors<'s, 'tcx, D>
     }
 }
 
-impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::DirectedGraph for RegionGraph<'s, 'tcx, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirection> graph::DirectedGraph for RegionGraph<'s, 'tcx, D> {
     type Node = RegionVid;
 }
 
-impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, 'tcx, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirection> graph::WithNumNodes for RegionGraph<'s, 'tcx, D> {
     fn num_nodes(&self) -> usize {
         self.constraint_graph.first_constraints.len()
     }
 }
 
-impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, 'tcx, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirection> graph::WithSuccessors for RegionGraph<'s, 'tcx, D> {
     fn successors(&self, node: Self::Node) -> <Self as graph::GraphSuccessors<'_>>::Iter {
         self.outgoing_regions(node)
     }
 }
 
-impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'_> for RegionGraph<'s, 'tcx, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirection> graph::GraphSuccessors<'_>
+    for RegionGraph<'s, 'tcx, D>
+{
     type Item = RegionVid;
     type Iter = Successors<'s, 'tcx, D>;
 }
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 2cbd2e3bc0d..94939c7e4cd 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -11,9 +11,7 @@ use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill}
 use rustc_mir_dataflow::{Analysis, Direction, Results};
 use std::fmt;
 
-use crate::{
-    places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid,
-};
+use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
 
 /// A tuple with named fields that can hold either the results or the transient state of the
 /// dataflow analyses used by the borrow checker.
@@ -242,7 +240,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
     ) -> Self {
         let mut prec = OutOfScopePrecomputer::new(body, nonlexical_regioncx);
         for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
-            let borrow_region = borrow_data.region.to_region_vid();
+            let borrow_region = borrow_data.region;
             let location = borrow_data.reserve_location;
 
             prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index e2d04324f3b..2495613fea1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -6,7 +6,6 @@ use std::rc::Rc;
 
 use crate::{
     def_use::{self, DefUse},
-    nll::ToRegionVid,
     region_infer::{Cause, RegionInferenceContext},
 };
 use rustc_data_structures::fx::FxIndexSet;
@@ -117,7 +116,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> {
 
         let mut found_it = false;
         self.tcx.for_each_free_region(&local_ty, |r| {
-            if r.to_region_vid() == self.region_vid {
+            if r.as_var() == self.region_vid {
                 found_it = true;
             }
         });
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index cc5a1f5ab12..f69c4829ae2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -10,7 +10,7 @@ use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
-use crate::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
+use crate::{universal_regions::DefiningTy, MirBorrowckCtxt};
 
 /// A name for a particular region used in emitting diagnostics. This name could be a generated
 /// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
@@ -497,7 +497,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 //     &
                 //     - let's call the lifetime of this reference `'1`
                 (ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => {
-                    if region.to_region_vid() == needle_fr {
+                    if region.as_var() == needle_fr {
                         // Just grab the first character, the `&`.
                         let source_map = self.infcx.tcx.sess.source_map();
                         let ampersand_span = source_map.start_point(hir_ty.span);
@@ -598,7 +598,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         for (kind, hir_arg) in iter::zip(substs, args.args) {
             match (kind.unpack(), hir_arg) {
                 (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
-                    if r.to_region_vid() == needle_fr {
+                    if r.as_var() == needle_fr {
                         return Some(lt);
                     }
                 }
@@ -666,7 +666,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
         let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
         debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
-        if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) {
+        if !tcx.any_free_region_meets(&return_ty, |r| r.as_var() == fr) {
             return None;
         }
 
@@ -803,7 +803,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
         let tcx = self.infcx.tcx;
 
-        if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) {
+        if !tcx.any_free_region_meets(&yield_ty, |r| r.as_var() == fr) {
             return None;
         }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 80b2787ce0c..376415e3d32 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -1,8 +1,8 @@
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
+use crate::region_infer::RegionInferenceContext;
 use crate::Upvar;
-use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext};
 use rustc_index::vec::{Idx, IndexSlice};
 use rustc_middle::mir::{Body, Local};
 use rustc_middle::ty::{RegionVid, TyCtxt};
@@ -46,7 +46,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| {
                 debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}");
                 tcx.any_free_region_meets(&upvar_ty, |r| {
-                    let r = r.to_region_vid();
+                    let r = r.as_var();
                     debug!("get_upvar_index_for_region: r={r:?} fr={fr:?}");
                     r == fr
                 })
@@ -96,7 +96,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position(
                 |arg_ty| {
                     debug!("get_argument_index_for_region: arg_ty = {arg_ty:?}");
-                    tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr)
+                    tcx.any_free_region_meets(arg_ty, |r| r.as_var() == fr)
                 },
             )?;
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 3d876155fc9..a4b285a34fa 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -94,7 +94,7 @@ pub mod consumers;
 
 use borrow_set::{BorrowData, BorrowSet};
 use dataflow::{BorrowIndex, BorrowckFlowState as Flows, BorrowckResults, Borrows};
-use nll::{PoloniusOutput, ToRegionVid};
+use nll::PoloniusOutput;
 use place_ext::PlaceExt;
 use places_conflict::{places_conflict, PlaceConflictBias};
 use region_infer::RegionInferenceContext;
@@ -507,9 +507,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
         F: Fn() -> RegionCtxt,
     {
         let next_region = self.infcx.next_region_var(origin);
-        let vid = next_region
-            .as_var()
-            .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region));
+        let vid = next_region.as_var();
 
         if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() {
             debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin);
@@ -531,9 +529,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
         F: Fn() -> RegionCtxt,
     {
         let next_region = self.infcx.next_nll_region_var(origin.clone());
-        let vid = next_region
-            .as_var()
-            .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region));
+        let vid = next_region.as_var();
 
         if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() {
             debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin);
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 06ecbdb1707..59a3ab3189d 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::{
     BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
     Promoted,
 };
-use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid, TyCtxt};
+use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
 use rustc_span::symbol::sym;
 use std::env;
 use std::io;
@@ -444,27 +444,6 @@ fn for_each_region_constraint<'tcx>(
     Ok(())
 }
 
-/// Right now, we piggy back on the `ReVar` to store our NLL inference
-/// regions. These are indexed with `RegionVid`. This method will
-/// assert that the region is a `ReVar` and extract its internal index.
-/// This is reasonable because in our MIR we replace all universal regions
-/// with inference variables.
-pub trait ToRegionVid {
-    fn to_region_vid(self) -> RegionVid;
-}
-
-impl<'tcx> ToRegionVid for Region<'tcx> {
-    fn to_region_vid(self) -> RegionVid {
-        if let ty::ReVar(vid) = *self { vid } else { bug!("region is not an ReVar: {:?}", self) }
-    }
-}
-
-impl ToRegionVid for RegionVid {
-    fn to_region_vid(self) -> RegionVid {
-        self
-    }
-}
-
 pub(crate) trait ConstraintDescription {
     fn description(&self) -> &'static str;
 }
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index f67af4584a4..729f3dbff3b 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -27,7 +27,7 @@ use crate::{
     },
     diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo},
     member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
-    nll::{PoloniusOutput, ToRegionVid},
+    nll::PoloniusOutput,
     region_infer::reverse_sccs::ReverseSccGraph,
     region_infer::values::{
         LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
@@ -593,14 +593,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Returns `true` if the region `r` contains the point `p`.
     ///
     /// Panics if called before `solve()` executes,
-    pub(crate) fn region_contains(&self, r: impl ToRegionVid, p: impl ToElementIndex) -> bool {
-        let scc = self.constraint_sccs.scc(r.to_region_vid());
+    pub(crate) fn region_contains(&self, r: RegionVid, p: impl ToElementIndex) -> bool {
+        let scc = self.constraint_sccs.scc(r);
         self.scc_values.contains(scc, p)
     }
 
     /// Returns access to the value of `r` for debugging purposes.
     pub(crate) fn region_value_str(&self, r: RegionVid) -> String {
-        let scc = self.constraint_sccs.scc(r.to_region_vid());
+        let scc = self.constraint_sccs.scc(r);
         self.scc_values.region_value_str(scc)
     }
 
@@ -608,24 +608,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &'a self,
         r: RegionVid,
     ) -> impl Iterator<Item = ty::PlaceholderRegion> + 'a {
-        let scc = self.constraint_sccs.scc(r.to_region_vid());
+        let scc = self.constraint_sccs.scc(r);
         self.scc_values.placeholders_contained_in(scc)
     }
 
     /// Returns access to the value of `r` for debugging purposes.
     pub(crate) fn region_universe(&self, r: RegionVid) -> ty::UniverseIndex {
-        let scc = self.constraint_sccs.scc(r.to_region_vid());
+        let scc = self.constraint_sccs.scc(r);
         self.scc_universes[scc]
     }
 
     /// Once region solving has completed, this function will return
     /// the member constraints that were applied to the value of a given
     /// region `r`. See `AppliedMemberConstraint`.
-    pub(crate) fn applied_member_constraints(
-        &self,
-        r: impl ToRegionVid,
-    ) -> &[AppliedMemberConstraint] {
-        let scc = self.constraint_sccs.scc(r.to_region_vid());
+    pub(crate) fn applied_member_constraints(&self, r: RegionVid) -> &[AppliedMemberConstraint] {
+        let scc = self.constraint_sccs.scc(r);
         binary_search_util::binary_search_slice(
             &self.member_constraints_applied,
             |applied| applied.member_region_scc,
@@ -1133,7 +1130,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             let r_vid = self.to_region_vid(r);
             let r_scc = self.constraint_sccs.scc(r_vid);
 
-            // The challenge if this. We have some region variable `r`
+            // The challenge is this. We have some region variable `r`
             // whose value is a set of CFG points and universal
             // regions. We want to find if that set is *equivalent* to
             // any of the named regions found in the closure.
@@ -2234,7 +2231,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         r: RegionVid,
         body: &Body<'_>,
     ) -> Option<Location> {
-        let scc = self.constraint_sccs.scc(r.to_region_vid());
+        let scc = self.constraint_sccs.scc(r);
         let locations = self.scc_values.locations_outlived_by(scc);
         for location in locations {
             let bb = &body[location.block];
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 0fbf01dbe44..94ce29dfe51 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -20,31 +20,13 @@ pub fn renumber_mir<'tcx>(
 ) {
     debug!(?body.arg_count);
 
-    let mut visitor = NllVisitor { infcx };
+    let mut renumberer = RegionRenumberer { infcx };
 
     for body in promoted.iter_mut() {
-        visitor.visit_body(body);
+        renumberer.visit_body(body);
     }
 
-    visitor.visit_body(body);
-}
-
-/// Replaces all regions appearing in `value` with fresh inference
-/// variables.
-#[instrument(skip(infcx, get_ctxt_fn), level = "debug")]
-pub(crate) fn renumber_regions<'tcx, T, F>(
-    infcx: &BorrowckInferCtxt<'_, 'tcx>,
-    value: T,
-    get_ctxt_fn: F,
-) -> T
-where
-    T: TypeFoldable<TyCtxt<'tcx>>,
-    F: Fn() -> RegionCtxt,
-{
-    infcx.tcx.fold_regions(value, |_region, _depth| {
-        let origin = NllRegionVariableOrigin::Existential { from_forall: false };
-        infcx.next_nll_region_var(origin, || get_ctxt_fn())
-    })
+    renumberer.visit_body(body);
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
@@ -69,12 +51,10 @@ impl RegionCtxt {
     /// Used to determine the representative of a component in the strongly connected
     /// constraint graph
     pub(crate) fn preference_value(self) -> usize {
-        let _anon = Symbol::intern("anon");
-
         match self {
             RegionCtxt::Unknown => 1,
             RegionCtxt::Existential(None) => 2,
-            RegionCtxt::Existential(Some(_anon)) | RegionCtxt::Free(_anon) => 2,
+            RegionCtxt::Existential(Some(_)) | RegionCtxt::Free(_) => 2,
             RegionCtxt::Location(_) => 3,
             RegionCtxt::TyContext(_) => 4,
             _ => 5,
@@ -82,21 +62,26 @@ impl RegionCtxt {
     }
 }
 
-struct NllVisitor<'a, 'tcx> {
+struct RegionRenumberer<'a, 'tcx> {
     infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
 }
 
-impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
+impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
+    /// Replaces all regions appearing in `value` with fresh inference
+    /// variables.
     fn renumber_regions<T, F>(&mut self, value: T, region_ctxt_fn: F) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
         F: Fn() -> RegionCtxt,
     {
-        renumber_regions(self.infcx, value, region_ctxt_fn)
+        let origin = NllRegionVariableOrigin::Existential { from_forall: false };
+        self.infcx.tcx.fold_regions(value, |_region, _depth| {
+            self.infcx.next_nll_region_var(origin, || region_ctxt_fn())
+        })
     }
 }
 
-impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
+impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
@@ -124,9 +109,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _location: Location) {
+    fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
         let literal = constant.literal;
-        constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(_location));
+        constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(location));
         debug!("constant: {:#?}", constant);
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index a9356135006..71eae7b27d1 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -12,7 +12,6 @@ use rustc_span::{Span, DUMMY_SP};
 
 use crate::{
     constraints::OutlivesConstraint,
-    nll::ToRegionVid,
     region_infer::TypeTest,
     type_check::{Locations, MirTypeckRegionConstraints},
     universal_regions::UniversalRegions,
@@ -198,7 +197,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
 
     fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
         if let ty::RePlaceholder(placeholder) = *r {
-            self.constraints.placeholder_region(self.infcx, placeholder).to_region_vid()
+            self.constraints.placeholder_region(self.infcx, placeholder).as_var()
         } else {
             self.universal_regions.to_region_vid(r)
         }
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index a411aec518e..f1ad0ca55cc 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -11,7 +11,6 @@ use crate::{
     constraints::OutlivesConstraintSet,
     facts::{AllFacts, AllFactsExt},
     location::LocationTable,
-    nll::ToRegionVid,
     region_infer::values::RegionValueElements,
     universal_regions::UniversalRegions,
 };
@@ -80,9 +79,7 @@ fn compute_relevant_live_locals<'tcx>(
 ) -> (Vec<Local>, Vec<Local>) {
     let (boring_locals, relevant_live_locals): (Vec<_>, Vec<_>) =
         body.local_decls.iter_enumerated().partition_map(|(local, local_decl)| {
-            if tcx.all_free_regions_meet(&local_decl.ty, |r| {
-                free_regions.contains(&r.to_region_vid())
-            }) {
+            if tcx.all_free_regions_meet(&local_decl.ty, |r| free_regions.contains(&r.as_var())) {
                 Either::Left(local)
             } else {
                 Either::Right(local)
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 624a4a00c31..375eca1b29d 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -35,6 +35,7 @@ use rustc_middle::ty::{
     OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
 };
 use rustc_span::def_id::CRATE_DEF_ID;
+use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
 use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
@@ -55,7 +56,6 @@ use crate::{
     facts::AllFacts,
     location::LocationTable,
     member_constraints::MemberConstraintSet,
-    nll::ToRegionVid,
     path_utils,
     region_infer::values::{
         LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
@@ -1338,18 +1338,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 };
                 let (sig, map) = tcx.replace_late_bound_regions(sig, |br| {
                     use crate::renumber::{BoundRegionInfo, RegionCtxt};
-                    use rustc_span::Symbol;
 
                     let region_ctxt_fn = || {
                         let reg_info = match br.kind {
                             ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
-                            ty::BoundRegionKind::BrAnon(..) => {
-                                BoundRegionInfo::Name(Symbol::intern("anon"))
-                            }
+                            ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(sym::anon),
                             ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
-                            ty::BoundRegionKind::BrEnv => {
-                                BoundRegionInfo::Name(Symbol::intern("env"))
-                            }
+                            ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env),
                         };
 
                         RegionCtxt::LateBound(reg_info)
@@ -2423,7 +2418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if let Some(all_facts) = all_facts {
             let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
             if let Some(borrow_index) = borrow_set.get_index_of(&location) {
-                let region_vid = borrow_region.to_region_vid();
+                let region_vid = borrow_region.as_var();
                 all_facts.loan_issued_at.push((
                     region_vid,
                     borrow_index,
@@ -2469,8 +2464,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     match base_ty.kind() {
                         ty::Ref(ref_region, _, mutbl) => {
                             constraints.outlives_constraints.push(OutlivesConstraint {
-                                sup: ref_region.to_region_vid(),
-                                sub: borrow_region.to_region_vid(),
+                                sup: ref_region.as_var(),
+                                sub: borrow_region.as_var(),
                                 locations: location.to_locations(),
                                 span: location.to_locations().span(body),
                                 category,
@@ -2600,7 +2595,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 self.implicit_region_bound,
                 self.param_env,
                 location.to_locations(),
-                DUMMY_SP,                   // irrelevant; will be overrided.
+                DUMMY_SP,                   // irrelevant; will be overridden.
                 ConstraintCategory::Boring, // same as above.
                 &mut self.borrowck_context.constraints,
             )
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 83429f2ddef..7e6d17ec343 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -4,6 +4,7 @@ use rustc_infer::traits::PredicateObligations;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{self, Ty};
+use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
 use rustc_trait_selection::traits::query::Fallible;
 
@@ -125,18 +126,14 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
 
         let reg_info = match placeholder.bound.kind {
             ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
-            ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(Symbol::intern("anon")),
+            ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(sym::anon),
             ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
-            ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(Symbol::intern("env")),
+            ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env),
         };
 
-        let reg_var =
-            reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg));
-
         if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() {
             let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
-            debug!(?reg_var);
-            var_to_origin.insert(reg_var, RegionCtxt::Placeholder(reg_info));
+            var_to_origin.insert(reg.as_var(), RegionCtxt::Placeholder(reg_info));
         }
 
         reg
@@ -149,12 +146,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
             universe,
         );
 
-        let reg_var =
-            reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg));
-
         if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() {
             let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
-            var_to_origin.insert(reg_var, RegionCtxt::Existential(None));
+            var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None));
         }
 
         reg
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 68c86051364..70fddb1057c 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -24,10 +24,10 @@ use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_span::symbol::{kw, sym};
 use rustc_span::Symbol;
 use std::iter;
 
-use crate::nll::ToRegionVid;
 use crate::renumber::{BoundRegionInfo, RegionCtxt};
 use crate::BorrowckInferCtxt;
 
@@ -404,10 +404,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());
 
         // Create the "global" region that is always free in all contexts: 'static.
-        let fr_static = self
-            .infcx
-            .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("static")))
-            .to_region_vid();
+        let fr_static =
+            self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).as_var();
 
         // We've now added all the global regions. The next ones we
         // add will be external.
@@ -440,18 +438,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     debug!(?r);
                     if !indices.indices.contains_key(&r) {
                         let region_vid = {
-                            let name = match r.get_name() {
-                                Some(name) => name,
-                                _ => Symbol::intern("anon"),
-                            };
-
+                            let name = r.get_name_or_anon();
                             self.infcx.next_nll_region_var(FR, || {
                                 RegionCtxt::LateBound(BoundRegionInfo::Name(name))
                             })
                         };
 
                         debug!(?region_vid);
-                        indices.insert_late_bound_region(r, region_vid.to_region_vid());
+                        indices.insert_late_bound_region(r, region_vid.as_var());
                     }
                 },
             );
@@ -478,18 +472,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             debug!(?r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = {
-                    let name = match r.get_name() {
-                        Some(name) => name,
-                        _ => Symbol::intern("anon"),
-                    };
-
+                    let name = r.get_name_or_anon();
                     self.infcx.next_nll_region_var(FR, || {
                         RegionCtxt::LateBound(BoundRegionInfo::Name(name))
                     })
                 };
 
                 debug!(?region_vid);
-                indices.insert_late_bound_region(r, region_vid.to_region_vid());
+                indices.insert_late_bound_region(r, region_vid.as_var());
             }
         });
 
@@ -508,7 +498,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                 let reg_vid = self
                     .infcx
                     .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
-                    .to_region_vid();
+                    .as_var();
 
                 let region = self.infcx.tcx.mk_re_var(reg_vid);
                 let va_list_ty =
@@ -523,7 +513,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         let fr_fn_body = self
             .infcx
             .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body")))
-            .to_region_vid();
+            .as_var();
 
         let num_universals = self.infcx.num_region_vars();
 
@@ -644,7 +634,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 
         let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
         let subst_mapping =
-            iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid()));
+            iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.as_var()));
 
         UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static }
     }
@@ -768,15 +758,10 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         self.infcx.tcx.fold_regions(value, |region, _depth| {
-            let name = match region.get_name() {
-                Some(name) => name,
-                _ => Symbol::intern("anon"),
-            };
+            let name = region.get_name_or_anon();
             debug!(?region, ?name);
 
-            let reg_var = self.next_nll_region_var(origin, || RegionCtxt::Free(name));
-
-            reg_var
+            self.next_nll_region_var(origin, || RegionCtxt::Free(name))
         })
     }
 
@@ -797,13 +782,13 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
             let region_vid = {
                 let name = match br.kind.get_name() {
                     Some(name) => name,
-                    _ => Symbol::intern("anon"),
+                    _ => sym::anon,
                 };
 
                 self.next_nll_region_var(origin, || RegionCtxt::Bound(BoundRegionInfo::Name(name)))
             };
 
-            indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid());
+            indices.insert_late_bound_region(liberated_region, region_vid.as_var());
             debug!(?liberated_region, ?region_vid);
             region_vid
         });
@@ -829,18 +814,14 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
             debug!(?r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = {
-                    let name = match r.get_name() {
-                        Some(name) => name,
-                        _ => Symbol::intern("anon"),
-                    };
-
+                    let name = r.get_name_or_anon();
                     self.next_nll_region_var(FR, || {
                         RegionCtxt::LateBound(BoundRegionInfo::Name(name))
                     })
                 };
 
                 debug!(?region_vid);
-                indices.insert_late_bound_region(r, region_vid.to_region_vid());
+                indices.insert_late_bound_region(r, region_vid.as_var());
             }
         });
     }
@@ -855,17 +836,13 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
             debug!(?r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = {
-                    let name = match r.get_name() {
-                        Some(name) => name,
-                        _ => Symbol::intern("anon"),
-                    };
-
+                    let name = r.get_name_or_anon();
                     self.next_nll_region_var(FR, || {
                         RegionCtxt::LateBound(BoundRegionInfo::Name(name))
                     })
                 };
 
-                indices.insert_late_bound_region(r, region_vid.to_region_vid());
+                indices.insert_late_bound_region(r, region_vid.as_var());
             }
         });
     }
@@ -883,7 +860,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     }
 
     /// Converts `r` into a local inference variable: `r` can either
-    /// by a `ReVar` (i.e., already a reference to an inference
+    /// be a `ReVar` (i.e., already a reference to an inference
     /// variable) or it can be `'static` or some early-bound
     /// region. This is useful when taking the results from
     /// type-checking and trait-matching, which may sometimes
@@ -892,7 +869,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     /// fully initialized.
     pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
         if let ty::ReVar(..) = *r {
-            r.to_region_vid()
+            r.as_var()
         } else if r.is_error() {
             // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
             // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 435a07d8ce7..f0fc61d7c4f 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -42,7 +42,7 @@ struct MacroInput {
     fmtstr: P<Expr>,
     args: FormatArguments,
     /// Whether the first argument was a string literal or a result from eager macro expansion.
-    /// If it's not a string literal, we disallow implicit arugment capturing.
+    /// If it's not a string literal, we disallow implicit argument capturing.
     ///
     /// This does not correspond to whether we can treat spans to the literal normally, as the whole
     /// invocation might be the result of another macro expansion, in which case this flag may still be true.
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index a76ed4ee6ce..79d8be2484b 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -118,34 +118,22 @@ pub fn expand_test_or_bench(
             }
         }
         other => {
-            cx.struct_span_err(
-                other.span(),
-                "`#[test]` attribute is only allowed on non associated functions",
-            )
-            .emit();
+            not_testable_error(cx, attr_sp, None);
             return vec![other];
         }
     };
 
-    // Note: non-associated fn items are already handled by `expand_test_or_bench`
     let ast::ItemKind::Fn(fn_) = &item.kind else {
-        let diag = &cx.sess.parse_sess.span_diagnostic;
-        let msg = "the `#[test]` attribute may only be used on a non-associated function";
-        let mut err = match item.kind {
-            // These were a warning before #92959 and need to continue being that to avoid breaking
-            // stable user code (#94508).
-            ast::ItemKind::MacCall(_) => diag.struct_span_warn(attr_sp, msg),
-            // `.forget_guarantee()` needed to get these two arms to match types. Because of how
-            // locally close the `.emit()` call is I'm comfortable with it, but if it can be
-            // reworked in the future to not need it, it'd be nice.
-            _ => diag.struct_span_err(attr_sp, msg).forget_guarantee(),
+        not_testable_error(cx, attr_sp, Some(&item));
+        return if is_stmt {
+            vec![Annotatable::Stmt(P(ast::Stmt {
+                id: ast::DUMMY_NODE_ID,
+                span: item.span,
+                kind: ast::StmtKind::Item(item),
+            }))]
+        } else {
+            vec![Annotatable::Item(item)]
         };
-        err.span_label(attr_sp, "the `#[test]` macro causes a function to be run on a test and has no effect on non-functions")
-            .span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr()))
-            .span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", "#[cfg(test)]", Applicability::MaybeIncorrect)
-            .emit();
-
-        return vec![Annotatable::Item(item)];
     };
 
     // has_*_signature will report any errors in the type so compilation
@@ -398,6 +386,36 @@ pub fn expand_test_or_bench(
     }
 }
 
+fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) {
+    let diag = &cx.sess.parse_sess.span_diagnostic;
+    let msg = "the `#[test]` attribute may only be used on a non-associated function";
+    let mut err = match item.map(|i| &i.kind) {
+        // These were a warning before #92959 and need to continue being that to avoid breaking
+        // stable user code (#94508).
+        Some(ast::ItemKind::MacCall(_)) => diag.struct_span_warn(attr_sp, msg),
+        // `.forget_guarantee()` needed to get these two arms to match types. Because of how
+        // locally close the `.emit()` call is I'm comfortable with it, but if it can be
+        // reworked in the future to not need it, it'd be nice.
+        _ => diag.struct_span_err(attr_sp, msg).forget_guarantee(),
+    };
+    if let Some(item) = item {
+        err.span_label(
+            item.span,
+            format!(
+                "expected a non-associated function, found {} {}",
+                item.kind.article(),
+                item.kind.descr()
+            ),
+        );
+    }
+    err.span_label(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions")
+        .span_suggestion(attr_sp,
+            "replace with conditional compilation to make the item only exist when tests are being run",
+            "#[cfg(test)]",
+            Applicability::MaybeIncorrect)
+        .emit();
+}
+
 fn get_location_info(cx: &ExtCtxt<'_>, item: &ast::Item) -> (Symbol, usize, usize, usize, usize) {
     let span = item.ident.span;
     let (source_file, lo_line, lo_col, hi_line, hi_col) =
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 41e9d61a10e..65de02b3567 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -593,6 +593,9 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
             InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
             InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
+            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
+            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
+            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
             InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
             InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
@@ -664,6 +667,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
         InlineAsmRegClass::Avr(_) => unimplemented!(),
         InlineAsmRegClass::Bpf(_) => unimplemented!(),
         InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
+        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
+        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
+        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(),
         InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(),
         InlineAsmRegClass::Msp430(_) => unimplemented!(),
@@ -849,6 +855,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
         InlineAsmRegClass::Avr(_) => None,
         InlineAsmRegClass::S390x(_) => None,
         InlineAsmRegClass::Msp430(_) => None,
+        InlineAsmRegClass::M68k(_) => None,
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index e7668341eb6..1a3865360a3 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -244,6 +244,9 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 InlineAsmArch::Msp430 => {
                     constraints.push("~{sr}".to_string());
                 }
+                InlineAsmArch::M68k => {
+                    constraints.push("~{ccr}".to_string());
+                }
             }
         }
         if !options.contains(InlineAsmOptions::NOMEM) {
@@ -671,6 +674,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
             InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
+            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
+            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
+            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
             InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
                 bug!("LLVM backend does not support SPIR-V")
             }
@@ -768,6 +774,7 @@ fn modifier_to_llvm(
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
+        InlineAsmRegClass::M68k(_) => None,
         InlineAsmRegClass::Err => unreachable!(),
     }
 }
@@ -839,6 +846,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
         InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
         InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
+        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
+        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
+        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(),
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 8fe5f8d50ab..243be0e1f70 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -141,7 +141,7 @@ codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but
 
 codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
 
-codegen_ssa_unsufficient_vs_code_product = VS Code is a different product, and is not sufficient.
+codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
 
 codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
     .note = {$output}
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 7a5fa5a370c..02e21e74fad 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -923,7 +923,7 @@ fn link_natively<'a>(
             if sess.target.is_like_msvc && linker_not_found {
                 sess.emit_note(errors::MsvcMissingLinker);
                 sess.emit_note(errors::CheckInstalledVisualStudio);
-                sess.emit_note(errors::UnsufficientVSCodeProduct);
+                sess.emit_note(errors::InsufficientVSCodeProduct);
             }
             sess.abort_if_errors();
         }
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 6dea7496fc3..66e7e314f79 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -405,8 +405,8 @@ pub struct MsvcMissingLinker;
 pub struct CheckInstalledVisualStudio;
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa_unsufficient_vs_code_product)]
-pub struct UnsufficientVSCodeProduct;
+#[diag(codegen_ssa_insufficient_vs_code_product)]
+pub struct InsufficientVSCodeProduct;
 
 #[derive(Diagnostic)]
 #[diag(codegen_ssa_processing_dymutil_failed)]
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 280f0207116..d049bafb821 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -442,11 +442,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let (var_ty, var_kind) = match var.value {
                     mir::VarDebugInfoContents::Place(place) => {
                         let var_ty = self.monomorphized_place_ty(place.as_ref());
-                        let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
+                        let var_kind = if let Some(arg_index) = var.argument_index
                             && place.projection.is_empty()
-                            && var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE
                         {
-                            let arg_index = place.local.index() - 1;
+                            let arg_index = arg_index as usize;
                             if target_is_msvc {
                                 // ScalarPair parameters are spilled to the stack so they need to
                                 // be marked as a `LocalVariable` for MSVC debuggers to visualize
@@ -455,13 +454,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
                                     VariableKind::LocalVariable
                                 } else {
-                                    VariableKind::ArgumentVariable(arg_index + 1)
+                                    VariableKind::ArgumentVariable(arg_index)
                                 }
                             } else {
                                 // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
                                 // offset in closures to account for the hidden environment?
-                                // Also, is this `+ 1` needed at all?
-                                VariableKind::ArgumentVariable(arg_index + 1)
+                                VariableKind::ArgumentVariable(arg_index)
                             }
                         } else {
                             VariableKind::LocalVariable
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 7564ba17b40..4bd6fe19931 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -205,7 +205,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
     let cid = key.value;
     let def_id = cid.instance.def.def_id();
     let is_static = tcx.is_static(def_id);
-    // This is just accessing an already computed constant, so no need to check alginment here.
+    // This is just accessing an already computed constant, so no need to check alignment here.
     let ecx = mk_eval_cx(
         tcx,
         tcx.def_span(key.value.instance.def_id()),
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
index 76c8d0a975a..3701eb93ec8 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -77,7 +77,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         line: u32,
         col: u32,
     ) -> MPlaceTy<'tcx, M::Provenance> {
-        let loc_details = &self.tcx.sess.opts.unstable_opts.location_detail;
+        let loc_details = self.tcx.sess.opts.unstable_opts.location_detail;
         // This can fail if rustc runs out of memory right here. Trying to emit an error would be
         // pointless, since that would require allocating more memory than these short strings.
         let file = if loc_details.file {
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 0f56fda18f5..d4bed97380b 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -679,13 +679,21 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             // Unlike `mem::transmute`, a MIR `Transmute` is well-formed
                             // for any two `Sized` types, just potentially UB to run.
 
-                            if !op_ty.is_sized(self.tcx, self.param_env) {
+                            if !self
+                                .tcx
+                                .normalize_erasing_regions(self.param_env, op_ty)
+                                .is_sized(self.tcx, self.param_env)
+                            {
                                 self.fail(
                                     location,
                                     format!("Cannot transmute from non-`Sized` type {op_ty:?}"),
                                 );
                             }
-                            if !target_type.is_sized(self.tcx, self.param_env) {
+                            if !self
+                                .tcx
+                                .normalize_erasing_regions(self.param_env, *target_type)
+                                .is_sized(self.tcx, self.param_env)
+                            {
                                 self.fail(
                                     location,
                                     format!("Cannot transmute to non-`Sized` type {target_type:?}"),
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 24b6b5cfb1f..2102f09c56a 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -33,6 +33,7 @@ tempfile = "3.2"
 thin-vec = "0.2.12"
 tracing = "0.1"
 elsa = "=1.7.1"
+itertools = "0.10.1"
 
 [dependencies.parking_lot]
 version = "0.11"
diff --git a/compiler/rustc_data_structures/src/sso/either_iter.rs b/compiler/rustc_data_structures/src/sso/either_iter.rs
deleted file mode 100644
index bca6c0955b9..00000000000
--- a/compiler/rustc_data_structures/src/sso/either_iter.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-use std::fmt;
-use std::iter::FusedIterator;
-
-/// Iterator which may contain instance of
-/// one of two specific implementations.
-///
-/// Note: For most methods providing custom
-///       implementation may marginally
-///       improve performance by avoiding
-///       doing Left/Right match on every step
-///       and doing it only once instead.
-#[derive(Clone)]
-pub enum EitherIter<L, R> {
-    Left(L),
-    Right(R),
-}
-
-impl<L, R> Iterator for EitherIter<L, R>
-where
-    L: Iterator,
-    R: Iterator<Item = L::Item>,
-{
-    type Item = L::Item;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match self {
-            EitherIter::Left(l) => l.next(),
-            EitherIter::Right(r) => r.next(),
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        match self {
-            EitherIter::Left(l) => l.size_hint(),
-            EitherIter::Right(r) => r.size_hint(),
-        }
-    }
-}
-
-impl<L, R> ExactSizeIterator for EitherIter<L, R>
-where
-    L: ExactSizeIterator,
-    R: ExactSizeIterator,
-    EitherIter<L, R>: Iterator,
-{
-    fn len(&self) -> usize {
-        match self {
-            EitherIter::Left(l) => l.len(),
-            EitherIter::Right(r) => r.len(),
-        }
-    }
-}
-
-impl<L, R> FusedIterator for EitherIter<L, R>
-where
-    L: FusedIterator,
-    R: FusedIterator,
-    EitherIter<L, R>: Iterator,
-{
-}
-
-impl<L, R> fmt::Debug for EitherIter<L, R>
-where
-    L: fmt::Debug,
-    R: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            EitherIter::Left(l) => l.fmt(f),
-            EitherIter::Right(r) => r.fmt(f),
-        }
-    }
-}
diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs
index 7cdac581977..89b8c852649 100644
--- a/compiler/rustc_data_structures/src/sso/map.rs
+++ b/compiler/rustc_data_structures/src/sso/map.rs
@@ -1,24 +1,24 @@
-use super::either_iter::EitherIter;
 use crate::fx::FxHashMap;
 use arrayvec::ArrayVec;
+use itertools::Either;
 use std::fmt;
 use std::hash::Hash;
 use std::ops::Index;
 
-// For pointer-sized arguments arrays
-// are faster than set/map for up to 64
-// arguments.
-//
-// On the other hand such a big array
-// hurts cache performance, makes passing
-// sso structures around very expensive.
-//
-// Biggest performance benefit is gained
-// for reasonably small arrays that stay
-// small in vast majority of cases.
-//
-// '8' is chosen as a sane default, to be
-// reevaluated later.
+/// For pointer-sized arguments arrays
+/// are faster than set/map for up to 64
+/// arguments.
+///
+/// On the other hand such a big array
+/// hurts cache performance, makes passing
+/// sso structures around very expensive.
+///
+/// Biggest performance benefit is gained
+/// for reasonably small arrays that stay
+/// small in vast majority of cases.
+///
+/// '8' is chosen as a sane default, to be
+/// reevaluated later.
 const SSO_ARRAY_SIZE: usize = 8;
 
 /// Small-storage-optimized implementation of a map.
@@ -138,8 +138,8 @@ impl<K, V> SsoHashMap<K, V> {
     /// The iterator element type is `&'a K`.
     pub fn keys(&self) -> impl Iterator<Item = &'_ K> {
         match self {
-            SsoHashMap::Array(array) => EitherIter::Left(array.iter().map(|(k, _v)| k)),
-            SsoHashMap::Map(map) => EitherIter::Right(map.keys()),
+            SsoHashMap::Array(array) => Either::Left(array.iter().map(|(k, _v)| k)),
+            SsoHashMap::Map(map) => Either::Right(map.keys()),
         }
     }
 
@@ -147,8 +147,8 @@ impl<K, V> SsoHashMap<K, V> {
     /// The iterator element type is `&'a V`.
     pub fn values(&self) -> impl Iterator<Item = &'_ V> {
         match self {
-            SsoHashMap::Array(array) => EitherIter::Left(array.iter().map(|(_k, v)| v)),
-            SsoHashMap::Map(map) => EitherIter::Right(map.values()),
+            SsoHashMap::Array(array) => Either::Left(array.iter().map(|(_k, v)| v)),
+            SsoHashMap::Map(map) => Either::Right(map.values()),
         }
     }
 
@@ -156,8 +156,8 @@ impl<K, V> SsoHashMap<K, V> {
     /// The iterator element type is `&'a mut V`.
     pub fn values_mut(&mut self) -> impl Iterator<Item = &'_ mut V> {
         match self {
-            SsoHashMap::Array(array) => EitherIter::Left(array.iter_mut().map(|(_k, v)| v)),
-            SsoHashMap::Map(map) => EitherIter::Right(map.values_mut()),
+            SsoHashMap::Array(array) => Either::Left(array.iter_mut().map(|(_k, v)| v)),
+            SsoHashMap::Map(map) => Either::Right(map.values_mut()),
         }
     }
 
@@ -165,8 +165,8 @@ impl<K, V> SsoHashMap<K, V> {
     /// allocated memory for reuse.
     pub fn drain(&mut self) -> impl Iterator<Item = (K, V)> + '_ {
         match self {
-            SsoHashMap::Array(array) => EitherIter::Left(array.drain(..)),
-            SsoHashMap::Map(map) => EitherIter::Right(map.drain()),
+            SsoHashMap::Array(array) => Either::Left(array.drain(..)),
+            SsoHashMap::Map(map) => Either::Right(map.drain()),
         }
     }
 }
@@ -406,16 +406,16 @@ where
 }
 
 impl<K, V> IntoIterator for SsoHashMap<K, V> {
-    type IntoIter = EitherIter<
-        <ArrayVec<(K, V), 8> as IntoIterator>::IntoIter,
+    type IntoIter = Either<
+        <ArrayVec<(K, V), SSO_ARRAY_SIZE> as IntoIterator>::IntoIter,
         <FxHashMap<K, V> as IntoIterator>::IntoIter,
     >;
     type Item = <Self::IntoIter as Iterator>::Item;
 
     fn into_iter(self) -> Self::IntoIter {
         match self {
-            SsoHashMap::Array(array) => EitherIter::Left(array.into_iter()),
-            SsoHashMap::Map(map) => EitherIter::Right(map.into_iter()),
+            SsoHashMap::Array(array) => Either::Left(array.into_iter()),
+            SsoHashMap::Map(map) => Either::Right(map.into_iter()),
         }
     }
 }
@@ -435,9 +435,9 @@ fn adapt_array_mut_it<K, V>(pair: &mut (K, V)) -> (&K, &mut V) {
 }
 
 impl<'a, K, V> IntoIterator for &'a SsoHashMap<K, V> {
-    type IntoIter = EitherIter<
+    type IntoIter = Either<
         std::iter::Map<
-            <&'a ArrayVec<(K, V), 8> as IntoIterator>::IntoIter,
+            <&'a ArrayVec<(K, V), SSO_ARRAY_SIZE> as IntoIterator>::IntoIter,
             fn(&'a (K, V)) -> (&'a K, &'a V),
         >,
         <&'a FxHashMap<K, V> as IntoIterator>::IntoIter,
@@ -446,16 +446,16 @@ impl<'a, K, V> IntoIterator for &'a SsoHashMap<K, V> {
 
     fn into_iter(self) -> Self::IntoIter {
         match self {
-            SsoHashMap::Array(array) => EitherIter::Left(array.into_iter().map(adapt_array_ref_it)),
-            SsoHashMap::Map(map) => EitherIter::Right(map.iter()),
+            SsoHashMap::Array(array) => Either::Left(array.into_iter().map(adapt_array_ref_it)),
+            SsoHashMap::Map(map) => Either::Right(map.iter()),
         }
     }
 }
 
 impl<'a, K, V> IntoIterator for &'a mut SsoHashMap<K, V> {
-    type IntoIter = EitherIter<
+    type IntoIter = Either<
         std::iter::Map<
-            <&'a mut ArrayVec<(K, V), 8> as IntoIterator>::IntoIter,
+            <&'a mut ArrayVec<(K, V), SSO_ARRAY_SIZE> as IntoIterator>::IntoIter,
             fn(&'a mut (K, V)) -> (&'a K, &'a mut V),
         >,
         <&'a mut FxHashMap<K, V> as IntoIterator>::IntoIter,
@@ -464,8 +464,8 @@ impl<'a, K, V> IntoIterator for &'a mut SsoHashMap<K, V> {
 
     fn into_iter(self) -> Self::IntoIter {
         match self {
-            SsoHashMap::Array(array) => EitherIter::Left(array.into_iter().map(adapt_array_mut_it)),
-            SsoHashMap::Map(map) => EitherIter::Right(map.iter_mut()),
+            SsoHashMap::Array(array) => Either::Left(array.into_iter().map(adapt_array_mut_it)),
+            SsoHashMap::Map(map) => Either::Right(map.iter_mut()),
         }
     }
 }
diff --git a/compiler/rustc_data_structures/src/sso/mod.rs b/compiler/rustc_data_structures/src/sso/mod.rs
index dd21bc8e696..ef634b9adce 100644
--- a/compiler/rustc_data_structures/src/sso/mod.rs
+++ b/compiler/rustc_data_structures/src/sso/mod.rs
@@ -1,4 +1,3 @@
-mod either_iter;
 mod map;
 mod set;
 
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 730d41ab962..b9f0e756e65 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -5,7 +5,6 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(is_terminal)]
 #![feature(lazy_cell)]
 #![feature(decl_macro)]
 #![recursion_limit = "256"]
@@ -37,7 +36,7 @@ use rustc_metadata::locator;
 use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
 use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
 use rustc_session::cstore::MetadataLoader;
-use rustc_session::getopts;
+use rustc_session::getopts::{self, Matches};
 use rustc_session::lint::{Lint, LintId};
 use rustc_session::{config, Session};
 use rustc_session::{early_error, early_error_no_abort, early_warn};
@@ -956,6 +955,46 @@ Available lint options:
     }
 }
 
+/// Show help for flag categories shared between rustdoc and rustc.
+///
+/// Returns whether a help option was printed.
+pub fn describe_flag_categories(matches: &Matches) -> bool {
+    // Handle the special case of -Wall.
+    let wall = matches.opt_strs("W");
+    if wall.iter().any(|x| *x == "all") {
+        print_wall_help();
+        rustc_errors::FatalError.raise();
+    }
+
+    // Don't handle -W help here, because we might first load plugins.
+    let debug_flags = matches.opt_strs("Z");
+    if debug_flags.iter().any(|x| *x == "help") {
+        describe_debug_flags();
+        return true;
+    }
+
+    let cg_flags = matches.opt_strs("C");
+    if cg_flags.iter().any(|x| *x == "help") {
+        describe_codegen_flags();
+        return true;
+    }
+
+    if cg_flags.iter().any(|x| *x == "no-stack-check") {
+        early_warn(
+            ErrorOutputType::default(),
+            "the --no-stack-check flag is deprecated and does nothing",
+        );
+    }
+
+    if cg_flags.iter().any(|x| *x == "passes=list") {
+        let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+        get_codegen_backend(&None, backend_name).print_passes();
+        return true;
+    }
+
+    false
+}
+
 fn describe_debug_flags() {
     println!("\nAvailable options:\n");
     print_flag_list("-Z", config::Z_OPTIONS);
@@ -966,7 +1005,7 @@ fn describe_codegen_flags() {
     print_flag_list("-C", config::CG_OPTIONS);
 }
 
-pub fn print_flag_list<T>(
+fn print_flag_list<T>(
     cmdline_opt: &str,
     flag_list: &[(&'static str, T, &'static str, &'static str)],
 ) {
@@ -1059,37 +1098,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
         return None;
     }
 
-    // Handle the special case of -Wall.
-    let wall = matches.opt_strs("W");
-    if wall.iter().any(|x| *x == "all") {
-        print_wall_help();
-        rustc_errors::FatalError.raise();
-    }
-
-    // Don't handle -W help here, because we might first load plugins.
-    let debug_flags = matches.opt_strs("Z");
-    if debug_flags.iter().any(|x| *x == "help") {
-        describe_debug_flags();
-        return None;
-    }
-
-    let cg_flags = matches.opt_strs("C");
-
-    if cg_flags.iter().any(|x| *x == "help") {
-        describe_codegen_flags();
-        return None;
-    }
-
-    if cg_flags.iter().any(|x| *x == "no-stack-check") {
-        early_warn(
-            ErrorOutputType::default(),
-            "the --no-stack-check flag is deprecated and does nothing",
-        );
-    }
-
-    if cg_flags.iter().any(|x| *x == "passes=list") {
-        let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
-        get_codegen_backend(&None, backend_name).print_passes();
+    if describe_flag_categories(&matches) {
         return None;
     }
 
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 81e8bcbf7cd..fe44799efdb 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1832,6 +1832,12 @@ impl EmitterWriter {
             }
             let show_code_change = if has_deletion && !is_multiline {
                 DisplaySuggestion::Diff
+            } else if let [part] = &parts[..]
+                && part.snippet.ends_with('\n')
+                && part.snippet.trim() == complete.trim()
+            {
+                // We are adding a line(s) of code before code that was already there.
+                DisplaySuggestion::Add
             } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim())
                 && !is_multiline
             {
@@ -1879,7 +1885,10 @@ impl EmitterWriter {
                 row_num += line_end - line_start;
             }
             let mut unhighlighted_lines = Vec::new();
+            let mut last_pos = 0;
+            let mut is_item_attribute = false;
             for (line_pos, (line, highlight_parts)) in lines.by_ref().zip(highlights).enumerate() {
+                last_pos = line_pos;
                 debug!(%line_pos, %line, ?highlight_parts);
 
                 // Remember lines that are not highlighted to hide them if needed
@@ -1887,6 +1896,12 @@ impl EmitterWriter {
                     unhighlighted_lines.push((line_pos, line));
                     continue;
                 }
+                if highlight_parts.len() == 1
+                    && line.trim().starts_with("#[")
+                    && line.trim().ends_with(']')
+                {
+                    is_item_attribute = true;
+                }
 
                 match unhighlighted_lines.len() {
                     0 => (),
@@ -1963,13 +1978,41 @@ impl EmitterWriter {
                     is_multiline,
                 )
             }
+            if let DisplaySuggestion::Add = show_code_change && is_item_attribute {
+                // The suggestion adds an entire line of code, ending on a newline, so we'll also
+                // print the *following* line, to provide context of what we're advicing people to
+                // do. Otherwise you would only see contextless code that can be confused for
+                // already existing code, despite the colors and UI elements.
+                // We special case `#[derive(_)]\n` and other attribute suggestions, because those
+                // are the ones where context is most useful.
+                let file_lines = sm
+                    .span_to_lines(span.primary_span().unwrap().shrink_to_hi())
+                    .expect("span_to_lines failed when emitting suggestion");
+                let line_num = sm.lookup_char_pos(parts[0].span.lo()).line;
+                if let Some(line) = file_lines.file.get_line(line_num - 1) {
+                    let line = normalize_whitespace(&line);
+                    self.draw_code_line(
+                        &mut buffer,
+                        &mut row_num,
+                        &[],
+                        line_num + last_pos + 1,
+                        &line,
+                        DisplaySuggestion::None,
+                        max_line_num_len,
+                        &file_lines,
+                        is_multiline,
+                    )
+                }
+            }
 
             // This offset and the ones below need to be signed to account for replacement code
             // that is shorter than the original code.
             let mut offsets: Vec<(usize, isize)> = Vec::new();
             // Only show an underline in the suggestions if the suggestion is not the
             // entirety of the code being shown and the displayed code is not multiline.
-            if let DisplaySuggestion::Diff | DisplaySuggestion::Underline = show_code_change {
+            if let DisplaySuggestion::Diff | DisplaySuggestion::Underline | DisplaySuggestion::Add =
+                show_code_change
+            {
                 draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1);
                 for part in parts {
                     let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display;
@@ -2247,6 +2290,10 @@ impl EmitterWriter {
                 }
             }
             buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle);
+        } else if let DisplaySuggestion::Add = show_code_change {
+            buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
+            buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
+            buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle);
         } else {
             buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
             draw_col_separator(buffer, *row_num, max_line_num_len + 1);
@@ -2281,6 +2328,7 @@ enum DisplaySuggestion {
     Underline,
     Diff,
     None,
+    Add,
 }
 
 impl FileWithAnnotatedLines {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 5b0d8096207..d20b168904d 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -6,7 +6,6 @@
 #![feature(array_windows)]
 #![feature(drain_filter)]
 #![feature(if_let_guard)]
-#![feature(is_terminal)]
 #![feature(adt_const_params)]
 #![feature(let_chains)]
 #![feature(never_type)]
@@ -475,8 +474,6 @@ pub enum StashKey {
     /// When an invalid lifetime e.g. `'2` should be reinterpreted
     /// as a char literal in the parser
     LifetimeIsChar,
-    /// When an invalid lifetime e.g. `'🐱` contains emoji.
-    LifetimeContainsEmoji,
     /// Maybe there was a typo where a comma was forgotten before
     /// FRU syntax
     MaybeFruTypo,
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index cfae781bdee..5d999d0db5d 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -135,4 +135,4 @@ expand_proc_macro_panicked =
     .help = message: {$message}
 
 expand_proc_macro_derive_tokens =
-    proc-macro derive produced unparseable tokens
+    proc-macro derive produced unparsable tokens
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 6bc393c6534..35572292271 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -66,7 +66,12 @@ pub(super) fn failed_to_match_macro<'cx>(
         && (matches!(expected_token.kind, TokenKind::Interpolated(_))
             || matches!(token.kind, TokenKind::Interpolated(_)))
     {
-        err.note("captured metavariables except for `$tt`, `$ident` and `$lifetime` cannot be compared to other tokens");
+        err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens");
+        err.note("see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information");
+
+        if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
+            err.help("try using `:tt` instead in the macro definition");
+        }
     }
 
     // Check whether there's a missing comma in this macro call, like `println!("{}" a);`
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 426c6727adc..48f5bd1cb50 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -309,7 +309,7 @@ declare_features! (
     (active, associated_type_defaults, "1.2.0", Some(29661), None),
     /// Allows `async || body` closures.
     (active, async_closure, "1.37.0", Some(62290), None),
-    /// Alows async functions to be declared, implemented, and used in traits.
+    /// Allows async functions to be declared, implemented, and used in traits.
     (incomplete, async_fn_in_trait, "1.66.0", Some(91611), None),
     /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries.
     (active, c_unwind, "1.52.0", Some(74990), None),
@@ -416,6 +416,8 @@ declare_features! (
     (active, half_open_range_patterns_in_slices, "1.66.0", Some(67264), None),
     /// Allows `if let` guard in match arms.
     (active, if_let_guard, "1.47.0", Some(51114), None),
+    /// Allows `impl Trait` to be used inside associated types (RFC 2515).
+    (active, impl_trait_in_assoc_type, "CURRENT_RUSTC_VERSION", Some(63063), None),
     /// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
     (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None),
     /// Allows referencing `Self` and projections in impl-trait.
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 8cb95610da0..8d1156c1771 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2520,24 +2520,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                     tcx,
                                     infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
                                 );
-                                // I guess we don't need to make a universe unless we need it,
-                                // but also we're on the error path, so it doesn't matter here.
-                                let universe = infcx.create_next_universe();
+                                let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
+                                // FIXME: Don't bother dealing with non-lifetime binders here...
+                                if value.has_escaping_bound_vars() {
+                                    return false;
+                                }
                                 infcx
                                     .can_eq(
                                         ty::ParamEnv::empty(),
                                         impl_.self_ty(),
-                                        tcx.replace_escaping_bound_vars_uncached(qself_ty, ty::fold::FnMutDelegate {
-                                            regions: &mut |_| tcx.lifetimes.re_erased,
-                                            types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType {
-                                                universe,
-                                                bound: bv,
-                                            }),
-                                            consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst {
-                                                universe,
-                                                bound: bv,
-                                            }, ty),
-                                        })
+                                        value,
                                     )
                             })
                             && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 0880c8c15f2..284b099e7bc 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -58,7 +58,7 @@ impl<'tcx> Bounds<'tcx> {
     pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
         let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
         let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [ty]));
-        // Preferrable to put this obligation first, since we report better errors for sized ambiguity.
+        // Preferable to put this obligation first, since we report better errors for sized ambiguity.
         self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span));
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 8617bca0825..0bb98fdf2a2 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -452,11 +452,8 @@ fn check_opaque_meets_bounds<'tcx>(
         hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
         // Can have different predicates to their defining use
         hir::OpaqueTyOrigin::TyAlias => {
-            let outlives_environment = OutlivesEnvironment::new(param_env);
-            let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(
-                defining_use_anchor,
-                &outlives_environment,
-            );
+            let outlives_env = OutlivesEnvironment::new(param_env);
+            let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
         }
     }
     // Clean up after ourselves
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 f6c2004c4a6..5d119a7737a 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -332,10 +332,6 @@ fn compare_method_predicate_entailment<'tcx>(
         param_env,
         infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()),
     );
-    infcx.process_registered_region_obligations(
-        outlives_env.region_bound_pairs(),
-        outlives_env.param_env,
-    );
     let errors = infcx.resolve_regions(&outlives_env);
     if !errors.is_empty() {
         // FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT
@@ -722,18 +718,18 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
         return Err(reported);
     }
 
+    let collected_types = collector.types;
+
     // Finally, resolve all regions. This catches wily misuses of
     // lifetime parameters.
-    let outlives_environment = OutlivesEnvironment::with_bounds(
+    let outlives_env = OutlivesEnvironment::with_bounds(
         param_env,
         infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
     );
-    infcx
-        .err_ctxt()
-        .check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?;
+    ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
 
     let mut collected_tys = FxHashMap::default();
-    for (def_id, (ty, substs)) in collector.types {
+    for (def_id, (ty, substs)) in collected_types {
         match infcx.fully_resolve(ty) {
             Ok(ty) => {
                 // `ty` contains free regions that we created earlier while liberating the
@@ -1742,11 +1738,8 @@ pub(super) fn compare_impl_const_raw(
         return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
     }
 
-    let outlives_environment = OutlivesEnvironment::new(param_env);
-    infcx
-        .err_ctxt()
-        .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?;
-    Ok(())
+    let outlives_env = OutlivesEnvironment::new(param_env);
+    ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env)
 }
 
 pub(super) fn compare_impl_ty<'tcx>(
@@ -1845,13 +1838,8 @@ fn compare_type_predicate_entailment<'tcx>(
 
     // Finally, resolve all regions. This catches wily misuses of
     // lifetime parameters.
-    let outlives_environment = OutlivesEnvironment::new(param_env);
-    infcx.err_ctxt().check_region_obligations_and_report_errors(
-        impl_ty.def_id.expect_local(),
-        &outlives_environment,
-    )?;
-
-    Ok(())
+    let outlives_env = OutlivesEnvironment::new(param_env);
+    ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
 }
 
 /// Validate that `ProjectionCandidate`s created for this associated type will
@@ -2063,14 +2051,8 @@ pub(super) fn check_type_bounds<'tcx>(
     // Finally, resolve all regions. This catches wily misuses of
     // lifetime parameters.
     let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types);
-    let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
-
-    infcx.err_ctxt().check_region_obligations_and_report_errors(
-        impl_ty.def_id.expect_local(),
-        &outlives_environment,
-    )?;
-
-    Ok(())
+    let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
+    ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
 }
 
 fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index c03621fcfb2..53197bc8491 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -114,11 +114,9 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
         return;
     }
 
-    let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
+    let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
 
-    let _ = infcx
-        .err_ctxt()
-        .check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
+    let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env);
 }
 
 fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
@@ -680,12 +678,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
 
     add_constraints(&infcx, region_bound_pairs);
 
-    infcx.process_registered_region_obligations(
-        outlives_environment.region_bound_pairs(),
-        param_env,
-    );
     let errors = infcx.resolve_regions(&outlives_environment);
-
     debug!(?errors, "errors");
 
     // If we were able to prove that the type outlives the region without
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index ac7c68d9c4b..0f40cca9427 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -354,9 +354,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
 
                 // Finally, resolve all regions.
                 let outlives_env = OutlivesEnvironment::new(param_env);
-                let _ = infcx
-                    .err_ctxt()
-                    .check_region_obligations_and_report_errors(impl_did, &outlives_env);
+                let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
             }
         }
         _ => {
@@ -592,7 +590,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
 
     // Finally, resolve all regions.
     let outlives_env = OutlivesEnvironment::new(param_env);
-    let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env);
+    let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
 
     CoerceUnsizedInfo { custom_kind: kind }
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 225b1550580..c173bd913a8 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -8,10 +8,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{
-    self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable,
-    TypeVisitableExt,
-};
+use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -874,28 +871,6 @@ fn infer_placeholder_type<'a>(
     item_ident: Ident,
     kind: &'static str,
 ) -> Ty<'a> {
-    // Attempts to make the type nameable by turning FnDefs into FnPtrs.
-    struct MakeNameable<'tcx> {
-        tcx: TyCtxt<'tcx>,
-    }
-
-    impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MakeNameable<'tcx> {
-        fn interner(&self) -> TyCtxt<'tcx> {
-            self.tcx
-        }
-
-        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-            let ty = match *ty.kind() {
-                ty::FnDef(def_id, substs) => {
-                    self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
-                }
-                _ => ty,
-            };
-
-            ty.super_fold_with(self)
-        }
-    }
-
     let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
 
     // If this came from a free `const` or `static mut?` item,
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 35785e81ff4..eb2fc395223 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -180,8 +180,7 @@ fn get_impl_substs(
 
     let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
     let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
-    let _ =
-        infcx.err_ctxt().check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
+    let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
     let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
         let span = tcx.def_span(impl1_def_id);
         tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 30d307948a6..a4c3be1d177 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -308,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let rcvr_ty = self.node_ty(rcvr.hir_id);
                 // Get the evaluated type *after* calling the method call, so that the influence
                 // of the arguments can be reflected in the receiver type. The receiver
-                // expression has the type *before* theis analysis is done.
+                // expression has the type *before* this analysis is done.
                 let ty = match self.lookup_probe_for_diagnostic(
                     segment.ident,
                     rcvr_ty,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 68e096e3bd0..6ffa0134f3d 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -120,7 +120,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ty
     }
 
-    pub(super) fn check_expr_coercable_to_type(
+    pub(super) fn check_expr_coercible_to_type(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
         expected: Ty<'tcx>,
@@ -1128,7 +1128,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
 
-        // This is (basically) inlined `check_expr_coercable_to_type`, but we want
+        // This is (basically) inlined `check_expr_coercible_to_type`, but we want
         // to suggest an additional fixup here in `suggest_deref_binop`.
         let rhs_ty = self.check_expr_with_hint(&rhs, lhs_ty);
         if let (_, Some(mut diag)) =
@@ -1401,7 +1401,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let (element_ty, t) = match uty {
             Some(uty) => {
-                self.check_expr_coercable_to_type(&element, uty, None);
+                self.check_expr_coercible_to_type(&element, uty, None);
                 (uty, uty)
             }
             None => {
@@ -1478,7 +1478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds {
             Some(fs) if i < fs.len() => {
                 let ety = fs[i];
-                self.check_expr_coercable_to_type(&e, ety, None);
+                self.check_expr_coercible_to_type(&e, ety, None);
                 ety
             }
             _ => self.check_expr_with_expectation(&e, NoExpectation),
@@ -2869,7 +2869,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         match self.resume_yield_tys {
             Some((resume_ty, yield_ty)) => {
-                self.check_expr_coercable_to_type(&value, yield_ty, None);
+                self.check_expr_coercible_to_type(&value, yield_ty, None);
 
                 resume_ty
             }
@@ -2878,7 +2878,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // information. Hence, we check the source of the yield expression here and check its
             // value's type against `()` (this check should always hold).
             None if src.is_await() => {
-                self.check_expr_coercable_to_type(&value, self.tcx.mk_unit(), None);
+                self.check_expr_coercible_to_type(&value, self.tcx.mk_unit(), None);
                 self.tcx.mk_unit()
             }
             _ => {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index fdf178c3ea7..f736f7a9620 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -578,7 +578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     pub(in super::super) fn report_ambiguity_errors(&self) {
-        let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors();
+        let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors(self);
 
         if !errors.is_empty() {
             self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index 3e0c2bf2a55..f879ccbb3af 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -78,7 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Finally, for ambiguity-related errors, we actually want to look
         // for a parameter that is the source of the inference type left
         // over in this predicate.
-        if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
+        if let traits::FulfillmentErrorCode::CodeAmbiguity { .. } = error.code {
             fallback_param_to_point_at = None;
             self_param_to_point_at = None;
             param_to_point_at =
@@ -466,7 +466,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
     ///
     /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
-    /// reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be
+    /// reported as an error. If it is `Ok`, then it means it refined successful. If it is `Err`, then it may be
     /// only a partial success - but it cannot be refined even further.
     fn blame_specific_expr_if_possible_for_derived_predicate_obligation(
         &self,
@@ -534,7 +534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// - in_ty: `(Option<Vec<T>, bool)`
     /// we would drill until we arrive at `vec![1, 2, 3]`.
     ///
-    /// If successful, we return `Ok(refined_expr)`. If unsuccesful, we return `Err(partially_refined_expr`),
+    /// If successful, we return `Ok(refined_expr)`. If unsuccessful, we return `Err(partially_refined_expr`),
     /// which will go as far as possible. For example, given `(foo(), false)` instead, we would drill to
     /// `foo()` and then return `Err("foo()")`.
     ///
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index cf93d1d2182..a009ae5d44e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1413,7 +1413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.demand_eqtype(init.span, local_ty, init_ty);
             init_ty
         } else {
-            self.check_expr_coercable_to_type(init, local_ty, None)
+            self.check_expr_coercible_to_type(init, local_ty, None)
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 6af095cb4d4..45890abad92 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -280,7 +280,7 @@ fn typeck_with_fallback<'tcx>(
         // Gather locals in statics (because of block expressions).
         GatherLocalsVisitor::new(&fcx).visit_body(body);
 
-        fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
+        fcx.check_expr_coercible_to_type(&body.value, expected_type, None);
 
         fcx.write_ty(id, expected_type);
     };
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 08cd6085d7f..4fd778910ba 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1531,23 +1531,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
                     // Convert the bounds into obligations.
                     let impl_obligations = traits::predicates_for_generics(
-                        |_idx, span| {
-                            let misc = traits::ObligationCause::misc(span, self.body_id);
-                            let parent_trait_pred = ty::Binder::dummy(ty::TraitPredicate {
-                                trait_ref: ty::TraitRef::from_method(self.tcx, impl_def_id, substs),
-                                constness: ty::BoundConstness::NotConst,
-                                polarity: ty::ImplPolarity::Positive,
-                            });
-                            misc.derived_cause(parent_trait_pred, |derived| {
-                                traits::ImplDerivedObligation(Box::new(
-                                    traits::ImplDerivedObligationCause {
-                                        derived,
-                                        impl_or_alias_def_id: impl_def_id,
-                                        impl_def_predicate_index: None,
-                                        span,
-                                    },
-                                ))
-                            })
+                        |idx, span| {
+                            let code = if span.is_dummy() {
+                                traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx)
+                            } else {
+                                traits::ExprBindingObligation(
+                                    impl_def_id,
+                                    span,
+                                    self.scope_expr_id,
+                                    idx,
+                                )
+                            };
+                            ObligationCause::new(self.span, self.body_id, code)
                         },
                         self.param_env,
                         impl_bounds,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 5c50619f4c3..900a6fa0d8d 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -300,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // We could pass the file for long types into these two, but it isn't strictly necessary
-        // given how targetted they are.
+        // given how targeted they are.
         if self.suggest_wrapping_range_with_parens(
             tcx,
             rcvr_ty,
@@ -661,19 +661,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Find all the requirements that come from a local `impl` block.
             let mut skip_list: FxHashSet<_> = Default::default();
             let mut spanned_predicates = FxHashMap::default();
-            for (p, parent_p, impl_def_id, cause) in unsatisfied_predicates
-                .iter()
-                .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
-                .filter_map(|(p, parent, c)| match c.code() {
-                    ObligationCauseCode::ImplDerivedObligation(data)
-                        if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
-                    {
-                        Some((p, parent, data.impl_or_alias_def_id, data))
+            for (p, parent_p, cause) in unsatisfied_predicates {
+                // Extract the predicate span and parent def id of the cause,
+                // if we have one.
+                let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) {
+                    Some(ObligationCauseCode::ImplDerivedObligation(data)) => {
+                        (data.impl_or_alias_def_id, data.span)
                     }
-                    _ => None,
-                })
-            {
-                match self.tcx.hir().get_if_local(impl_def_id) {
+                    Some(
+                        ObligationCauseCode::ExprBindingObligation(def_id, span, _, _)
+                        | ObligationCauseCode::BindingObligation(def_id, span),
+                    ) => (*def_id, *span),
+                    _ => continue,
+                };
+
+                // Don't point out the span of `WellFormed` predicates.
+                if !matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) {
+                    continue;
+                };
+
+                match self.tcx.hir().get_if_local(item_def_id) {
                     // Unmet obligation comes from a `derive` macro, point at it once to
                     // avoid multiple span labels pointing at the same place.
                     Some(Node::Item(hir::Item {
@@ -718,7 +725,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 }
                             });
                         for param in generics.params {
-                            if param.span == cause.span && sized_pred {
+                            if param.span == cause_span && sized_pred {
                                 let (sp, sugg) = match param.colon_span {
                                     Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
                                     None => (param.span.shrink_to_hi(), ": ?Sized"),
@@ -741,9 +748,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             (FxHashSet::default(), FxHashSet::default(), Vec::new())
                         });
                         entry.2.push(p);
-                        if cause.span != *item_span {
-                            entry.0.insert(cause.span);
-                            entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
+                        if cause_span != *item_span {
+                            entry.0.insert(cause_span);
+                            entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
                         } else {
                             if let Some(trait_ref) = of_trait {
                                 entry.0.insert(trait_ref.path.span);
@@ -775,9 +782,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let entry = entry.or_insert_with(|| {
                             (FxHashSet::default(), FxHashSet::default(), Vec::new())
                         });
-                        entry.0.insert(cause.span);
+                        entry.0.insert(cause_span);
                         entry.1.insert((ident.span, ""));
-                        entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
+                        entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
                         entry.2.push(p);
                     }
                     Some(node) => unreachable!("encountered `{node:?}`"),
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 8a83bb58573..a52c94cb00c 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -12,9 +12,7 @@ use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{
-    self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
-};
+use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
@@ -103,9 +101,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match BinOpCategory::from(op) {
             BinOpCategory::Shortcircuit => {
                 // && and || are a simple case.
-                self.check_expr_coercable_to_type(lhs_expr, tcx.types.bool, None);
+                self.check_expr_coercible_to_type(lhs_expr, tcx.types.bool, None);
                 let lhs_diverges = self.diverges.get();
-                self.check_expr_coercable_to_type(rhs_expr, tcx.types.bool, None);
+                self.check_expr_coercible_to_type(rhs_expr, tcx.types.bool, None);
 
                 // Depending on the LHS' value, the RHS can never execute.
                 self.diverges.set(lhs_diverges);
@@ -255,7 +253,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
 
         // see `NB` above
-        let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var, Some(lhs_expr));
+        let rhs_ty = self.check_expr_coercible_to_type(rhs_expr, rhs_ty_var, Some(lhs_expr));
         let rhs_ty = self.resolve_vars_with_obligations(rhs_ty);
 
         let return_ty = match result {
@@ -965,21 +963,3 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool
         }
     }
 }
-
-struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span);
-
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TypeParamEraser<'_, 'tcx> {
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.0.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        match ty.kind() {
-            ty::Param(_) => self.0.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::MiscVariable,
-                span: self.1,
-            }),
-            _ => ty.super_fold_with(self),
-        }
-    }
-}
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 4d4a7880b00..c8998ea91bf 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -163,7 +163,6 @@ infer_region_explanation = {$pref_kind ->
     [as_defined] the lifetime `{$desc_arg}` as defined here
     [as_defined_anon] the anonymous lifetime as defined here
     [defined_here] the anonymous lifetime defined here
-    [anon_num_here] the anonymous lifetime #{$desc_num_arg} defined here
     [defined_here_reg] the lifetime `{$desc_arg}` as defined here
 }{$suff_kind ->
     *[should_not_happen] [{$suff_kind}]
@@ -174,7 +173,7 @@ infer_region_explanation = {$pref_kind ->
 
 infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
 infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
-infer_fullfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
+infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
 infer_lf_bound_not_satisfied = lifetime bound not satisfied
 infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
 infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index b129621130d..65b3dd1a892 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -53,7 +53,7 @@ pub struct AnnotationRequired<'a> {
 // Copy of `AnnotationRequired` for E0283
 #[derive(Diagnostic)]
 #[diag(infer_type_annotations_needed, code = "E0283")]
-pub struct AmbigousImpl<'a> {
+pub struct AmbiguousImpl<'a> {
     #[primary_span]
     pub span: Span,
     pub source_kind: &'static str,
@@ -942,8 +942,8 @@ pub struct OutlivesBound<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_fullfill_req_lifetime, code = "E0477")]
-pub struct FullfillReqLifetime<'a> {
+#[diag(infer_fulfill_req_lifetime, code = "E0477")]
+pub struct FulfillReqLifetime<'a> {
     #[primary_span]
     pub span: Span,
     pub ty: Ty<'a>,
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 30f6af74b83..7328241dfbc 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -4,12 +4,10 @@ use rustc_errors::{self, AddToDiagnostic, Diagnostic, IntoDiagnosticArg, Subdiag
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{symbol::kw, Span};
 
-#[derive(Default)]
 struct DescriptionCtx<'a> {
     span: Option<Span>,
     kind: &'a str,
     arg: String,
-    num_arg: u32,
 }
 
 impl<'a> DescriptionCtx<'a> {
@@ -18,102 +16,74 @@ impl<'a> DescriptionCtx<'a> {
         region: ty::Region<'tcx>,
         alt_span: Option<Span>,
     ) -> Option<Self> {
-        let mut me = DescriptionCtx::default();
-        me.span = alt_span;
-        match *region {
-            ty::ReEarlyBound(_) | ty::ReFree(_) => {
-                return Self::from_early_bound_and_free_regions(tcx, region);
-            }
-            ty::ReStatic => {
-                me.kind = "restatic";
-            }
-
-            ty::RePlaceholder(_) => return None,
-
-            ty::ReError(_) => return None,
-
-            // FIXME(#13998) RePlaceholder should probably print like
-            // ReFree rather than dumping Debug output on the user.
-            //
-            // We shouldn't really be having unification failures with ReVar
-            // and ReLateBound though.
-            ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
-                me.kind = "revar";
-                me.arg = format!("{:?}", region);
-            }
-        };
-        Some(me)
-    }
-
-    fn from_early_bound_and_free_regions<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        region: ty::Region<'tcx>,
-    ) -> Option<Self> {
-        let mut me = DescriptionCtx::default();
-        let scope = region.free_region_binding_scope(tcx).expect_local();
-        match *region {
+        let (span, kind, arg) = match *region {
             ty::ReEarlyBound(ref br) => {
-                let mut sp = tcx.def_span(scope);
-                if let Some(param) =
+                let scope = region.free_region_binding_scope(tcx).expect_local();
+                let span = if let Some(param) =
                     tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
                 {
-                    sp = param.span;
-                }
-                if br.has_name() {
-                    me.kind = "as_defined";
-                    me.arg = br.name.to_string();
+                    param.span
                 } else {
-                    me.kind = "as_defined_anon";
+                    tcx.def_span(scope)
                 };
-                me.span = Some(sp)
+                if br.has_name() {
+                    (Some(span), "as_defined", br.name.to_string())
+                } else {
+                    (Some(span), "as_defined_anon", String::new())
+                }
             }
             ty::ReFree(ref fr) => {
                 if !fr.bound_region.is_named()
                     && let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
                 {
-                    me.kind = "defined_here";
-                    me.span = Some(ty.span);
+                    (Some(ty.span), "defined_here", String::new())
                 } else {
+                    let scope = region.free_region_binding_scope(tcx).expect_local();
                     match fr.bound_region {
                         ty::BoundRegionKind::BrNamed(_, name) => {
-                            let mut sp = tcx.def_span(scope);
-                            if let Some(param) =
-                                tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
+                            let span = if let Some(param) = tcx
+                                .hir()
+                                .get_generics(scope)
+                                .and_then(|generics| generics.get_named(name))
                             {
-                                sp = param.span;
-                            }
-                            if name == kw::UnderscoreLifetime {
-                                me.kind = "as_defined_anon";
+                                param.span
                             } else {
-                                me.kind = "as_defined";
-                                me.arg = name.to_string();
+                                tcx.def_span(scope)
                             };
-                            me.span = Some(sp);
+                            if name == kw::UnderscoreLifetime {
+                                (Some(span), "as_defined_anon", String::new())
+                            } else {
+                                (Some(span), "as_defined", name.to_string())
+                            }
                         }
                         ty::BrAnon(span) => {
-                            me.kind = "defined_here";
-                            me.span = match span {
+                            let span = match span {
                                 Some(_) => span,
                                 None => Some(tcx.def_span(scope)),
-                            }
-                        },
+                            };
+                            (span, "defined_here", String::new())
+                        }
                         _ => {
-                            me.kind = "defined_here_reg";
-                            me.arg = region.to_string();
-                            me.span = Some(tcx.def_span(scope));
-                        },
+                            (Some(tcx.def_span(scope)), "defined_here_reg", region.to_string())
+                        }
                     }
                 }
             }
-            _ => bug!(),
-        }
-        Some(me)
-    }
 
-    fn add_to(self, diag: &mut rustc_errors::Diagnostic) {
-        diag.set_arg("desc_kind", self.kind);
-        diag.set_arg("desc_arg", self.arg);
-        diag.set_arg("desc_num_arg", self.num_arg);
+            ty::ReStatic => (alt_span, "restatic", String::new()),
+
+            ty::RePlaceholder(_) | ty::ReError(_) => return None,
+
+            // FIXME(#13998) RePlaceholder should probably print like
+            // ReFree rather than dumping Debug output on the user.
+            //
+            // We shouldn't really be having unification failures with ReVar
+            // and ReLateBound though.
+            ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
+                (alt_span, "revar", format!("{:?}", region))
+            }
+        };
+        Some(DescriptionCtx { span, kind, arg })
     }
 }
 
@@ -198,10 +168,11 @@ impl AddToDiagnostic for RegionExplanation<'_> {
     {
         diag.set_arg("pref_kind", self.prefix);
         diag.set_arg("suff_kind", self.suffix);
-        let desc_span = self.desc.span;
-        self.desc.add_to(diag);
+        diag.set_arg("desc_kind", self.desc.kind);
+        diag.set_arg("desc_arg", self.desc.arg);
+
         let msg = f(diag, fluent::infer_region_explanation.into());
-        if let Some(span) = desc_span {
+        if let Some(span) = self.desc.span {
             diag.span_note(span, msg);
         } else {
             diag.note(msg);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 7901bc94021..9e5f6d107d1 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -74,6 +74,7 @@ use rustc_middle::ty::{
     self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
     TypeVisitable, TypeVisitableExt,
 };
+use rustc_span::DUMMY_SP;
 use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::ops::{ControlFlow, Deref};
@@ -113,7 +114,11 @@ fn escape_literal(s: &str) -> String {
 
 /// A helper for building type related errors. The `typeck_results`
 /// field is only populated during an in-progress typeck.
-/// Get an instance by calling `InferCtxt::err` or `FnCtxt::infer_err`.
+/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
+///
+/// You must only create this if you intend to actually emit an error.
+/// This provides a lot of utility methods which should not be used
+/// during the happy path.
 pub struct TypeErrCtxt<'a, 'tcx> {
     pub infcx: &'a InferCtxt<'tcx>,
     pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
@@ -125,6 +130,19 @@ pub struct TypeErrCtxt<'a, 'tcx> {
         Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
 }
 
+impl Drop for TypeErrCtxt<'_, '_> {
+    fn drop(&mut self) {
+        if let Some(_) = self.infcx.tcx.sess.has_errors_or_delayed_span_bugs() {
+            // ok, emitted an error.
+        } else {
+            self.infcx
+                .tcx
+                .sess
+                .delay_span_bug(DUMMY_SP, "used a `TypeErrCtxt` without failing compilation");
+        }
+    }
+}
+
 impl TypeErrCtxt<'_, '_> {
     /// This is just to avoid a potential footgun of accidentally
     /// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
@@ -185,83 +203,73 @@ fn msg_span_from_named_region<'tcx>(
     alt_span: Option<Span>,
 ) -> (String, Option<Span>) {
     match *region {
-        ty::ReEarlyBound(_) | ty::ReFree(_) => {
-            let (msg, span) = msg_span_from_early_bound_and_free_regions(tcx, region);
-            (msg, Some(span))
-        }
-        ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
-        ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, name), .. },
-            ..
-        }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
-        ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. },
-            ..
-        }) => (format!("the anonymous lifetime defined here"), Some(span)),
-        ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. },
-            ..
-        }) => (format!("an anonymous lifetime"), None),
-        _ => bug!("{:?}", region),
-    }
-}
-
-fn msg_span_from_early_bound_and_free_regions<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    region: ty::Region<'tcx>,
-) -> (String, Span) {
-    let scope = region.free_region_binding_scope(tcx).expect_local();
-    match *region {
         ty::ReEarlyBound(ref br) => {
-            let mut sp = tcx.def_span(scope);
-            if let Some(param) =
+            let scope = region.free_region_binding_scope(tcx).expect_local();
+            let span = if let Some(param) =
                 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
             {
-                sp = param.span;
-            }
+                param.span
+            } else {
+                tcx.def_span(scope)
+            };
             let text = if br.has_name() {
                 format!("the lifetime `{}` as defined here", br.name)
             } else {
                 "the anonymous lifetime as defined here".to_string()
             };
-            (text, sp)
+            (text, Some(span))
         }
         ty::ReFree(ref fr) => {
             if !fr.bound_region.is_named()
                 && let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
             {
-                ("the anonymous lifetime defined here".to_string(), ty.span)
+                ("the anonymous lifetime defined here".to_string(), Some(ty.span))
             } else {
+                let scope = region.free_region_binding_scope(tcx).expect_local();
                 match fr.bound_region {
                     ty::BoundRegionKind::BrNamed(_, name) => {
-                        let mut sp = tcx.def_span(scope);
-                        if let Some(param) =
+                        let span = if let Some(param) =
                             tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
                         {
-                            sp = param.span;
-                        }
+                            param.span
+                        } else {
+                            tcx.def_span(scope)
+                        };
                         let text = if name == kw::UnderscoreLifetime {
                             "the anonymous lifetime as defined here".to_string()
                         } else {
                             format!("the lifetime `{}` as defined here", name)
                         };
-                        (text, sp)
+                        (text, Some(span))
                     }
                     ty::BrAnon(span) => (
                         "the anonymous lifetime as defined here".to_string(),
-                        match span {
+                        Some(match span {
                             Some(span) => span,
                             None => tcx.def_span(scope)
-                        }
+                        })
                     ),
                     _ => (
                         format!("the lifetime `{}` as defined here", region),
-                        tcx.def_span(scope),
+                        Some(tcx.def_span(scope)),
                     ),
                 }
             }
         }
-        _ => bug!(),
+        ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
+        ty::RePlaceholder(ty::PlaceholderRegion {
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, name), .. },
+            ..
+        }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
+        ty::RePlaceholder(ty::PlaceholderRegion {
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. },
+            ..
+        }) => (format!("the anonymous lifetime defined here"), Some(span)),
+        ty::RePlaceholder(ty::PlaceholderRegion {
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. },
+            ..
+        }) => (format!("an anonymous lifetime"), None),
+        _ => bug!("{:?}", region),
     }
 }
 
@@ -419,7 +427,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         generic_param_scope: LocalDefId,
         errors: &[RegionResolutionError<'tcx>],
-    ) {
+    ) -> ErrorGuaranteed {
+        if let Some(guaranteed) = self.infcx.tainted_by_errors() {
+            return guaranteed;
+        }
+
         debug!("report_region_errors(): {} errors to start", errors.len());
 
         // try to pre-process the errors, which will group some of them
@@ -499,6 +511,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
             }
         }
+
+        self.tcx
+            .sess
+            .delay_span_bug(self.tcx.def_span(generic_param_scope), "expected region errors")
     }
 
     // This method goes through all the errors and try to group certain types
@@ -1829,7 +1845,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             // will try to hide in some case such as `async fn`, so
                             // to make an error more use friendly we will
                             // avoid to suggest a mismatch type with a
-                            // type that the user usually are not usign
+                            // type that the user usually are not using
                             // directly such as `impl Future<Output = u8>`.
                             if !self.tcx.ty_is_opaque_future(found_ty) {
                                 diag.note_expected_found_extra(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index d7b900ca02d..75cc4e257bd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -1,5 +1,5 @@
 use crate::errors::{
-    AmbigousImpl, AmbigousReturn, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
+    AmbigousReturn, AmbiguousImpl, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
     SourceKindMultiSuggestion, SourceKindSubdiag,
 };
 use crate::infer::error_reporting::TypeErrCtxt;
@@ -358,7 +358,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 bad_label,
             }
             .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
-            TypeAnnotationNeeded::E0283 => AmbigousImpl {
+            TypeAnnotationNeeded::E0283 => AmbiguousImpl {
                 span,
                 source_kind,
                 source_name,
@@ -563,7 +563,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 bad_label: None,
             }
             .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
-            TypeAnnotationNeeded::E0283 => AmbigousImpl {
+            TypeAnnotationNeeded::E0283 => AmbiguousImpl {
                 span,
                 source_kind,
                 source_name: &name,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index e720af73c39..07a9eff2dbe 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -1,5 +1,5 @@
 use crate::errors::{
-    note_and_explain, FullfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
+    note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
     RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
 };
 use crate::fluent_generated as fluent;
@@ -176,7 +176,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let note = note_and_explain::RegionExplanation::new(
                     self.tcx, sub, opt_span, prefix, suffix,
                 );
-                FullfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
+                FulfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
                     .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
             }
             infer::RelateRegionParamBound(span) => {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index b4f2ad0bb34..66f51328bbe 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -45,8 +45,7 @@ use self::combine::CombineFields;
 use self::error_reporting::TypeErrCtxt;
 use self::free_regions::RegionRelations;
 use self::lexical_region_resolve::LexicalRegionResolutions;
-use self::outlives::env::OutlivesEnvironment;
-use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
+use self::region_constraints::{GenericKind, VarInfos, VerifyBound};
 use self::region_constraints::{
     RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
 };
@@ -1213,95 +1212,6 @@ impl<'tcx> InferCtxt<'tcx> {
         self.tainted_by_errors.set(Some(e));
     }
 
-    pub fn skip_region_resolution(&self) {
-        let (var_infos, _) = {
-            let mut inner = self.inner.borrow_mut();
-            let inner = &mut *inner;
-            // Note: `inner.region_obligations` may not be empty, because we
-            // didn't necessarily call `process_registered_region_obligations`.
-            // This is okay, because that doesn't introduce new vars.
-            inner
-                .region_constraint_storage
-                .take()
-                .expect("regions already resolved")
-                .with_log(&mut inner.undo_log)
-                .into_infos_and_data()
-        };
-
-        let lexical_region_resolutions = LexicalRegionResolutions {
-            values: rustc_index::vec::IndexVec::from_elem_n(
-                crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
-                var_infos.len(),
-            ),
-        };
-
-        let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
-        assert!(old_value.is_none());
-    }
-
-    /// Process the region constraints and return any errors that
-    /// result. After this, no more unification operations should be
-    /// done -- or the compiler will panic -- but it is legal to use
-    /// `resolve_vars_if_possible` as well as `fully_resolve`.
-    pub fn resolve_regions(
-        &self,
-        outlives_env: &OutlivesEnvironment<'tcx>,
-    ) -> Vec<RegionResolutionError<'tcx>> {
-        let (var_infos, data) = {
-            let mut inner = self.inner.borrow_mut();
-            let inner = &mut *inner;
-            assert!(
-                self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
-                "region_obligations not empty: {:#?}",
-                inner.region_obligations
-            );
-            inner
-                .region_constraint_storage
-                .take()
-                .expect("regions already resolved")
-                .with_log(&mut inner.undo_log)
-                .into_infos_and_data()
-        };
-
-        let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
-
-        let (lexical_region_resolutions, errors) =
-            lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
-
-        let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
-        assert!(old_value.is_none());
-
-        errors
-    }
-    /// Obtains (and clears) the current set of region
-    /// constraints. The inference context is still usable: further
-    /// unifications will simply add new constraints.
-    ///
-    /// This method is not meant to be used with normal lexical region
-    /// resolution. Rather, it is used in the NLL mode as a kind of
-    /// interim hack: basically we run normal type-check and generate
-    /// region constraints as normal, but then we take them and
-    /// translate them into the form that the NLL solver
-    /// understands. See the NLL module for mode details.
-    pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
-        assert!(
-            self.inner.borrow().region_obligations.is_empty(),
-            "region_obligations not empty: {:#?}",
-            self.inner.borrow().region_obligations
-        );
-
-        self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
-    }
-
-    /// Gives temporary access to the region constraint data.
-    pub fn with_region_constraints<R>(
-        &self,
-        op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
-    ) -> R {
-        let mut inner = self.inner.borrow_mut();
-        op(inner.unwrap_region_constraints().data())
-    }
-
     pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin {
         let mut inner = self.inner.borrow_mut();
         let inner = &mut *inner;
@@ -1754,56 +1664,6 @@ impl<'cx, 'tcx> Drop for CanonicalizationCtxtGuard<'cx, 'tcx> {
 }
 
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    /// Processes registered region obliations and resolves regions, reporting
-    /// any errors if any were raised. Prefer using this function over manually
-    /// calling `resolve_regions_and_report_errors`.
-    pub fn check_region_obligations_and_report_errors(
-        &self,
-        generic_param_scope: LocalDefId,
-        outlives_env: &OutlivesEnvironment<'tcx>,
-    ) -> Result<(), ErrorGuaranteed> {
-        self.process_registered_region_obligations(
-            outlives_env.region_bound_pairs(),
-            outlives_env.param_env,
-        );
-
-        self.resolve_regions_and_report_errors(generic_param_scope, outlives_env)
-    }
-
-    /// Process the region constraints and report any errors that
-    /// result. After this, no more unification operations should be
-    /// done -- or the compiler will panic -- but it is legal to use
-    /// `resolve_vars_if_possible` as well as `fully_resolve`.
-    ///
-    /// Make sure to call [`InferCtxt::process_registered_region_obligations`]
-    /// first, or preferably use [`TypeErrCtxt::check_region_obligations_and_report_errors`]
-    /// to do both of these operations together.
-    pub fn resolve_regions_and_report_errors(
-        &self,
-        generic_param_scope: LocalDefId,
-        outlives_env: &OutlivesEnvironment<'tcx>,
-    ) -> Result<(), ErrorGuaranteed> {
-        let errors = self.resolve_regions(outlives_env);
-
-        if let None = self.tainted_by_errors() {
-            // As a heuristic, just skip reporting region errors
-            // altogether if other errors have been reported while
-            // this infcx was in use. This is totally hokey but
-            // otherwise we have a hard time separating legit region
-            // errors from silly ones.
-            self.report_region_errors(generic_param_scope, &errors);
-        }
-
-        if errors.is_empty() {
-            Ok(())
-        } else {
-            Err(self
-                .tcx
-                .sess
-                .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted"))
-        }
-    }
-
     // [Note-Type-error-reporting]
     // An invariant is that anytime the expected or actual type is Error (the special
     // error type, meaning that an error occurred when typechecking this expression),
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 048dad3a48b..9a9a1696b00 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -1,4 +1,11 @@
 //! Various code related to computing outlives relations.
+use self::env::OutlivesEnvironment;
+use super::region_constraints::RegionConstraintData;
+use super::{InferCtxt, RegionResolutionError};
+use crate::infer::free_regions::RegionRelations;
+use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions};
+use rustc_middle::traits::query::OutlivesBound;
+use rustc_middle::ty;
 
 pub mod components;
 pub mod env;
@@ -6,9 +13,6 @@ pub mod obligations;
 pub mod test_type_match;
 pub mod verify;
 
-use rustc_middle::traits::query::OutlivesBound;
-use rustc_middle::ty;
-
 #[instrument(level = "debug", skip(param_env), ret)]
 pub fn explicit_outlives_bounds<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
@@ -39,3 +43,98 @@ pub fn explicit_outlives_bounds<'tcx>(
             ))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)),
         })
 }
+
+impl<'tcx> InferCtxt<'tcx> {
+    pub fn skip_region_resolution(&self) {
+        let (var_infos, _) = {
+            let mut inner = self.inner.borrow_mut();
+            let inner = &mut *inner;
+            // Note: `inner.region_obligations` may not be empty, because we
+            // didn't necessarily call `process_registered_region_obligations`.
+            // This is okay, because that doesn't introduce new vars.
+            inner
+                .region_constraint_storage
+                .take()
+                .expect("regions already resolved")
+                .with_log(&mut inner.undo_log)
+                .into_infos_and_data()
+        };
+
+        let lexical_region_resolutions = LexicalRegionResolutions {
+            values: rustc_index::vec::IndexVec::from_elem_n(
+                crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
+                var_infos.len(),
+            ),
+        };
+
+        let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
+        assert!(old_value.is_none());
+    }
+
+    /// Process the region constraints and return any errors that
+    /// result. After this, no more unification operations should be
+    /// done -- or the compiler will panic -- but it is legal to use
+    /// `resolve_vars_if_possible` as well as `fully_resolve`.
+    #[must_use]
+    pub fn resolve_regions(
+        &self,
+        outlives_env: &OutlivesEnvironment<'tcx>,
+    ) -> Vec<RegionResolutionError<'tcx>> {
+        self.process_registered_region_obligations(outlives_env);
+
+        let (var_infos, data) = {
+            let mut inner = self.inner.borrow_mut();
+            let inner = &mut *inner;
+            assert!(
+                self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
+                "region_obligations not empty: {:#?}",
+                inner.region_obligations
+            );
+            inner
+                .region_constraint_storage
+                .take()
+                .expect("regions already resolved")
+                .with_log(&mut inner.undo_log)
+                .into_infos_and_data()
+        };
+
+        let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
+
+        let (lexical_region_resolutions, errors) =
+            lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
+
+        let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
+        assert!(old_value.is_none());
+
+        errors
+    }
+
+    /// Obtains (and clears) the current set of region
+    /// constraints. The inference context is still usable: further
+    /// unifications will simply add new constraints.
+    ///
+    /// This method is not meant to be used with normal lexical region
+    /// resolution. Rather, it is used in the NLL mode as a kind of
+    /// interim hack: basically we run normal type-check and generate
+    /// region constraints as normal, but then we take them and
+    /// translate them into the form that the NLL solver
+    /// understands. See the NLL module for mode details.
+    pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
+        assert!(
+            self.inner.borrow().region_obligations.is_empty(),
+            "region_obligations not empty: {:#?}",
+            self.inner.borrow().region_obligations
+        );
+
+        self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
+    }
+
+    /// Gives temporary access to the region constraint data.
+    pub fn with_region_constraints<R>(
+        &self,
+        op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
+    ) -> R {
+        let mut inner = self.inner.borrow_mut();
+        op(inner.unwrap_region_constraints().data())
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index bbe7d4c63f7..ccf11c61b57 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -72,6 +72,8 @@ use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
 use smallvec::smallvec;
 
+use super::env::OutlivesEnvironment;
+
 impl<'tcx> InferCtxt<'tcx> {
     /// Registers that the given region obligation must be resolved
     /// from within the scope of `body_id`. These regions are enqueued
@@ -112,39 +114,17 @@ impl<'tcx> InferCtxt<'tcx> {
         std::mem::take(&mut self.inner.borrow_mut().region_obligations)
     }
 
-    /// NOTE: Prefer using `TypeErrCtxt::check_region_obligations_and_report_errors`
-    /// instead of calling this directly.
-    ///
     /// Process the region obligations that must be proven (during
     /// `regionck`) for the given `body_id`, given information about
-    /// the region bounds in scope and so forth. This function must be
-    /// invoked for all relevant body-ids before region inference is
-    /// done (or else an assert will fire).
+    /// the region bounds in scope and so forth.
     ///
     /// See the `region_obligations` field of `InferCtxt` for some
     /// comments about how this function fits into the overall expected
     /// flow of the inferencer. The key point is that it is
     /// invoked after all type-inference variables have been bound --
-    /// towards the end of regionck. This also ensures that the
-    /// region-bound-pairs are available (see comments above regarding
-    /// closures).
-    ///
-    /// # Parameters
-    ///
-    /// - `region_bound_pairs_map`: the set of region bounds implied by
-    ///   the parameters and where-clauses. In particular, each pair
-    ///   `('a, K)` in this list tells us that the bounds in scope
-    ///   indicate that `K: 'a`, where `K` is either a generic
-    ///   parameter like `T` or a projection like `T::Item`.
-    /// - `param_env` is the parameter environment for the enclosing function.
-    /// - `body_id` is the body-id whose region obligations are being
-    ///   processed.
-    #[instrument(level = "debug", skip(self, region_bound_pairs))]
-    pub fn process_registered_region_obligations(
-        &self,
-        region_bound_pairs: &RegionBoundPairs<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) {
+    /// right before lexical region resolution.
+    #[instrument(level = "debug", skip(self, outlives_env))]
+    pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
         assert!(
             !self.in_snapshot.get(),
             "cannot process registered region obligations in a snapshot"
@@ -153,15 +133,16 @@ impl<'tcx> InferCtxt<'tcx> {
         let my_region_obligations = self.take_registered_region_obligations();
 
         for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
-            debug!(
-                "process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}",
-                sup_type, sub_region, origin
-            );
-
+            debug!(?sup_type, ?sub_region, ?origin);
             let sup_type = self.resolve_vars_if_possible(sup_type);
 
-            let outlives =
-                &mut TypeOutlives::new(self, self.tcx, &region_bound_pairs, None, param_env);
+            let outlives = &mut TypeOutlives::new(
+                self,
+                self.tcx,
+                &outlives_env.region_bound_pairs(),
+                None,
+                outlives_env.param_env,
+            );
             let category = origin.to_constraint_category();
             outlives.type_must_outlive(origin, sup_type, sub_region, category);
         }
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index f75344f20b6..b8940e2f045 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -36,9 +36,10 @@ pub trait TraitEngine<'tcx>: 'tcx {
         obligation: PredicateObligation<'tcx>,
     );
 
+    #[must_use]
     fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
 
-    fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>>;
+    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
 
     fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
 
@@ -58,6 +59,7 @@ pub trait TraitEngineExt<'tcx> {
         obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
     );
 
+    #[must_use]
     fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
 }
 
@@ -78,6 +80,6 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
             return errors;
         }
 
-        self.collect_remaining_errors()
+        self.collect_remaining_errors(infcx)
     }
 }
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index dd9b2e548c7..e01b6caf430 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -128,7 +128,11 @@ pub enum FulfillmentErrorCode<'tcx> {
     CodeProjectionError(MismatchedProjectionTypes<'tcx>),
     CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
     CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
-    CodeAmbiguity,
+    CodeAmbiguity {
+        /// Overflow reported from the new solver `-Ztrait-solver=next`, which will
+        /// be reported as an regular error as opposed to a fatal error.
+        overflow: bool,
+    },
 }
 
 impl<'tcx, O> Obligation<'tcx, O> {
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 3a5273b0359..1563d92af0e 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -46,7 +46,8 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
             super::CodeConstEquateError(ref a, ref b) => {
                 write!(f, "CodeConstEquateError({:?}, {:?})", a, b)
             }
-            super::CodeAmbiguity => write!(f, "Ambiguity"),
+            super::CodeAmbiguity { overflow: false } => write!(f, "Ambiguity"),
+            super::CodeAmbiguity { overflow: true } => write!(f, "Overflow"),
             super::CodeCycle(ref cycle) => write!(f, "Cycle({:?})", cycle),
         }
     }
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 322ec31fb2c..b3f4b5cd5e5 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -95,7 +95,7 @@ pub enum TokenKind {
     Literal { kind: LiteralKind, suffix_start: u32 },
 
     /// "'a"
-    Lifetime { starts_with_number: bool, contains_emoji: bool },
+    Lifetime { starts_with_number: bool },
 
     // One-char tokens:
     /// ";"
@@ -632,13 +632,7 @@ impl Cursor<'_> {
             // If the first symbol is valid for identifier, it can be a lifetime.
             // Also check if it's a number for a better error reporting (so '0 will
             // be reported as invalid lifetime and not as unterminated char literal).
-            // We also have to account for potential `'🐱` emojis to avoid reporting
-            // it as an unterminated char literal.
-            is_id_start(self.first())
-                || self.first().is_digit(10)
-                // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode
-                // 5.0, but Unicode is already newer than this.
-                || unic_emoji_char::is_emoji(self.first())
+            is_id_start(self.first()) || self.first().is_digit(10)
         };
 
         if !can_be_a_lifetime {
@@ -651,33 +645,16 @@ impl Cursor<'_> {
             return Literal { kind, suffix_start };
         }
 
-        // Either a lifetime or a character literal.
+        // Either a lifetime or a character literal with
+        // length greater than 1.
 
         let starts_with_number = self.first().is_digit(10);
-        let mut contains_emoji = false;
 
-        // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode
-        // 5.0, but Unicode is already newer than this.
-        if unic_emoji_char::is_emoji(self.first()) {
-            contains_emoji = true;
-        } else {
-            // Skip the literal contents.
-            // First symbol can be a number (which isn't a valid identifier start),
-            // so skip it without any checks.
-            self.bump();
-        }
-        self.eat_while(|c| {
-            if is_id_continue(c) {
-                true
-            // FIXME(#108019): `unic-emoji-char` seems to have data tables only up to Unicode
-            // 5.0, but Unicode is already newer than this.
-            } else if unic_emoji_char::is_emoji(c) {
-                contains_emoji = true;
-                true
-            } else {
-                false
-            }
-        });
+        // Skip the literal contents.
+        // First symbol can be a number (which isn't a valid identifier start),
+        // so skip it without any checks.
+        self.bump();
+        self.eat_while(is_id_continue);
 
         // Check if after skipping literal contents we've met a closing
         // single quote (which means that user attempted to create a
@@ -687,7 +664,7 @@ impl Cursor<'_> {
             let kind = Char { terminated: true };
             Literal { kind, suffix_start: self.pos_within_token() }
         } else {
-            Lifetime { starts_with_number, contains_emoji }
+            Lifetime { starts_with_number }
         }
     }
 
diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs
index 670d64fb983..e4c1787f2cc 100644
--- a/compiler/rustc_lexer/src/tests.rs
+++ b/compiler/rustc_lexer/src/tests.rs
@@ -235,7 +235,7 @@ fn lifetime() {
     check_lexing(
         "'abc",
         expect![[r#"
-            Token { kind: Lifetime { starts_with_number: false, contains_emoji: false }, len: 4 }
+            Token { kind: Lifetime { starts_with_number: false }, len: 4 }
         "#]],
     );
 }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index d9c8142226d..db15b176df0 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -91,7 +91,7 @@ lint_ty_qualified = usage of qualified `ty::{$ty}`
 lint_lintpass_by_hand = implementing `LintPass` by hand
     .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
 
-lint_non_existant_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
+lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
     .help = only existing keywords are allowed in core/std
 
 lint_diag_out_of_impl =
@@ -107,7 +107,7 @@ lint_cstring_ptr = getting the inner pointer of a temporary `CString`
     .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
     .help = for more information, see https://doc.rust-lang.org/reference/destructors.html
 
-lint_multple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
+lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
 
 lint_identifier_non_ascii_char = identifier contains non-ASCII characters
 
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 9c7feadaf87..4ac589c2e10 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -2,7 +2,7 @@
 //! Clippy.
 
 use crate::lints::{
-    BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistantDocKeyword,
+    BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
     QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
 };
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@@ -334,7 +334,7 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
                         cx.emit_spanned_lint(
                             EXISTING_DOC_KEYWORD,
                             attr.span,
-                            NonExistantDocKeyword { keyword },
+                            NonExistentDocKeyword { keyword },
                         );
                     }
                 }
@@ -424,7 +424,7 @@ impl LateLintPass<'_> for Diagnostics {
 }
 
 declare_tool_lint! {
-    /// The `bad_opt_access` lint detects accessing options by field instad of
+    /// The `bad_opt_access` lint detects accessing options by field instead of
     /// the wrapper function.
     pub rustc::BAD_OPT_ACCESS,
     Deny,
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index b83a9665fc0..3eefd1b0e08 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -25,7 +25,7 @@ declare_lint! {
     ///
     /// fn main() {
     ///    #[warn(let_underscore_drop)]
-    ///     // SomeStuct is dropped immediately instead of at end of scope,
+    ///     // SomeStruct is dropped immediately instead of at end of scope,
     ///     // so "Dropping SomeStruct" is printed before "end of main".
     ///     // The order of prints would be reversed if SomeStruct was bound to
     ///     // a name (such as "_foo").
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index a2a7c93a7ca..bb863f09516 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -3,7 +3,7 @@ use crate::{
     fluent_generated as fluent,
     late::unerased_lint_store,
     lints::{
-        DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAtributeLint,
+        DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint,
         RenamedOrRemovedLint, RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion,
     },
 };
@@ -612,7 +612,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                     self.emit_spanned_lint(
                         FORBIDDEN_LINT_GROUPS,
                         src.span().into(),
-                        OverruledAtributeLint {
+                        OverruledAttributeLint {
                             overruled: src.span(),
                             lint_level: level.as_str(),
                             lint_source: src.name(),
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 8ec4c2b3d46..1d5e02369f5 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -806,9 +806,9 @@ pub struct TyQualified {
 pub struct LintPassByHand;
 
 #[derive(LintDiagnostic)]
-#[diag(lint_non_existant_doc_keyword)]
+#[diag(lint_non_existent_doc_keyword)]
 #[help]
-pub struct NonExistantDocKeyword {
+pub struct NonExistentDocKeyword {
     pub keyword: Symbol,
 }
 
@@ -875,7 +875,7 @@ impl AddToDiagnostic for NonBindingLetSub {
 // levels.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_overruled_attribute)]
-pub struct OverruledAtributeLint<'a> {
+pub struct OverruledAttributeLint<'a> {
     #[label]
     pub overruled: Span,
     pub lint_level: &'a str,
@@ -947,7 +947,7 @@ pub struct CStringPtr {
 
 // multiple_supertrait_upcastable.rs
 #[derive(LintDiagnostic)]
-#[diag(lint_multple_supertrait_upcastable)]
+#[diag(lint_multiple_supertrait_upcastable)]
 pub struct MultipleSupertraitUpcastable {
     pub ident: Ident,
 }
@@ -1422,7 +1422,7 @@ pub struct UnusedResult<'a> {
     pub ty: Ty<'a>,
 }
 
-// FIXME(davidtwco): this isn't properly translatable becauses of the
+// FIXME(davidtwco): this isn't properly translatable because of the
 // pre/post strings
 #[derive(LintDiagnostic)]
 #[diag(lint_unused_closure)]
@@ -1433,7 +1433,7 @@ pub struct UnusedClosure<'a> {
     pub post: &'a str,
 }
 
-// FIXME(davidtwco): this isn't properly translatable becauses of the
+// FIXME(davidtwco): this isn't properly translatable because of the
 // pre/post strings
 #[derive(LintDiagnostic)]
 #[diag(lint_unused_generator)]
@@ -1444,7 +1444,7 @@ pub struct UnusedGenerator<'a> {
     pub post: &'a str,
 }
 
-// FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
+// FIXME(davidtwco): this isn't properly translatable because of the pre/post
 // strings
 pub struct UnusedDef<'a, 'b> {
     pub pre: &'a str,
diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs
index f130a98185d..4af879b4e91 100644
--- a/compiler/rustc_lint/src/non_ascii_idents.rs
+++ b/compiler/rustc_lint/src/non_ascii_idents.rs
@@ -250,7 +250,7 @@ impl EarlyLintPass for NonAsciiIdents {
             let latin_augmented_script_set = AugmentedScriptSet::for_char('A');
             script_states.insert(latin_augmented_script_set, ScriptSetUsage::Verified);
 
-            let mut has_suspicous = false;
+            let mut has_suspicious = false;
             for (symbol, &sp) in symbols.iter() {
                 let symbol_str = symbol.as_str();
                 for ch in symbol_str.chars() {
@@ -278,14 +278,14 @@ impl EarlyLintPass for NonAsciiIdents {
                             if !is_potential_mixed_script_confusable_char(ch) {
                                 ScriptSetUsage::Verified
                             } else {
-                                has_suspicous = true;
+                                has_suspicious = true;
                                 ScriptSetUsage::Suspicious(vec![ch], sp)
                             }
                         });
                 }
             }
 
-            if has_suspicous {
+            if has_suspicious {
                 let verified_augmented_script_sets = script_states
                     .iter()
                     .flat_map(|(k, v)| match v {
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 69a8b691ab2..7ea472ed504 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -532,7 +532,7 @@ pub enum BuiltinLintDiagnostics {
     AmbiguousGlobReexports {
         /// The name for which collision(s) have occurred.
         name: String,
-        /// The name space for whihc the collision(s) occurred in.
+        /// The name space for which the collision(s) occurred in.
         namespace: String,
         /// Span where the name is first re-exported.
         first_reexport_span: Span,
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index 21f6a404a01..3cbb2c21e28 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -40,7 +40,6 @@
 
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-#![feature(is_terminal)]
 
 use std::env::{self, VarError};
 use std::fmt::{self, Display};
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index d83a587a86a..a873854f068 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -58,7 +58,7 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
 
     fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
         // We pick the value of the least universe because it is compatible with more variables.
-        // This is *not* neccessary for soundness, but it allows more region variables to be
+        // This is *not* necessary for soundness, but it allows more region variables to be
         // resolved to the said value.
         #[cold]
         fn min_universe<'tcx>(r1: Region<'tcx>, r2: Region<'tcx>) -> Region<'tcx> {
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index a8d71ce030c..89014f62d4d 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -1,6 +1,6 @@
 /// A macro for triggering an ICE.
 /// Calling `bug` instead of panicking will result in a nicer error message and should
-/// therefore be prefered over `panic`/`unreachable` or others.
+/// therefore be preferred over `panic`/`unreachable` or others.
 ///
 /// If you have a span available, you should use [`span_bug`] instead.
 ///
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
index 9a02bc0cc15..dcb56a1755e 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -63,7 +63,7 @@ impl InitMask {
     }
 
     /// Sets a specified range to a value. If the range is out-of-bounds, the mask will grow to
-    /// accomodate it entirely.
+    /// accommodate it entirely.
     pub fn set_range(&mut self, range: AllocRange, new_state: bool) {
         let start = range.start;
         let end = range.end();
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index ddd3f394358..318f93e12b5 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -14,7 +14,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 #[derive(HashStable)]
 pub struct ProvenanceMap<Prov = AllocId> {
     /// Provenance in this map applies from the given offset for an entire pointer-size worth of
-    /// bytes. Two entires in this map are always at least a pointer size apart.
+    /// bytes. Two entries in this map are always at least a pointer size apart.
     ptrs: SortedMap<Size, Prov>,
     /// Provenance in this map only applies to the given single byte.
     /// This map is disjoint from the previous. It will always be empty when
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 56755e588cb..2ea8602af12 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1115,6 +1115,11 @@ pub struct VarDebugInfo<'tcx> {
 
     /// Where the data for this user variable is to be found.
     pub value: VarDebugInfoContents<'tcx>,
+
+    /// When present, indicates what argument number this variable is in the function that it
+    /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
+    /// argument number in the original function before it was inlined.
+    pub argument_index: Option<u16>,
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 6c4ea065abe..0a9fcd898b9 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -832,6 +832,7 @@ macro_rules! make_mir_visitor {
                     name: _,
                     source_info,
                     value,
+                    argument_index: _,
                 } = var_debug_info;
 
                 self.visit_source_info(source_info);
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 24d98665a7b..7d9aea02289 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -37,7 +37,7 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
 #[inline(always)]
 pub fn restore<T: EraseType>(value: Erase<T>) -> T {
     let value: Erased<<T as EraseType>::Result> = value;
-    // SAFETY: Due to the use of impl Trait in `Erase` the only way to safetly create an instance
+    // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance
     // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
     // the right size.
     unsafe { transmute_copy(&value.data) }
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 3b0eec683de..23b28ac5ca9 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -26,7 +26,7 @@ pub trait Key: Sized {
     //
     //      ...But r-a doesn't support them yet and using a default here causes r-a to not infer
     //      return types of queries which is very annoying. Thus, until r-a support associated
-    //      type defaults, plese restrain from using them here <3
+    //      type defaults, please restrain from using them here <3
     //
     //      r-a issue: <https://github.com/rust-lang/rust-analyzer/issues/13693>
     type CacheSelector;
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index ef9f91f8859..7a5a1603585 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -97,7 +97,7 @@ rustc_queries! {
 
     /// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any.
     ///
-    /// Definitions that were generated with no HIR, would be feeded to return `None`.
+    /// Definitions that were generated with no HIR, would be fed to return `None`.
     query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
         desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
         feedable
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 2328a1324fc..195d951f9f3 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1226,10 +1226,11 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
         | AvrNonBlockingInterrupt
         | CCmseNonSecureCall
         | Wasm
-        | RustIntrinsic
         | PlatformIntrinsic
         | Unadjusted => false,
-        Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind,
+        Rust | RustCall | RustCold | RustIntrinsic => {
+            tcx.sess.panic_strategy() == PanicStrategy::Unwind
+        }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index bc0ccc1ebc3..72caadaf661 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1347,7 +1347,7 @@ pub trait PrettyPrinter<'tcx>:
                             p!(write("{}::{}", self.tcx().crate_name(def.did.krate), self.tcx().def_path(def.did).to_string_no_crate_verbose()))
                         }
                     }
-                    defkind => bug!("`{:?}` has unexpcted defkind {:?}", ct, defkind),
+                    defkind => bug!("`{:?}` has unexpected defkind {:?}", ct, defkind),
                 }
             }
             ty::ConstKind::Infer(infer_ct) => {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 24cbe8e8281..96c1577d52b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use crate::ty::visit::ValidateBoundVars;
 use crate::ty::InferTy::*;
 use crate::ty::{
-    self, AdtDef, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
-    TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+    self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
+    TypeVisitableExt, TypeVisitor,
 };
 use crate::ty::{List, ParamEnv};
 use hir::def::DefKind;
@@ -1156,81 +1156,6 @@ where
     }
 }
 
-struct SkipBindersAt<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    index: ty::DebruijnIndex,
-}
-
-impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> {
-    type Error = ();
-
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
-    where
-        T: ty::TypeFoldable<TyCtxt<'tcx>>,
-    {
-        self.index.shift_in(1);
-        let value = t.try_map_bound(|t| t.try_fold_with(self));
-        self.index.shift_out(1);
-        value
-    }
-
-    fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        if !ty.has_escaping_bound_vars() {
-            Ok(ty)
-        } else if let ty::Bound(index, bv) = *ty.kind() {
-            if index == self.index {
-                Err(())
-            } else {
-                Ok(self.interner().mk_bound(index.shifted_out(1), bv))
-            }
-        } else {
-            ty.try_super_fold_with(self)
-        }
-    }
-
-    fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
-        if !r.has_escaping_bound_vars() {
-            Ok(r)
-        } else if let ty::ReLateBound(index, bv) = r.kind() {
-            if index == self.index {
-                Err(())
-            } else {
-                Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv))
-            }
-        } else {
-            r.try_super_fold_with(self)
-        }
-    }
-
-    fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
-        if !ct.has_escaping_bound_vars() {
-            Ok(ct)
-        } else if let ty::ConstKind::Bound(index, bv) = ct.kind() {
-            if index == self.index {
-                Err(())
-            } else {
-                Ok(self.interner().mk_const(
-                    ty::ConstKind::Bound(index.shifted_out(1), bv),
-                    ct.ty().try_fold_with(self)?,
-                ))
-            }
-        } else {
-            ct.try_super_fold_with(self)
-        }
-    }
-
-    fn try_fold_predicate(
-        &mut self,
-        p: ty::Predicate<'tcx>,
-    ) -> Result<ty::Predicate<'tcx>, Self::Error> {
-        if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) }
-    }
-}
-
 /// Represents the projection of an associated type.
 ///
 /// For a projection, this would be `<Ty as Trait<...>>::N`.
@@ -1621,19 +1546,24 @@ impl<'tcx> Region<'tcx> {
 
     pub fn get_name(self) -> Option<Symbol> {
         if self.has_name() {
-            let name = match *self {
+            match *self {
                 ty::ReEarlyBound(ebr) => Some(ebr.name),
                 ty::ReLateBound(_, br) => br.kind.get_name(),
                 ty::ReFree(fr) => fr.bound_region.get_name(),
                 ty::ReStatic => Some(kw::StaticLifetime),
                 ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(),
                 _ => None,
-            };
-
-            return name;
+            }
+        } else {
+            None
         }
+    }
 
-        None
+    pub fn get_name_or_anon(self) -> Symbol {
+        match self.get_name() {
+            Some(name) => name,
+            None => sym::anon,
+        }
     }
 
     /// Is this region named by the user?
@@ -1767,10 +1697,10 @@ impl<'tcx> Region<'tcx> {
         matches!(self.kind(), ty::ReVar(_))
     }
 
-    pub fn as_var(self) -> Option<RegionVid> {
+    pub fn as_var(self) -> RegionVid {
         match self.kind() {
-            ty::ReVar(vid) => Some(vid),
-            _ => None,
+            ty::ReVar(vid) => vid,
+            _ => bug!("expected region {:?} to be of kind ReVar", self),
         }
     }
 }
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 54028dfe87b..931fe1b2433 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -148,6 +148,11 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                     )),
                 )
             },
+            @call("mir_offset", args) => {
+                let ptr = self.parse_operand(args[0])?;
+                let offset = self.parse_operand(args[1])?;
+                Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
+            },
             @call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
             ExprKind::Borrow { borrow_kind, arg } => Ok(
                 Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 2d52102db2c..4926ff85de3 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -2242,6 +2242,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             name,
             source_info: debug_source_info,
             value: VarDebugInfoContents::Place(for_arm_body.into()),
+            argument_index: None,
         });
         let locals = if has_guard.0 {
             let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
@@ -2260,6 +2261,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 name,
                 source_info: debug_source_info,
                 value: VarDebugInfoContents::Place(ref_for_guard.into()),
+                argument_index: None,
             });
             LocalsForNode::ForGuard { ref_for_guard, for_arm_body }
         } else {
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 415f5b1b1e1..bc50bcbc3d0 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -811,6 +811,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     name,
                     source_info: SourceInfo::outermost(captured_place.var_ident.span),
                     value: VarDebugInfoContents::Place(use_place),
+                    argument_index: None,
                 });
 
                 let capture = Capture { captured_place, use_place, mutability };
@@ -827,7 +828,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr: &Expr<'tcx>,
     ) -> BlockAnd<()> {
         // Allocate locals for the function arguments
-        for param in arguments.iter() {
+        for (argument_index, param) in arguments.iter().enumerate() {
             let source_info =
                 SourceInfo::outermost(param.pat.as_ref().map_or(self.fn_span, |pat| pat.span));
             let arg_local =
@@ -839,6 +840,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     name,
                     source_info,
                     value: VarDebugInfoContents::Place(arg_local.into()),
+                    argument_index: Some(argument_index as u16 + 1),
                 });
             }
         }
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 431c3255ab2..43e787db41a 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -593,7 +593,7 @@ pub struct MultipleMutBorrows {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub occurences: Vec<Conflict>,
+    pub occurrences: Vec<Conflict>,
 }
 
 #[derive(Diagnostic)]
@@ -602,7 +602,7 @@ pub struct AlreadyBorrowed {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub occurences: Vec<Conflict>,
+    pub occurrences: Vec<Conflict>,
 }
 
 #[derive(Diagnostic)]
@@ -611,7 +611,7 @@ pub struct AlreadyMutBorrowed {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub occurences: Vec<Conflict>,
+    pub occurrences: Vec<Conflict>,
 }
 
 #[derive(Diagnostic)]
@@ -620,7 +620,7 @@ pub struct MovedWhileBorrowed {
     #[primary_span]
     pub span: Span,
     #[subdiagnostic]
-    pub occurences: Vec<Conflict>,
+    pub occurrences: Vec<Conflict>,
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 0882b473f10..bac46db2b1e 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -966,30 +966,30 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>,
     let report_mut_ref = !conflicts_mut_ref.is_empty();
     let report_move_conflict = !conflicts_move.is_empty();
 
-    let mut occurences = match mut_outer {
+    let mut occurrences = match mut_outer {
         Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }],
         Mutability::Not => vec![Conflict::Ref { span: pat.span, name }],
     };
-    occurences.extend(conflicts_mut_mut);
-    occurences.extend(conflicts_mut_ref);
-    occurences.extend(conflicts_move);
+    occurrences.extend(conflicts_mut_mut);
+    occurrences.extend(conflicts_mut_ref);
+    occurrences.extend(conflicts_move);
 
     // Report errors if any.
     if report_mut_mut {
         // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
-        sess.emit_err(MultipleMutBorrows { span: pat.span, occurences });
+        sess.emit_err(MultipleMutBorrows { span: pat.span, occurrences });
     } else if report_mut_ref {
         // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
         match mut_outer {
             Mutability::Mut => {
-                sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurences });
+                sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurrences });
             }
             Mutability::Not => {
-                sess.emit_err(AlreadyBorrowed { span: pat.span, occurences });
+                sess.emit_err(AlreadyBorrowed { span: pat.span, occurrences });
             }
         };
     } else if report_move_conflict {
         // Report by-ref and by-move conflicts, e.g. `ref x @ y`.
-        sess.emit_err(MovedWhileBorrowed { span: pat.span, occurences });
+        sess.emit_err(MovedWhileBorrowed { span: pat.span, occurrences });
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index c188105eae8..707729f8f21 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -394,8 +394,8 @@ where
     ) -> io::Result<()> {
         let diffs = StateDiffCollector::run(body, block, self.results.results(), self.style);
 
-        let mut befores = diffs.before.map(|v| v.into_iter());
-        let mut afters = diffs.after.into_iter();
+        let mut diffs_before = diffs.before.map(|v| v.into_iter());
+        let mut diffs_after = diffs.after.into_iter();
 
         let next_in_dataflow_order = |it: &mut std::vec::IntoIter<_>| {
             if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
@@ -405,8 +405,8 @@ where
             let statement_str = format!("{statement:?}");
             let index_str = format!("{i}");
 
-            let after = next_in_dataflow_order(&mut afters);
-            let before = befores.as_mut().map(next_in_dataflow_order);
+            let after = next_in_dataflow_order(&mut diffs_after);
+            let before = diffs_before.as_mut().map(next_in_dataflow_order);
 
             self.write_row(w, &index_str, &statement_str, |_this, w, fmt| {
                 if let Some(before) = before {
@@ -417,11 +417,11 @@ where
             })?;
         }
 
-        let after = next_in_dataflow_order(&mut afters);
-        let before = befores.as_mut().map(next_in_dataflow_order);
+        let after = next_in_dataflow_order(&mut diffs_after);
+        let before = diffs_before.as_mut().map(next_in_dataflow_order);
 
-        assert!(afters.is_empty());
-        assert!(befores.as_ref().map_or(true, ExactSizeIterator::is_empty));
+        assert!(diffs_after.is_empty());
+        assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty));
 
         let terminator = body[block].terminator();
         let mut terminator_str = String::new();
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 8086a4557b7..c76dc56065c 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -1,5 +1,6 @@
 use crate::MirPass;
 use rustc_hir::def_id::DefId;
+use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::*;
 use rustc_middle::mir::{
@@ -17,6 +18,12 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment {
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        // This pass emits new panics. If for whatever reason we do not have a panic
+        // implementation, running this pass may cause otherwise-valid code to not compile.
+        if tcx.lang_items().get(LangItem::PanicImpl).is_none() {
+            return;
+        }
+
         let basic_blocks = body.basic_blocks.as_mut();
         let local_decls = &mut body.local_decls;
 
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 811935aa990..39164917770 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -83,7 +83,7 @@
 //!   that ever have their address taken. Of course that requires actually having alias analysis
 //!   (and a model to build it on), so this might be a bit of a ways off.
 //!
-//! * Various perf improvents. There are a bunch of comments in here marked `PERF` with ideas for
+//! * Various perf improvements. There are a bunch of comments in here marked `PERF` with ideas for
 //!   how to do things more efficiently. However, the complexity of the pass as a whole should be
 //!   kept in mind.
 //!
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 159780319ba..4c4423721fb 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1556,6 +1556,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         body.arg_count = 2; // self, resume arg
         body.spread_arg = None;
 
+        // The original arguments to the function are no longer arguments, mark them as such.
+        // Otherwise they'll conflict with our new arguments, which although they don't have
+        // argument_index set, will get emitted as unnamed arguments.
+        for var in &mut body.var_debug_info {
+            var.argument_index = None;
+        }
+
         body.generator.as_mut().unwrap().yield_ty = None;
         body.generator.as_mut().unwrap().generator_layout = Some(layout);
 
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index d4b1cfe4337..bd1724bf842 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -99,7 +99,7 @@ where
                 //
                 // This generates a `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]`, which allows us or LLVM to
                 // turn it into just `x` later. Without the unreachable, such a transformation would be illegal.
-                // If the otherwise branch is unreachable, we can delete all other unreacahble targets, as they will
+                // If the otherwise branch is unreachable, we can delete all other unreachable targets, as they will
                 // still point to the unreachable and therefore not lose reachability information.
                 let reachable_iter = targets.iter().filter(|(_, bb)| !is_unreachable(*bb));
 
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 7ac1c9e057e..18aa0742c09 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -474,7 +474,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
     (tcx.arena.alloc(mono_items), codegen_units)
 }
 
-/// Outputs stats about instantation counts and estimated size, per `MonoItem`'s
+/// Outputs stats about instantiation counts and estimated size, per `MonoItem`'s
 /// def, to a file in the given output directory.
 fn dump_mono_items_stats<'tcx>(
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index e21bbd0217b..f11d0ed0f01 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -738,3 +738,7 @@ parse_box_syntax_removed = `box_syntax` has been removed
 parse_bad_return_type_notation_output =
     return type not allowed with return type notation
     .suggestion = remove the return type
+
+parse_bad_return_type_notation_dotdot =
+    return type notation uses `()` instead of `(..)` for elided arguments
+    .suggestion = remove the `..`
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index aead216b61c..069217165fa 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2324,3 +2324,11 @@ pub(crate) struct BadReturnTypeNotationOutput {
     #[suggestion(code = "", applicability = "maybe-incorrect")]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_bad_return_type_notation_dotdot)]
+pub(crate) struct BadReturnTypeNotationDotDot {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "maybe-incorrect")]
+    pub span: Span,
+}
diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs
index c4b9fdc81c5..9e6d27bf036 100644
--- a/compiler/rustc_parse/src/lexer/diagnostics.rs
+++ b/compiler/rustc_parse/src/lexer/diagnostics.rs
@@ -21,7 +21,7 @@ pub struct TokenTreeDiagInfo {
     pub matching_block_spans: Vec<(Span, Span)>,
 }
 
-pub fn same_identation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) -> bool {
+pub fn same_indentation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) -> bool {
     match (sm.span_to_margin(open_sp), sm.span_to_margin(close_sp)) {
         (Some(open_padding), Some(close_padding)) => open_padding == close_padding,
         _ => false,
@@ -67,13 +67,13 @@ pub fn report_suspicious_mismatch_block(
     let mut matched_spans: Vec<(Span, bool)> = diag_info
         .matching_block_spans
         .iter()
-        .map(|&(open, close)| (open.with_hi(close.lo()), same_identation_level(sm, open, close)))
+        .map(|&(open, close)| (open.with_hi(close.lo()), same_indentation_level(sm, open, close)))
         .collect();
 
     // sort by `lo`, so the large block spans in the front
     matched_spans.sort_by_key(|(span, _)| span.lo());
 
-    // We use larger block whose identation is well to cover those inner mismatched blocks
+    // We use larger block whose indentation is well to cover those inner mismatched blocks
     // O(N^2) here, but we are on error reporting path, so it is fine
     for i in 0..matched_spans.len() {
         let (block_span, same_ident) = matched_spans[i];
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index e41d0f7047b..9e856c9f212 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -223,21 +223,16 @@ impl<'a> StringReader<'a> {
                     };
                     token::Literal(token::Lit { kind, symbol, suffix })
                 }
-                rustc_lexer::TokenKind::Lifetime { starts_with_number, contains_emoji } => {
+                rustc_lexer::TokenKind::Lifetime { starts_with_number } => {
                     // Include the leading `'` in the real identifier, for macro
                     // expansion purposes. See #12512 for the gory details of why
                     // this is necessary.
                     let lifetime_name = self.str_from(start);
                     if starts_with_number {
                         let span = self.mk_sp(start, self.pos);
-                        let mut diag = self.sess.struct_err("lifetimes or labels cannot start with a number");
+                        let mut diag = self.sess.struct_err("lifetimes cannot start with a number");
                         diag.set_span(span);
                         diag.stash(span, StashKey::LifetimeIsChar);
-                    } else if contains_emoji {
-                        let span = self.mk_sp(start, self.pos);
-                        let mut diag = self.sess.struct_err("lifetimes or labels cannot contain emojis");
-                        diag.set_span(span);
-                        diag.stash(span, StashKey::LifetimeContainsEmoji);
                     }
                     let ident = Symbol::intern(lifetime_name);
                     token::Lifetime(ident)
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 36fd1e37d65..7c2c0895193 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -1,5 +1,5 @@
 use super::diagnostics::report_suspicious_mismatch_block;
-use super::diagnostics::same_identation_level;
+use super::diagnostics::same_indentation_level;
 use super::diagnostics::TokenTreeDiagInfo;
 use super::{StringReader, UnmatchedDelim};
 use rustc_ast::token::{self, Delimiter, Token};
@@ -153,7 +153,7 @@ impl<'a> TokenTreesReader<'a> {
                         unclosed_delimiter = Some(sp);
                     };
                     for (brace, brace_span) in &self.diag_info.open_braces {
-                        if same_identation_level(&sm, self.token.span, *brace_span)
+                        if same_indentation_level(&sm, self.token.span, *brace_span)
                             && brace == &close_delim
                         {
                             // high likelihood of these two corresponding
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index c4605e63cf3..03c82fbd329 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2767,7 +2767,7 @@ impl<'a> Parser<'a> {
                     (token::DotDotEq, token::Gt)
                 ) {
                     // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`,
-                    // so we supress the error here
+                    // so we suppress the error here
                     err.delay_as_bug();
                     this.bump();
                 } else {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index f1c9f0109f8..c25c23d849f 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -290,16 +290,17 @@ impl<'a> Parser<'a> {
                     })?;
                     let span = lo.to(self.prev_token.span);
                     AngleBracketedArgs { args, span }.into()
-                } else if self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
+                } else if self.may_recover()
+                    && self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
                     // FIXME(return_type_notation): Could also recover `...` here.
                     && self.look_ahead(1, |tok| tok.kind == token::DotDot)
                 {
-                    let lo = self.token.span;
                     self.bump();
+                    self.sess
+                        .emit_err(errors::BadReturnTypeNotationDotDot { span: self.token.span });
                     self.bump();
                     self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
                     let span = lo.to(self.prev_token.span);
-                    self.sess.gated_spans.gate(sym::return_type_notation, span);
 
                     if self.eat_noexpect(&token::RArrow) {
                         let lo = self.prev_token.span;
@@ -308,7 +309,13 @@ impl<'a> Parser<'a> {
                             .emit_err(errors::BadReturnTypeNotationOutput { span: lo.to(ty.span) });
                     }
 
-                    P(GenericArgs::ReturnTypeNotation(span))
+                    ParenthesizedArgs {
+                        span,
+                        inputs: ThinVec::new(),
+                        inputs_span: span,
+                        output: ast::FnRetTy::Default(self.prev_token.span.shrink_to_hi()),
+                    }
+                    .into()
                 } else {
                     // `(T, U) -> R`
                     let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
@@ -566,13 +573,13 @@ impl<'a> Parser<'a> {
                     };
 
                     let span = lo.to(self.prev_token.span);
-
                     // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
                     if let AssocConstraintKind::Bound { .. } = kind {
-                        if gen_args.as_ref().map_or(false, |args| {
-                            matches!(args, GenericArgs::ReturnTypeNotation(..))
-                        }) {
-                            // This is already gated in `parse_path_segment`
+                        if let Some(ast::GenericArgs::Parenthesized(args)) = &gen_args
+                            && args.inputs.is_empty()
+                            && matches!(args.output, ast::FnRetTy::Default(..))
+                        {
+                            self.sess.gated_spans.gate(sym::return_type_notation, span);
                         } else {
                             self.sess.gated_spans.gate(sym::associated_type_bounds, span);
                         }
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 1c5410c5658..7de84db211e 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -909,7 +909,7 @@ fn find_width_map_from_snippet(
     // Strip quotes.
     let snippet = &snippet[1..snippet.len() - 1];
 
-    // Macros like `println` add a newline at the end. That technically doens't make them "literals" anymore, but it's fine
+    // Macros like `println` add a newline at the end. That technically doesn't make them "literals" anymore, but it's fine
     // since we will never need to point our spans there, so we lie about it here by ignoring it.
     // Since there might actually be newlines in the source code, we need to normalize away all trailing newlines.
     // If we only trimmed it off the input, `format!("\n")` would cause a mismatch as here we they actually match up.
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 91483fe3de7..5cfe691df17 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -700,6 +700,13 @@ impl<'tcx> DeadVisitor<'tcx> {
             .collect();
 
         let descr = tcx.def_descr(first_id.to_def_id());
+        // `impl` blocks are "batched" and (unlike other batching) might
+        // contain different kinds of associated items.
+        let descr = if dead_codes.iter().any(|did| tcx.def_descr(did.to_def_id()) != descr) {
+            "associated item"
+        } else {
+            descr
+        };
         let num = dead_codes.len();
         let multiple = num > 6;
         let name_list = names.into();
@@ -712,12 +719,12 @@ impl<'tcx> DeadVisitor<'tcx> {
 
         let parent_info = if let Some(parent_item) = parent_item {
             let parent_descr = tcx.def_descr(parent_item.to_def_id());
-            Some(ParentInfo {
-                num,
-                descr,
-                parent_descr,
-                span: tcx.def_ident_span(parent_item).unwrap(),
-            })
+            let span = if let DefKind::Impl { .. } = tcx.def_kind(parent_item) {
+                tcx.def_span(parent_item)
+            } else {
+                tcx.def_ident_span(parent_item).unwrap()
+            };
+            Some(ParentInfo { num, descr, parent_descr, span })
         } else {
             None
         };
@@ -800,16 +807,7 @@ impl<'tcx> DeadVisitor<'tcx> {
     }
 
     fn check_definition(&mut self, def_id: LocalDefId) {
-        if self.live_symbols.contains(&def_id) {
-            return;
-        }
-        if has_allow_dead_code_or_lang_attr(self.tcx, def_id) {
-            return;
-        }
-        let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
-            return
-        };
-        if name.as_str().starts_with('_') {
+        if self.is_live_code(def_id) {
             return;
         }
         match self.tcx.def_kind(def_id) {
@@ -827,6 +825,18 @@ impl<'tcx> DeadVisitor<'tcx> {
             _ => {}
         }
     }
+
+    fn is_live_code(&self, def_id: LocalDefId) -> bool {
+        // if we cannot get a name for the item, then we just assume that it is
+        // live. I mean, we can't really emit a lint.
+        let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
+            return true;
+        };
+
+        self.live_symbols.contains(&def_id)
+            || has_allow_dead_code_or_lang_attr(self.tcx, def_id)
+            || name.as_str().starts_with('_')
+    }
 }
 
 fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
@@ -836,6 +846,22 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
     let module_items = tcx.hir_module_items(module);
 
     for item in module_items.items() {
+        if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind {
+            let mut dead_items = Vec::new();
+            for item in impl_item.items {
+                let did = item.id.owner_id.def_id;
+                if !visitor.is_live_code(did) {
+                    dead_items.push(did)
+                }
+            }
+            visitor.warn_multiple_dead_codes(
+                &dead_items,
+                "used",
+                Some(item.owner_id.def_id),
+                false,
+            );
+        }
+
         if !live_symbols.contains(&item.owner_id.def_id) {
             let parent = tcx.local_parent(item.owner_id.def_id);
             if parent != module && !live_symbols.contains(&parent) {
@@ -900,10 +926,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
         }
     }
 
-    for impl_item in module_items.impl_items() {
-        visitor.check_definition(impl_item.owner_id.def_id);
-    }
-
     for foreign_item in module_items.foreign_items() {
         visitor.check_definition(foreign_item.owner_id.def_id);
     }
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 9418f3cd322..3942a73befd 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -8,8 +8,6 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
-    tcx.dep_graph.assert_ignored();
-
     if tcx.sess.opts.unstable_opts.hir_stats {
         crate::hir_stats::print_hir_stats(tcx);
     }
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index ce44f709f3b..47e032758f2 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -666,7 +666,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     fn visit_generic_args(&mut self, g: &'v ast::GenericArgs) {
         record_variants!(
             (self, g, g, Id::None, ast, GenericArgs, GenericArgs),
-            [AngleBracketed, Parenthesized, ReturnTypeNotation]
+            [AngleBracketed, Parenthesized]
         );
         ast_visit::walk_generic_args(self, g)
     }
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 534d13b1ae0..a9a2e6dd04c 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -143,7 +143,7 @@ impl<K: DepKind> DepGraph<K> {
         assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
 
         // Instantiate a dependy-less red node only once for anonymous queries.
-        let (_red_node_index, _prev_and_index) = current.intern_node(
+        let (red_node_index, red_node_prev_index_and_color) = current.intern_node(
             profiler,
             &prev_graph,
             DepNode { kind: DepKind::RED, hash: Fingerprint::ZERO.into() },
@@ -151,8 +151,21 @@ impl<K: DepKind> DepGraph<K> {
             None,
             false,
         );
-        assert_eq!(_red_node_index, DepNodeIndex::FOREVER_RED_NODE);
-        assert!(matches!(_prev_and_index, None | Some((_, DepNodeColor::Red))));
+        assert_eq!(red_node_index, DepNodeIndex::FOREVER_RED_NODE);
+        match red_node_prev_index_and_color {
+            None => {
+                // This is expected when we have no previous compilation session.
+                assert!(prev_graph_node_count == 0);
+            }
+            Some((prev_red_node_index, DepNodeColor::Red)) => {
+                assert_eq!(prev_red_node_index.as_usize(), red_node_index.as_usize());
+                colors.insert(prev_red_node_index, DepNodeColor::Red);
+            }
+            Some((_, DepNodeColor::Green(_))) => {
+                // There must be a logic error somewhere if we hit this branch.
+                panic!("DepNodeIndex::FOREVER_RED_NODE evaluated to DepNodeColor::Green")
+            }
+        }
 
         DepGraph {
             data: Some(Lrc::new(DepGraphData {
@@ -353,10 +366,8 @@ impl<K: DepKind> DepGraphData<K> {
             }))
         };
 
-        let task_deps_ref = match &task_deps {
-            Some(deps) => TaskDepsRef::Allow(deps),
-            None => TaskDepsRef::Ignore,
-        };
+        let task_deps_ref =
+            task_deps.as_ref().map(TaskDepsRef::Allow).unwrap_or(TaskDepsRef::EvalAlways);
 
         let result = K::with_deps(task_deps_ref, || task(cx, arg));
         let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
@@ -461,6 +472,11 @@ impl<K: DepKind> DepGraph<K> {
             K::read_deps(|task_deps| {
                 let mut task_deps = match task_deps {
                     TaskDepsRef::Allow(deps) => deps.lock(),
+                    TaskDepsRef::EvalAlways => {
+                        // We don't need to record dependencies of eval_always
+                        // queries. They are re-evaluated unconditionally anyway.
+                        return;
+                    }
                     TaskDepsRef::Ignore => return,
                     TaskDepsRef::Forbid => {
                         panic!("Illegal read of: {dep_node_index:?}")
@@ -563,7 +579,10 @@ impl<K: DepKind> DepGraph<K> {
             let mut edges = SmallVec::new();
             K::read_deps(|task_deps| match task_deps {
                 TaskDepsRef::Allow(deps) => edges.extend(deps.lock().reads.iter().copied()),
-                TaskDepsRef::Ignore => {} // During HIR lowering, we have no dependencies.
+                TaskDepsRef::EvalAlways => {
+                    edges.push(DepNodeIndex::FOREVER_RED_NODE);
+                }
+                TaskDepsRef::Ignore => {}
                 TaskDepsRef::Forbid => {
                     panic!("Cannot summarize when dependencies are not recorded.")
                 }
@@ -1356,10 +1375,13 @@ pub enum TaskDepsRef<'a, K: DepKind> {
     /// `TaskDeps`. This is used when executing a 'normal' query
     /// (no `eval_always` modifier)
     Allow(&'a Lock<TaskDeps<K>>),
-    /// New dependencies are ignored. This is used when
-    /// executing an `eval_always` query, since there's no
+    /// This is used when executing an `eval_always` query. We don't
     /// need to track dependencies for a query that's always
-    /// re-executed. This is also used for `dep_graph.with_ignore`
+    /// re-executed -- but we need to know that this is an `eval_always`
+    /// query in order to emit dependencies to `DepNodeIndex::FOREVER_RED_NODE`
+    /// when directly feeding other queries.
+    EvalAlways,
+    /// New dependencies are ignored. This is also used for `dep_graph.with_ignore`.
     Ignore,
     /// Any attempt to add new dependencies will cause a panic.
     /// This is used when decoding a query result from disk,
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 2628f247c54..01f002c9408 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -42,7 +42,7 @@ resolve_try_adding_local_generic_param_on_method =
     try adding a local generic parameter in this method instead
 
 resolve_help_try_using_local_generic_param =
-    try using a local generic paramter instead
+    try using a local generic parameter instead
 
 resolve_name_is_already_used_as_generic_parameter =
     the name `{$name}` is already used for a generic parameter in this item's generic parameters
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 31ac3f1c151..90a2fa89cd2 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -598,7 +598,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     /// The current set of local scopes for types and values.
     ribs: PerNS<Vec<Rib<'a>>>,
 
-    /// Previous poped `rib`, only used for diagnostic.
+    /// Previous popped `rib`, only used for diagnostic.
     last_block_rib: Option<Rib<'a>>,
 
     /// The current set of local scopes, for labels.
@@ -1116,7 +1116,6 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                         }
                     }
                 }
-                GenericArgs::ReturnTypeNotation(_span) => {}
             }
         }
     }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 2ed871a4f77..b820d56b8af 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -312,7 +312,6 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
                     (args.span, found_lifetimes)
                 }
                 GenericArgs::Parenthesized(args) => (args.span, true),
-                GenericArgs::ReturnTypeNotation(span) => (*span, false),
             }
         } else {
             (DUMMY_SP, false)
@@ -1654,7 +1653,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 misc2: AmbiguityErrorMisc::None,
             };
             if !self.matches_previous_ambiguity_error(&ambiguity_error) {
-                // avoid dumplicated span information to be emitt out
+                // avoid duplicated span information to be emitt out
                 self.ambiguity_errors.push(ambiguity_error);
             }
         }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index acfb36c97d0..79eb31bb105 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -222,7 +222,7 @@ impl LinkerPluginLto {
 }
 
 /// The different settings that can be enabled via the `-Z location-detail` flag.
-#[derive(Clone, PartialEq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Hash, Debug)]
 pub struct LocationDetail {
     pub file: bool,
     pub line: bool,
diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs
index 9fe9e3a7a5f..259f4238654 100644
--- a/compiler/rustc_span/src/edit_distance.rs
+++ b/compiler/rustc_span/src/edit_distance.rs
@@ -219,7 +219,7 @@ fn find_best_match_for_name_impl(
     }
 
     // We have a tie among several candidates, try to select the best among them ignoring substrings.
-    // For example, the candidates list `force_capture`, `capture`, and user inputed `forced_capture`,
+    // For example, the candidates list `force_capture`, `capture`, and user inputted `forced_capture`,
     // we select `force_capture` with a extra round of edit distance calculation.
     if next_candidates.len() > 1 {
         debug_assert!(use_substring_score);
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 0bb42a3a71f..08c4414034a 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1207,7 +1207,7 @@ impl HygieneEncodeContext {
         // a `SyntaxContext` that we haven't seen before
         while !self.latest_ctxts.lock().is_empty() || !self.latest_expns.lock().is_empty() {
             debug!(
-                "encode_hygiene: Serializing a round of {:?} SyntaxContextDatas: {:?}",
+                "encode_hygiene: Serializing a round of {:?} SyntaxContextData: {:?}",
                 self.latest_ctxts.lock().len(),
                 self.latest_ctxts
             );
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7affad9aa01..6bfae377152 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -357,6 +357,7 @@ symbols! {
         always,
         and,
         and_then,
+        anon,
         anonymous_lifetime_in_impl_trait,
         any,
         append_const_msg,
@@ -800,6 +801,7 @@ symbols! {
         ignore,
         impl_header_lifetime_elision,
         impl_lint_pass,
+        impl_trait_in_assoc_type,
         impl_trait_in_bindings,
         impl_trait_in_fn_trait_return,
         impl_trait_projections,
@@ -1173,7 +1175,9 @@ symbols! {
         reg32,
         reg64,
         reg_abcd,
+        reg_addr,
         reg_byte,
+        reg_data,
         reg_iw,
         reg_nonzero,
         reg_pair,
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index a0730fbb650..57011aa8a14 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -755,7 +755,7 @@ impl FromStr for Conv {
             "AmdGpuKernel" => Ok(Conv::AmdGpuKernel),
             "AvrInterrupt" => Ok(Conv::AvrInterrupt),
             "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt),
-            _ => Err(format!("'{s}' is not a valid value for entry function call convetion.")),
+            _ => Err(format!("'{s}' is not a valid value for entry function call convention.")),
         }
     }
 }
diff --git a/compiler/rustc_target/src/asm/m68k.rs b/compiler/rustc_target/src/asm/m68k.rs
new file mode 100644
index 00000000000..8c857550cf2
--- /dev/null
+++ b/compiler/rustc_target/src/asm/m68k.rs
@@ -0,0 +1,81 @@
+use super::{InlineAsmArch, InlineAsmType};
+use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
+use std::fmt;
+
+def_reg_class! {
+    M68k M68kInlineAsmRegClass {
+        reg,
+        reg_addr,
+        reg_data,
+    }
+}
+
+impl M68kInlineAsmRegClass {
+    pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
+        &[]
+    }
+
+    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
+        None
+    }
+
+    pub fn suggest_modifier(
+        self,
+        _arch: InlineAsmArch,
+        _ty: InlineAsmType,
+    ) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn supported_types(
+        self,
+        _arch: InlineAsmArch,
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
+        match self {
+            Self::reg => types! { _: I16, I32; },
+            Self::reg_data => types! { _: I8, I16, I32; },
+            Self::reg_addr => types! { _: I16, I32; },
+        }
+    }
+}
+
+def_regs! {
+    M68k M68kInlineAsmReg M68kInlineAsmRegClass {
+        d0: reg, reg_data = ["d0"],
+        d1: reg, reg_data = ["d1"],
+        d2: reg, reg_data = ["d2"],
+        d3: reg, reg_data = ["d3"],
+        d4: reg, reg_data = ["d4"],
+        d5: reg, reg_data = ["d5"],
+        d6: reg, reg_data = ["d6"],
+        d7: reg, reg_data = ["d7"],
+        a0: reg, reg_addr = ["a0"],
+        a1: reg, reg_addr = ["a1"],
+        a2: reg, reg_addr = ["a2"],
+        a3: reg, reg_addr = ["a3"],
+        #error = ["a4"] =>
+            "a4 is used internally by LLVM and cannot be used as an operand for inline asm",
+        #error = ["a5", "bp"] =>
+            "a5 is used internally by LLVM and cannot be used as an operand for inline asm",
+        #error = ["a6", "fp"] =>
+            "a6 is used internally by LLVM and cannot be used as an operand for inline asm",
+        #error = ["a7", "sp", "usp", "ssp", "isp"] =>
+            "the stack pointer cannot be used as an operand for inline asm",
+    }
+}
+
+impl M68kInlineAsmReg {
+    pub fn emit(
+        self,
+        out: &mut dyn fmt::Write,
+        _arch: InlineAsmArch,
+        _modifier: Option<char>,
+    ) -> fmt::Result {
+        out.write_str(self.name())
+    }
+}
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 0dbfd426781..3f9c850b352 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -168,6 +168,7 @@ mod arm;
 mod avr;
 mod bpf;
 mod hexagon;
+mod m68k;
 mod mips;
 mod msp430;
 mod nvptx;
@@ -183,6 +184,7 @@ pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
 pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass};
 pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass};
 pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
+pub use m68k::{M68kInlineAsmReg, M68kInlineAsmRegClass};
 pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
 pub use msp430::{Msp430InlineAsmReg, Msp430InlineAsmRegClass};
 pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
@@ -214,6 +216,7 @@ pub enum InlineAsmArch {
     Bpf,
     Avr,
     Msp430,
+    M68k,
 }
 
 impl FromStr for InlineAsmArch {
@@ -240,6 +243,7 @@ impl FromStr for InlineAsmArch {
             "bpf" => Ok(Self::Bpf),
             "avr" => Ok(Self::Avr),
             "msp430" => Ok(Self::Msp430),
+            "m68k" => Ok(Self::M68k),
             _ => Err(()),
         }
     }
@@ -262,6 +266,7 @@ pub enum InlineAsmReg {
     Bpf(BpfInlineAsmReg),
     Avr(AvrInlineAsmReg),
     Msp430(Msp430InlineAsmReg),
+    M68k(M68kInlineAsmReg),
     // Placeholder for invalid register constraints for the current target
     Err,
 }
@@ -280,6 +285,7 @@ impl InlineAsmReg {
             Self::Bpf(r) => r.name(),
             Self::Avr(r) => r.name(),
             Self::Msp430(r) => r.name(),
+            Self::M68k(r) => r.name(),
             Self::Err => "<reg>",
         }
     }
@@ -297,6 +303,7 @@ impl InlineAsmReg {
             Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
             Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()),
             Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()),
+            Self::M68k(r) => InlineAsmRegClass::M68k(r.reg_class()),
             Self::Err => InlineAsmRegClass::Err,
         }
     }
@@ -328,6 +335,7 @@ impl InlineAsmReg {
             InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmReg::parse(name)?),
             InlineAsmArch::Avr => Self::Avr(AvrInlineAsmReg::parse(name)?),
             InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(name)?),
+            InlineAsmArch::M68k => Self::M68k(M68kInlineAsmReg::parse(name)?),
         })
     }
 
@@ -351,6 +359,7 @@ impl InlineAsmReg {
             Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
             Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
             Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::M68k(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
             Self::Err => unreachable!(),
         }
     }
@@ -375,6 +384,7 @@ impl InlineAsmReg {
             Self::Bpf(r) => r.emit(out, arch, modifier),
             Self::Avr(r) => r.emit(out, arch, modifier),
             Self::Msp430(r) => r.emit(out, arch, modifier),
+            Self::M68k(r) => r.emit(out, arch, modifier),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
     }
@@ -392,6 +402,7 @@ impl InlineAsmReg {
             Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
             Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))),
             Self::Msp430(_) => cb(self),
+            Self::M68k(_) => cb(self),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
     }
@@ -414,6 +425,7 @@ pub enum InlineAsmRegClass {
     Bpf(BpfInlineAsmRegClass),
     Avr(AvrInlineAsmRegClass),
     Msp430(Msp430InlineAsmRegClass),
+    M68k(M68kInlineAsmRegClass),
     // Placeholder for invalid register constraints for the current target
     Err,
 }
@@ -435,6 +447,7 @@ impl InlineAsmRegClass {
             Self::Bpf(r) => r.name(),
             Self::Avr(r) => r.name(),
             Self::Msp430(r) => r.name(),
+            Self::M68k(r) => r.name(),
             Self::Err => rustc_span::symbol::sym::reg,
         }
     }
@@ -458,6 +471,7 @@ impl InlineAsmRegClass {
             Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
             Self::Avr(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Avr),
             Self::Msp430(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Msp430),
+            Self::M68k(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::M68k),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -488,6 +502,7 @@ impl InlineAsmRegClass {
             Self::Bpf(r) => r.suggest_modifier(arch, ty),
             Self::Avr(r) => r.suggest_modifier(arch, ty),
             Self::Msp430(r) => r.suggest_modifier(arch, ty),
+            Self::M68k(r) => r.suggest_modifier(arch, ty),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -514,6 +529,7 @@ impl InlineAsmRegClass {
             Self::Bpf(r) => r.default_modifier(arch),
             Self::Avr(r) => r.default_modifier(arch),
             Self::Msp430(r) => r.default_modifier(arch),
+            Self::M68k(r) => r.default_modifier(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -539,6 +555,7 @@ impl InlineAsmRegClass {
             Self::Bpf(r) => r.supported_types(arch),
             Self::Avr(r) => r.supported_types(arch),
             Self::Msp430(r) => r.supported_types(arch),
+            Self::M68k(r) => r.supported_types(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -569,6 +586,7 @@ impl InlineAsmRegClass {
             InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(name)?),
             InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(name)?),
             InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(name)?),
+            InlineAsmArch::M68k => Self::M68k(M68kInlineAsmRegClass::parse(name)?),
         })
     }
 
@@ -590,6 +608,7 @@ impl InlineAsmRegClass {
             Self::Bpf(r) => r.valid_modifiers(arch),
             Self::Avr(r) => r.valid_modifiers(arch),
             Self::Msp430(r) => r.valid_modifiers(arch),
+            Self::M68k(r) => r.valid_modifiers(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -776,6 +795,11 @@ pub fn allocatable_registers(
             msp430::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
+        InlineAsmArch::M68k => {
+            let mut map = m68k::regclass_map();
+            m68k::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
+            map
+        }
     }
 }
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 192b2ab0ca2..4e5a821f0f6 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -123,7 +123,7 @@ pub enum Lld {
 /// target properties, in accordance with the first design goal.
 ///
 /// The first component of the flavor is tightly coupled with the compilation target,
-/// while the `Cc` and `Lld` flags can vary withing the same target.
+/// while the `Cc` and `Lld` flags can vary within the same target.
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
 pub enum LinkerFlavor {
     /// Unix-like linker with GNU extensions (both naked and compiler-wrapped forms).
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index 55025e2e72b..25e7439ece7 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -13,7 +13,7 @@ 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.
+/// Whether we're canonicalizing a query input or the query response.
 ///
 /// When canonicalizing an input we're in the context of the caller
 /// while canonicalizing the response happens in the context of the
@@ -21,7 +21,7 @@ use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 #[derive(Debug, Clone, Copy)]
 pub enum CanonicalizeMode {
     Input,
-    /// FIXME: We currently return region constraints refering to
+    /// FIXME: We currently return region constraints referring to
     /// placeholders and inference variables from a binder instantiated
     /// inside of the query.
     ///
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 861fa0a305a..ada868705c7 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -42,7 +42,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     ///
     /// - `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
+    /// - `external_constraints`: additional constraints which aren't expressible
     ///   using simple unification of inference variables.
     #[instrument(level = "debug", skip(self))]
     pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
@@ -113,7 +113,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     }
 
     /// This returns the substitutions to instantiate the bound variables of
-    /// the canonical reponse. This depends on the `original_values` for the
+    /// the canonical response. This depends on the `original_values` for the
     /// bound variables.
     fn compute_query_response_substitution(
         &self,
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 76a2a587911..32bd10f0beb 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -1,6 +1,7 @@
 use std::mem;
 
 use rustc_infer::infer::InferCtxt;
+use rustc_infer::traits::solve::MaybeCause;
 use rustc_infer::traits::Obligation;
 use rustc_infer::traits::{
     query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
@@ -41,13 +42,31 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
         self.obligations.push(obligation);
     }
 
-    fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
+    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
         self.obligations
             .drain(..)
-            .map(|obligation| FulfillmentError {
-                obligation: obligation.clone(),
-                code: FulfillmentErrorCode::CodeAmbiguity,
-                root_obligation: obligation,
+            .map(|obligation| {
+                let code =
+                    infcx.probe(|_| match infcx.evaluate_root_goal(obligation.clone().into()) {
+                        Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
+                            FulfillmentErrorCode::CodeAmbiguity { overflow: false }
+                        }
+                        Ok((_, Certainty::Maybe(MaybeCause::Overflow), _)) => {
+                            FulfillmentErrorCode::CodeAmbiguity { overflow: true }
+                        }
+                        Ok((_, Certainty::Yes, _)) => {
+                            bug!("did not expect successful goal when collecting ambiguity errors")
+                        }
+                        Err(_) => {
+                            bug!("did not expect selection error when collecting ambiguity errors")
+                        }
+                    });
+
+                FulfillmentError {
+                    obligation: obligation.clone(),
+                    code,
+                    root_obligation: obligation,
+                }
             })
             .collect()
     }
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
index 42c28686f5c..050269fa973 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -153,7 +153,7 @@ impl<'tcx> SearchGraph<'tcx> {
     /// coinductive cycles.
     ///
     /// When we encounter a coinductive cycle, we have to prove the final result of that cycle
-    /// while we are still computing that result. Because of this we continously recompute the
+    /// while we are still computing that result. Because of this we continuously recompute the
     /// cycle until the result of the previous iteration is equal to the final result, at which
     /// point we are done.
     ///
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs b/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs
index 574f3e9a577..e0a2e0c5cc2 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs
@@ -45,7 +45,7 @@ impl OverflowData {
     /// Updating the current limit when hitting overflow.
     fn deal_with_overflow(&mut self) {
         // When first hitting overflow we reduce the overflow limit
-        // for all future goals to prevent hangs if there's an exponental
+        // for all future goals to prevent hangs if there's an exponential
         // blowup.
         self.current_limit.0 = self.default_limit.0 / 8;
     }
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index a53d414be9e..182d995c4eb 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -9,7 +9,6 @@ use crate::infer::InferCtxt;
 use crate::traits::project::ProjectAndUnifyResult;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{ImplPolarity, Region, RegionVid};
 
@@ -187,7 +186,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
         }
 
-        infcx.process_registered_region_obligations(&Default::default(), full_env);
+        let outlives_env = OutlivesEnvironment::new(full_env);
+        infcx.process_registered_region_obligations(&outlives_env);
 
         let region_data =
             infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();
@@ -851,23 +851,3 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         infcx.freshen(p)
     }
 }
-
-/// Replaces all ReVars in a type with ty::Region's, using the provided map
-pub struct RegionReplacer<'a, 'tcx> {
-    vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        (match *r {
-            ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
-            _ => None,
-        })
-        .unwrap_or_else(|| r.super_fold_with(self))
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index b42a49eb47b..28967e1cc55 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -40,13 +40,16 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         self.obligations.insert(obligation);
     }
 
-    fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
+    fn collect_remaining_errors(
+        &mut self,
+        _infcx: &InferCtxt<'tcx>,
+    ) -> Vec<FulfillmentError<'tcx>> {
         // any remaining obligations are errors
         self.obligations
             .iter()
             .map(|obligation| FulfillmentError {
                 obligation: obligation.clone(),
-                code: FulfillmentErrorCode::CodeAmbiguity,
+                code: FulfillmentErrorCode::CodeAmbiguity { overflow: false },
                 // FIXME - does Chalk have a notation of 'root obligation'?
                 // This is just for diagnostics, so it's okay if this is wrong
                 root_obligation: obligation.clone(),
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 53d4f95e9e3..3c918b6028d 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -405,9 +405,6 @@ fn resolve_negative_obligation<'tcx>(
         param_env,
         infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
     );
-
-    infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
-
     infcx.resolve_regions(&outlives_env).is_empty()
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 8acc31cd410..2beebe94b6d 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -6,11 +6,13 @@ use super::{ChalkFulfillmentContext, FulfillmentContext};
 use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
 use crate::traits::NormalizeExt;
 use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::at::ToTrace;
 use rustc_infer::infer::canonical::{
     Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
 };
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_infer::traits::query::Fallible;
 use rustc_infer::traits::{
@@ -173,14 +175,33 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
             .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
     }
 
+    #[must_use]
     pub fn select_where_possible(&self) -> Vec<FulfillmentError<'tcx>> {
         self.engine.borrow_mut().select_where_possible(self.infcx)
     }
 
+    #[must_use]
     pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
         self.engine.borrow_mut().select_all_or_error(self.infcx)
     }
 
+    /// Resolves regions and reports errors.
+    ///
+    /// Takes ownership of the context as doing trait solving afterwards
+    /// will result in region constraints getting ignored.
+    pub fn resolve_regions_and_report_errors(
+        self,
+        generic_param_scope: LocalDefId,
+        outlives_env: &OutlivesEnvironment<'tcx>,
+    ) -> Result<(), ErrorGuaranteed> {
+        let errors = self.infcx.resolve_regions(&outlives_env);
+        if errors.is_empty() {
+            Ok(())
+        } else {
+            Err(self.infcx.err_ctxt().report_region_errors(generic_param_scope, &errors))
+        }
+    }
+
     pub fn assumed_wf_types(
         &self,
         param_env: ty::ParamEnv<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 6ebf056f0e8..0ef6579664a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -125,6 +125,8 @@ pub trait TypeErrCtxtExt<'tcx> {
             + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
         <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
 
+    fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
+
     fn report_fulfillment_errors(&self, errors: &[FulfillmentError<'tcx>]) -> ErrorGuaranteed;
 
     fn report_overflow_obligation<T>(
@@ -602,6 +604,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         );
     }
 
+    fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed {
+        let obligation = self.resolve_vars_if_possible(obligation);
+        let mut err = self.build_overflow_error(&obligation.predicate, obligation.cause.span, true);
+        self.note_obligation_cause(&mut err, &obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+        err.emit()
+    }
+
     fn report_selection_error(
         &self,
         mut obligation: PredicateObligation<'tcx>,
@@ -1658,9 +1668,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             FulfillmentErrorCode::CodeProjectionError(ref e) => {
                 self.report_projection_error(&error.obligation, e);
             }
-            FulfillmentErrorCode::CodeAmbiguity => {
+            FulfillmentErrorCode::CodeAmbiguity { overflow: false } => {
                 self.maybe_report_ambiguity(&error.obligation);
             }
+            FulfillmentErrorCode::CodeAmbiguity { overflow: true } => {
+                self.report_overflow_no_abort(error.obligation.clone());
+            }
             FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
                 self.report_mismatched_types(
                     &error.obligation.cause,
@@ -1763,7 +1776,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                 // constrain inference variables a bit more to nested obligations from normalize so
                 // we can have more helpful errors.
-                ocx.select_where_possible();
+                //
+                // we intentionally drop errors from normalization here,
+                // since the normalization is just done to improve the error message.
+                let _ = ocx.select_where_possible();
 
                 if let Err(new_err) = ocx.eq_exp(
                     &obligation.cause,
@@ -2380,8 +2396,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
 
                 if let Some(ty::subst::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack())
+                    && let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
                 {
-                    let body_id = self.tcx.hir().body_owned_by(obligation.cause.body_id);
                     let mut expr_finder = FindExprBySpan::new(span);
                     expr_finder.visit_expr(&self.tcx.hir().body(body_id).value);
 
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 07e31e87bfb..26cadab3e9f 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -133,8 +133,15 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
             .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
     }
 
-    fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
-        self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
+    fn collect_remaining_errors(
+        &mut self,
+        _infcx: &InferCtxt<'tcx>,
+    ) -> Vec<FulfillmentError<'tcx>> {
+        self.predicates
+            .to_errors(CodeAmbiguity { overflow: false })
+            .into_iter()
+            .map(to_fulfillment_error)
+            .collect()
     }
 
     fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 0bde43c54df..af567c07438 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -117,10 +117,6 @@ pub fn type_allowed_to_implement_copy<'tcx>(
                     FxIndexSet::from_iter([self_type]),
                 ),
             );
-            infcx.process_registered_region_obligations(
-                outlives_env.region_bound_pairs(),
-                param_env,
-            );
             let errors = infcx.resolve_regions(&outlives_env);
             if !errors.is_empty() {
                 infringing.push((field, ty, InfringingFieldsReason::Regions(errors)));
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 a794d20d683..1f5bbc178f7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -294,7 +294,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return;
         }
 
-        // Keep this funtion in sync with extract_tupled_inputs_and_output_from_callable
+        // Keep this function in sync with extract_tupled_inputs_and_output_from_callable
         // until the old solver (and thus this function) is removed.
 
         // Okay to skip binder because what we are inspecting doesn't involve bound regions.
@@ -406,7 +406,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             match obligation.self_ty().skip_binder().kind() {
-                // Fast path to avoid evaluating an obligation that trivally holds.
+                // Fast path to avoid evaluating an obligation that trivially holds.
                 // There may be more bounds, but these are checked by the regular path.
                 ty::FnPtr(..) => return false,
                 // These may potentially implement `FnPtr`
diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index a1e97bb95bc..15a14112f4a 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -12,7 +12,7 @@ ty_utils_array_not_supported = array construction is not supported in generic co
 
 ty_utils_block_not_supported = blocks are not supported in generic constants
 
-ty_utils_never_to_any_not_supported = converting nevers to any is not supported in generic constants
+ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants
 
 ty_utils_tuple_not_supported = tuple construction is not supported in generic constants
 
@@ -54,4 +54,4 @@ ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with
 
 ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
 
-ty_utils_non_primative_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
+ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 3db3c98e9e2..3d3fc50e6e5 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -95,7 +95,7 @@ pub struct OversizedSimdType<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ty_utils_non_primative_simd_type)]
+#[diag(ty_utils_non_primitive_simd_type)]
 pub struct NonPrimitiveSimdType<'tcx> {
     pub ty: Ty<'tcx>,
     pub e_ty: Ty<'tcx>,
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 63eb34f7d55..63ef1c72417 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -322,7 +322,7 @@ fn layout_of_uncached<'tcx>(
                 if fi.ty(tcx, substs) != f0_ty {
                     tcx.sess.delay_span_bug(
                         DUMMY_SP,
-                        "#[repr(simd)] was applied to an ADT with hetrogeneous field type",
+                        "#[repr(simd)] was applied to an ADT with heterogeneous field type",
                     );
                     return Err(LayoutError::Unknown(ty));
                 }
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 8b23fbc7583..a3c98ae007e 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -83,7 +83,7 @@ pub trait CollectAndApply<T, R>: Sized {
     /// Produce a result of type `Self::Output` from `iter`. The result will
     /// typically be produced by applying `f` on the elements produced by
     /// `iter`, though this may not happen in some impls, e.g. if an error
-    /// occured during iteration.
+    /// occurred during iteration.
     fn collect_and_apply<I, F>(iter: I, f: F) -> Self::Output
     where
         I: Iterator<Item = Self>,