about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs36
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs55
-rw-r--r--compiler/rustc_attr/src/builtin.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs15
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs18
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/standard_library_imports.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs15
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs1
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs11
-rw-r--r--compiler/rustc_errors/src/emitter.rs3
-rw-r--r--compiler/rustc_errors/src/lib.rs29
-rw-r--r--compiler/rustc_expand/src/config.rs10
-rw-r--r--compiler/rustc_feature/src/active.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs112
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs33
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs (renamed from compiler/rustc_hir_analysis/src/collect/lifetimes.rs)403
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs123
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs5
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs13
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs30
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs10
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs10
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs19
-rw-r--r--compiler/rustc_lint/src/context.rs10
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs7
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs2
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/resolve_bound_vars.rs (renamed from compiler/rustc_middle/src/middle/resolve_lifetime.rs)14
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs31
-rw-r--r--compiler/rustc_middle/src/ty/context.rs168
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs4
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs18
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs2
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs18
-rw-r--r--compiler/rustc_middle/src/ty/query.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs8
-rw-r--r--compiler/rustc_middle/src/ty/util.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs9
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs8
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs8
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs7
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs24
-rw-r--r--compiler/rustc_parse/src/parser/path.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs5
-rw-r--r--compiler/rustc_parse_format/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs2
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs7
-rw-r--r--compiler/rustc_passes/src/stability.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs3
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs3
-rw-r--r--compiler/rustc_resolve/src/late.rs10
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs8
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs2
-rw-r--r--compiler/rustc_session/src/config.rs2
-rw-r--r--compiler/rustc_session/src/errors.rs28
-rw-r--r--compiler/rustc_session/src/filesearch.rs2
-rw-r--r--compiler/rustc_session/src/options.rs4
-rw-r--r--compiler/rustc_session/src/parse.rs6
-rw-r--r--compiler/rustc_span/src/def_id.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs20
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs12
-rw-r--r--library/core/src/iter/traits/iterator.rs22
-rw-r--r--src/bootstrap/check.rs3
-rw-r--r--src/bootstrap/config.rs5
-rw-r--r--src/bootstrap/flags.rs11
-rw-r--r--src/bootstrap/run.rs1
-rw-r--r--src/bootstrap/test.rs1
-rw-r--r--src/librustdoc/clean/mod.rs182
-rw-r--r--src/librustdoc/html/format.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs4
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/rustdoc/reexport-attr-merge.rs33
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr9
-rw-r--r--tests/ui/argument-suggestions/basic.stderr9
-rw-r--r--tests/ui/argument-suggestions/exotic-calls.stderr36
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.stderr145
-rw-r--r--tests/ui/argument-suggestions/issue-101097.stderr6
-rw-r--r--tests/ui/argument-suggestions/issue-97484.stderr11
-rw-r--r--tests/ui/argument-suggestions/mixed_cases.stderr13
-rw-r--r--tests/ui/associated-types/issue-38821.rs (renamed from tests/ui/issues/issue-38821.rs)0
-rw-r--r--tests/ui/associated-types/issue-38821.stderr (renamed from tests/ui/issues/issue-38821.stderr)0
-rw-r--r--tests/ui/borrowck/issue-83924.fixed (renamed from tests/ui/issues/issue-83924.fixed)0
-rw-r--r--tests/ui/borrowck/issue-83924.rs (renamed from tests/ui/issues/issue-83924.rs)0
-rw-r--r--tests/ui/borrowck/issue-83924.stderr (renamed from tests/ui/issues/issue-83924.stderr)0
-rw-r--r--tests/ui/bounds-lifetime.stderr11
-rw-r--r--tests/ui/closures/binder/disallow-const.stderr6
-rw-r--r--tests/ui/closures/binder/disallow-ty.stderr6
-rw-r--r--tests/ui/conditional-compilation/cfg-generic-params.stderr46
-rw-r--r--tests/ui/consts/issue-33903.rs (renamed from tests/ui/issues/issue-33903.rs)0
-rw-r--r--tests/ui/consts/issue-54582.rs (renamed from tests/ui/issues/issue-54582.rs)0
-rw-r--r--tests/ui/drop/issue-2735-2.rs (renamed from tests/ui/issues/issue-2735-2.rs)0
-rw-r--r--tests/ui/drop/issue-2735-3.rs (renamed from tests/ui/issues/issue-2735-3.rs)0
-rw-r--r--tests/ui/drop/issue-2735.rs (renamed from tests/ui/issues/issue-2735.rs)0
-rw-r--r--tests/ui/error-codes/E0057.stderr9
-rw-r--r--tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr12
-rw-r--r--tests/ui/fmt/issue-75307.rs (renamed from tests/ui/issues/issue-75307.rs)0
-rw-r--r--tests/ui/fmt/issue-75307.stderr (renamed from tests/ui/issues/issue-75307.stderr)0
-rw-r--r--tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr11
-rw-r--r--tests/ui/higher-rank-trait-bounds/issue-39292.rs (renamed from tests/ui/issues/issue-39292.rs)0
-rw-r--r--tests/ui/issues/issue-16939.stderr9
-rw-r--r--tests/ui/issues/issue-26094.rs2
-rw-r--r--tests/ui/issues/issue-26094.stderr9
-rw-r--r--tests/ui/issues/issue-4935.stderr9
-rw-r--r--tests/ui/loops/issue-50576.rs (renamed from tests/ui/issues/issue-50576.rs)0
-rw-r--r--tests/ui/loops/issue-50576.stderr (renamed from tests/ui/issues/issue-50576.stderr)0
-rw-r--r--tests/ui/methods/method-call-err-msg.stderr9
-rw-r--r--tests/ui/mismatched_types/overloaded-calls-bad.stderr7
-rw-r--r--tests/ui/moves/issue-22536-copy-mustnt-zero.rs (renamed from tests/ui/issues/issue-22536-copy-mustnt-zero.rs)0
-rw-r--r--tests/ui/nll/issue-27583.rs (renamed from tests/ui/issues/issue-27583.rs)0
-rw-r--r--tests/ui/nll/issue-48179.rs (renamed from tests/ui/issues/issue-48179.rs)0
-rw-r--r--tests/ui/nll/issue-75777.rs (renamed from tests/ui/issues/issue-75777.rs)0
-rw-r--r--tests/ui/nll/issue-75777.stderr (renamed from tests/ui/issues/issue-75777.stderr)0
-rw-r--r--tests/ui/parser/recover-fn-ptr-with-generics.stderr12
-rw-r--r--tests/ui/recursion_limit/issue-40003.rs (renamed from tests/ui/issues/issue-40003.rs)0
-rw-r--r--tests/ui/resolve/resolve-primitive-fallback.stderr9
-rw-r--r--tests/ui/span/issue-34264.stderr18
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple-errors.stderr14
-rw-r--r--tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs11
-rw-r--r--tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr19
-rw-r--r--tests/ui/traits/non_lifetime_binders/basic.rs19
-rw-r--r--tests/ui/traits/non_lifetime_binders/basic.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/fail.rs23
-rw-r--r--tests/ui/traits/non_lifetime_binders/fail.stderr43
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-dyn.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-dyn.stderr17
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-ptr.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-ptr.stderr17
-rw-r--r--tests/ui/tuple/wrong_argument_ice-3.stderr7
-rw-r--r--tests/ui/tuple/wrong_argument_ice-4.stderr9
-rw-r--r--tests/ui/type/type-ascription-instead-of-initializer.stderr9
-rw-r--r--tests/ui/typeck/issue-53712.rs (renamed from tests/ui/issues/issue-53712.rs)0
-rw-r--r--tests/ui/typeck/issue-53712.stderr (renamed from tests/ui/issues/issue-53712.stderr)0
-rw-r--r--tests/ui/typeck/issue-7813.rs (renamed from tests/ui/issues/issue-7813.rs)0
-rw-r--r--tests/ui/typeck/issue-7813.stderr (renamed from tests/ui/issues/issue-7813.stderr)0
-rw-r--r--tests/ui/typeck/remove-extra-argument.stderr9
-rw-r--r--tests/ui/typeck/struct-enum-wrong-args.stderr36
-rw-r--r--triagebot.toml2
198 files changed, 1682 insertions, 1091 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 902b4b1a1ec..d1ae8c1fdbd 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -271,7 +271,7 @@ impl<'a> AstValidator<'a> {
 
         self.session.emit_err(InvalidVisibility {
             span: vis.span,
-            implied: if vis.kind.is_pub() { Some(vis.span) } else { None },
+            implied: vis.kind.is_pub().then_some(vis.span),
             note,
         });
     }
@@ -294,27 +294,6 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
-        // Check only lifetime parameters are present and that the lifetime
-        // parameters that are present have no bounds.
-        let non_lt_param_spans: Vec<_> = params
-            .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => {
-                    if !param.bounds.is_empty() {
-                        let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
-                        self.session.emit_err(ForbiddenLifetimeBound { spans });
-                    }
-                    None
-                }
-                _ => Some(param.ident.span),
-            })
-            .collect();
-        if !non_lt_param_spans.is_empty() {
-            self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
-        }
-    }
-
     fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
         self.check_decl_num_args(fn_decl);
         self.check_decl_cvaradic_pos(fn_decl);
@@ -745,7 +724,6 @@ impl<'a> AstValidator<'a> {
                     )
                     .emit();
                 });
-                self.check_late_bound_lifetime_defs(&bfty.generic_params);
                 if let Extern::Implicit(_) = bfty.ext {
                     let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
                     self.maybe_lint_missing_abi(sig_span, ty.id);
@@ -1318,9 +1296,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         for predicate in &generics.where_clause.predicates {
             match predicate {
                 WherePredicate::BoundPredicate(bound_pred) => {
-                    // A type binding, eg `for<'c> Foo: Send+Clone+'c`
-                    self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
-
                     // This is slightly complicated. Our representation for poly-trait-refs contains a single
                     // binder and thus we only allow a single level of quantification. However,
                     // the syntax of Rust permits quantification in two places in where clauses,
@@ -1396,11 +1371,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_param_bound(self, bound)
     }
 
-    fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) {
-        self.check_late_bound_lifetime_defs(&t.bound_generic_params);
-        visit::walk_poly_trait_ref(self, t);
-    }
-
     fn visit_variant_data(&mut self, s: &'a VariantData) {
         self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
     }
@@ -1437,10 +1407,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 .emit();
         }
 
-        if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
-            self.check_late_bound_lifetime_defs(generic_params);
-        }
-
         if let FnKind::Fn(
             _,
             _,
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 89ba6f936d1..3af2ef4e727 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -11,6 +11,8 @@ use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::spec::abi;
 
+use crate::errors::ForbiddenLifetimeBound;
+
 macro_rules! gate_feature_fn {
     ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
         let (visitor, has_feature, span, name, explain, help) =
@@ -136,6 +138,34 @@ impl<'a> PostExpansionVisitor<'a> {
         }
         ImplTraitVisitor { vis: self }.visit_ty(ty);
     }
+
+    fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
+        // Check only lifetime parameters are present and that the lifetime
+        // parameters that are present have no bounds.
+        let non_lt_param_spans: Vec<_> = params
+            .iter()
+            .filter_map(|param| match param.kind {
+                ast::GenericParamKind::Lifetime { .. } => None,
+                _ => Some(param.ident.span),
+            })
+            .collect();
+        // FIXME: gate_feature_post doesn't really handle multispans...
+        if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
+            feature_err(
+                &self.sess.parse_sess,
+                sym::non_lifetime_binders,
+                non_lt_param_spans,
+                rustc_errors::fluent::ast_passes_forbidden_non_lifetime_param,
+            )
+            .emit();
+        }
+        for param in params {
+            if !param.bounds.is_empty() {
+                let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
+                self.sess.emit_err(ForbiddenLifetimeBound { spans });
+            }
+        }
+    }
 }
 
 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@@ -147,7 +177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             ..
         }) = attr_info
         {
-            gate_feature_fn!(self, has_feature, attr.span, *name, descr);
+            gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
         }
         // Check unstable flavors of the `#[doc]` attribute.
         if attr.has_name(sym::doc) {
@@ -306,6 +336,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             ast::TyKind::BareFn(bare_fn_ty) => {
                 // Function pointers cannot be `const`
                 self.check_extern(bare_fn_ty.ext, ast::Const::No);
+                self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
             }
             ast::TyKind::Never => {
                 gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
@@ -318,6 +349,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_ty(self, ty)
     }
 
+    fn visit_generics(&mut self, g: &'a ast::Generics) {
+        for predicate in &g.where_clause.predicates {
+            match predicate {
+                ast::WherePredicate::BoundPredicate(bound_pred) => {
+                    // A type binding, eg `for<'c> Foo: Send+Clone+'c`
+                    self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
+                }
+                _ => {}
+            }
+        }
+        visit::walk_generics(self, g);
+    }
+
     fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
         if let ast::FnRetTy::Ty(output_ty) = ret_ty {
             if let ast::TyKind::Never = output_ty.kind {
@@ -437,12 +481,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_pat(self, pattern)
     }
 
+    fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
+        self.check_late_bound_lifetime_defs(&t.bound_generic_params);
+        visit::walk_poly_trait_ref(self, t);
+    }
+
     fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
         if let Some(header) = fn_kind.header() {
             // Stability of const fn methods are covered in `visit_assoc_item` below.
             self.check_extern(header.ext, header.constness);
         }
 
+        if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind {
+            self.check_late_bound_lifetime_defs(generic_params);
+        }
+
         if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
             gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
         }
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 40531c1c164..3d240108b4a 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -731,7 +731,7 @@ pub fn eval_condition(
                             sess,
                             sym::cfg_target_compact,
                             cfg.span,
-                            &"compact `cfg(target(..))` is experimental and subject to change"
+                            "compact `cfg(target(..))` is experimental and subject to change"
                         ).emit();
                     }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 1550958ab8e..d51cc652bfd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -180,20 +180,20 @@ trait TypeOpInfo<'tcx> {
             return;
         };
 
-        let placeholder_region = tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
+        let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder {
             name: placeholder.name,
             universe: adjusted_universe.into(),
-        }));
+        });
 
         let error_region =
             if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
                 let adjusted_universe =
                     error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
                 adjusted_universe.map(|adjusted| {
-                    tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
+                    tcx.mk_re_placeholder(ty::Placeholder {
                         name: error_placeholder.name,
                         universe: adjusted.into(),
-                    }))
+                    })
                 })
             } else {
                 None
@@ -390,7 +390,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
         error_region,
         &region_constraints,
         |vid| ocx.infcx.region_var_origin(vid),
-        |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_region(ty::ReVar(vid))),
+        |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_re_var(vid)),
     )
 }
 
@@ -411,7 +411,7 @@ fn try_extract_error_from_region_constraints<'tcx>(
                 }
                 // FIXME: Should this check the universe of the var?
                 Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
-                    Some((infcx.tcx.mk_region(ty::ReVar(vid)), cause.clone()))
+                    Some((infcx.tcx.mk_re_var(vid), cause.clone()))
                 }
                 _ => None,
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 7b07c2a4633..9e90ca3b92c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1186,11 +1186,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 return None;
             };
             debug!("checking call args for uses of inner_param: {:?}", args);
-            if args.contains(&Operand::Move(inner_param)) {
-                Some((loc, term))
-            } else {
-                None
-            }
+            args.contains(&Operand::Move(inner_param)).then_some((loc, term))
         }) else {
             debug!("no uses of inner_param found as a by-move call arg");
             return;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index a82e695d649..0033dc70c70 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -280,17 +280,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
         debug!("give_region_a_name: error_region = {:?}", error_region);
         match *error_region {
-            ty::ReEarlyBound(ebr) => {
-                if ebr.has_name() {
-                    let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
-                    Some(RegionName {
-                        name: ebr.name,
-                        source: RegionNameSource::NamedEarlyBoundRegion(span),
-                    })
-                } else {
-                    None
-                }
-            }
+            ty::ReEarlyBound(ebr) => ebr.has_name().then(|| {
+                let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
+                RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyBoundRegion(span) }
+            }),
 
             ty::ReStatic => {
                 Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static })
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index f2693bded59..83fdb6066c6 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1297,7 +1297,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             let vid = self.to_region_vid(r);
             let scc = self.constraint_sccs.scc(vid);
             let repr = self.scc_representatives[scc];
-            tcx.mk_region(ty::ReVar(repr))
+            tcx.mk_re_var(repr)
         })
     }
 
@@ -1719,7 +1719,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
 
             // If not, report an error.
-            let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
+            let member_region = infcx.tcx.mk_re_var(member_region_vid);
             errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
                 span: m_c.definition_span,
                 hidden_ty: m_c.hidden_ty,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index c7b22d5f2e6..bb42301828d 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -91,7 +91,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     }
                     None => {
                         subst_regions.push(vid);
-                        infcx.tcx.re_error_with_message(
+                        infcx.tcx.mk_re_error_with_message(
                             concrete_type.span,
                             "opaque type with non-universal region substs",
                         )
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index d5c401ae1c6..a411aec518e 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -50,13 +50,11 @@ pub(super) fn generate<'mir, 'tcx>(
         compute_relevant_live_locals(typeck.tcx(), &free_regions, &body);
     let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
 
-    let polonius_drop_used = if facts_enabled {
+    let polonius_drop_used = facts_enabled.then(|| {
         let mut drop_used = Vec::new();
         polonius::populate_access_facts(typeck, body, location_table, move_data, &mut drop_used);
-        Some(drop_used)
-    } else {
-        None
-    };
+        drop_used
+    });
 
     trace::trace(
         typeck,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 5b7adae66ac..7a05fde47fc 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -137,7 +137,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     upvars: &[Upvar<'tcx>],
     use_polonius: bool,
 ) -> MirTypeckResults<'tcx> {
-    let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
+    let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 56930c89b2c..3f254a6b7b6 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -480,10 +480,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     LangItem::VaList,
                     Some(self.infcx.tcx.def_span(self.mir_def.did)),
                 );
-                let region = self
-                    .infcx
-                    .tcx
-                    .mk_region(ty::ReVar(self.infcx.next_nll_region_var(FR).to_region_vid()));
+                let region =
+                    self.infcx.tcx.mk_re_var(self.infcx.next_nll_region_var(FR).to_region_vid());
                 let va_list_ty = self
                     .infcx
                     .tcx
@@ -636,7 +634,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                     kind: ty::BrEnv,
                 };
-                let env_region = ty::ReLateBound(ty::INNERMOST, br);
+                let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
                 let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
 
                 // The "inputs" of the closure in the
@@ -748,10 +746,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
     {
         let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
             debug!(?br);
-            let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                scope: all_outlive_scope.to_def_id(),
-                bound_region: br.kind,
-            }));
+            let liberated_region = self.tcx.mk_re_free(all_outlive_scope.to_def_id(), br.kind);
             let region_vid = self.next_nll_region_var(origin);
             indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid());
             debug!(?liberated_region, ?region_vid);
@@ -843,7 +838,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        tcx.fold_regions(value, |region, _| tcx.mk_region(ty::ReVar(self.to_region_vid(region))))
+        tcx.fold_regions(value, |region, _| tcx.mk_re_var(self.to_region_vid(region)))
     }
 }
 
@@ -883,8 +878,7 @@ fn for_each_late_bound_region_in_item<'tcx>(
 
     for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) {
         let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; };
-        let liberated_region = tcx
-            .mk_region(ty::ReFree(ty::FreeRegion { scope: mir_def_id.to_def_id(), bound_region }));
+        let liberated_region = tcx.mk_re_free(mir_def_id.to_def_id(), bound_region);
         f(liberated_region);
     }
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index e8a353b1c8f..d30e8ba4b93 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -135,19 +135,17 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
         }
 
         // `let names: &'static _ = &["field1", "field2"];`
-        let names_let = if is_struct {
+        let names_let = is_struct.then(|| {
             let lt_static = Some(cx.lifetime_static(span));
             let ty_static_ref = cx.ty_ref(span, cx.ty_infer(span), lt_static, ast::Mutability::Not);
-            Some(cx.stmt_let_ty(
+            cx.stmt_let_ty(
                 span,
                 false,
                 Ident::new(sym::names, span),
                 Some(ty_static_ref),
                 cx.expr_array_ref(span, name_exprs),
-            ))
-        } else {
-            None
-        };
+            )
+        });
 
         // `let values: &[&dyn Debug] = &[&&self.field1, &&self.field2];`
         let path_debug = cx.path_global(span, cx.std_path(&[sym::fmt, sym::Debug]));
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 970b9115d8d..7fc735dbafa 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -942,13 +942,11 @@ impl<'a> MethodDef<'a> {
         let mut nonself_arg_tys = Vec::new();
         let span = trait_.span;
 
-        let explicit_self = if self.explicit_self {
+        let explicit_self = self.explicit_self.then(|| {
             let (self_expr, explicit_self) = ty::get_explicit_self(cx, span);
             selflike_args.push(self_expr);
-            Some(explicit_self)
-        } else {
-            None
-        };
+            explicit_self
+        });
 
         for (ty, name) in self.nonself_args.iter() {
             let ast_ty = ty.to_ty(cx, span, type_ident, generics);
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index f73f20c84a3..e67c0dba685 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -62,7 +62,7 @@ pub fn inject(
     // the one with the prelude.
     let name = names[0];
 
-    let root = (edition == Edition2015).then(|| kw::PathRoot);
+    let root = (edition == Edition2015).then_some(kw::PathRoot);
 
     let import_path = root
         .iter()
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 58b01dfb5b0..7c6fd9f6f1e 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -248,17 +248,13 @@ fn reuse_workproduct_for_cgu(
             dwarf_object: None,
             bytecode: None,
         },
-        module_global_asm: if has_global_asm {
-            Some(CompiledModule {
-                name: cgu.name().to_string(),
-                kind: ModuleKind::Regular,
-                object: Some(obj_out_global_asm),
-                dwarf_object: None,
-                bytecode: None,
-            })
-        } else {
-            None
-        },
+        module_global_asm: has_global_asm.then(|| CompiledModule {
+            name: cgu.name().to_string(),
+            kind: ModuleKind::Regular,
+            object: Some(obj_out_global_asm),
+            dwarf_object: None,
+            bytecode: None,
+        }),
         existing_work_product: Some((cgu.work_product_id(), work_product)),
     })
 }
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 38f8733763d..fb160669436 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -412,11 +412,7 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> {
 }
 
 fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> {
-    if config.instrument_coverage {
-        Some(CString::new("default_%m_%p.profraw").unwrap())
-    } else {
-        None
-    }
+    config.instrument_coverage.then(|| CString::new("default_%m_%p.profraw").unwrap())
 }
 
 pub(crate) unsafe fn llvm_optimize(
@@ -451,11 +447,10 @@ pub(crate) unsafe fn llvm_optimize(
         None
     };
 
-    let mut llvm_profiler = if cgcx.prof.llvm_recording_enabled() {
-        Some(LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()))
-    } else {
-        None
-    };
+    let mut llvm_profiler = cgcx
+        .prof
+        .llvm_recording_enabled()
+        .then(|| LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()));
 
     let llvm_selfprofiler =
         llvm_profiler.as_mut().map(|s| s as *mut _ as *mut c_void).unwrap_or(std::ptr::null_mut());
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 120dc59dfb3..8848ea3bb9a 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -402,12 +402,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
 
         let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
 
-        let coverage_cx = if tcx.sess.instrument_coverage() {
-            let covctx = coverageinfo::CrateCoverageContext::new();
-            Some(covctx)
-        } else {
-            None
-        };
+        let coverage_cx =
+            tcx.sess.instrument_coverage().then(coverageinfo::CrateCoverageContext::new);
 
         let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
             let dctx = debuginfo::CodegenUnitDebugContext::new(llmod);
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 0cb4bc806a1..cc8ff947fc3 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -154,7 +154,7 @@ fn struct_llfields<'a, 'tcx>(
     } else {
         debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
     }
-    let field_remapping = if padding_used { Some(field_remapping) } else { None };
+    let field_remapping = padding_used.then_some(field_remapping);
     (result, packed, field_remapping)
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 6fe8527ada6..8aa744ce935 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2024,7 +2024,7 @@ fn linker_with_args<'a>(
         .native_libraries
         .iter()
         .filter_map(|(cnum, libraries)| {
-            (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then(|| libraries)
+            (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries)
         })
         .flatten();
     for (raw_dylib_name, raw_dylib_imports) in
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 6e136db3895..023d38e9312 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -579,7 +579,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
         }
     }
 
-    let metadata_module = if need_metadata_module {
+    let metadata_module = need_metadata_module.then(|| {
         // Emit compressed metadata object.
         let metadata_cgu_name =
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
@@ -594,17 +594,15 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
             if let Err(error) = std::fs::write(&file_name, data) {
                 tcx.sess.emit_fatal(errors::MetadataObjectFileWrite { error });
             }
-            Some(CompiledModule {
+            CompiledModule {
                 name: metadata_cgu_name,
                 kind: ModuleKind::Metadata,
                 object: Some(file_name),
                 dwarf_object: None,
                 bytecode: None,
-            })
+            }
         })
-    } else {
-        None
-    };
+    });
 
     let ongoing_codegen = start_async_codegen(
         backend.clone(),
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index de1734332d4..eec91ffa44a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -167,8 +167,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         start_bx.set_personality_fn(cx.eh_personality());
     }
 
-    let cleanup_kinds =
-        if base::wants_msvc_seh(cx.tcx().sess) { Some(analyze::cleanup_kinds(&mir)) } else { None };
+    let cleanup_kinds = base::wants_msvc_seh(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir));
 
     let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
         mir.basic_blocks
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index a6afbad5b24..0432a9c5a12 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -286,6 +286,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("mutable-globals", Some(sym::wasm_target_feature)),
     ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
     ("reference-types", Some(sym::wasm_target_feature)),
+    ("relaxed-simd", Some(sym::wasm_target_feature)),
     ("sign-ext", Some(sym::wasm_target_feature)),
     ("simd128", None),
     // tidy-alphabetical-end
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 3aca03f6e5c..44331683694 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -207,8 +207,7 @@ impl SelfProfilerRef {
     /// a measureme event, "verbose" generic activities also print a timing entry to
     /// stderr if the compiler is invoked with -Ztime-passes.
     pub fn verbose_generic_activity(&self, event_label: &'static str) -> VerboseTimingGuard<'_> {
-        let message =
-            if self.print_verbose_generic_activities { Some(event_label.to_owned()) } else { None };
+        let message = self.print_verbose_generic_activities.then(|| event_label.to_owned());
 
         VerboseTimingGuard::start(message, self.generic_activity(event_label))
     }
@@ -222,11 +221,9 @@ impl SelfProfilerRef {
     where
         A: Borrow<str> + Into<String>,
     {
-        let message = if self.print_verbose_generic_activities {
-            Some(format!("{}({})", event_label, event_arg.borrow()))
-        } else {
-            None
-        };
+        let message = self
+            .print_verbose_generic_activities
+            .then(|| format!("{}({})", event_label, event_arg.borrow()));
 
         VerboseTimingGuard::start(message, self.generic_activity_with_arg(event_label, event_arg))
     }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 4f2cc8b0351..211bbf4f50e 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1768,7 +1768,7 @@ impl EmitterWriter {
 
         // Render the replacements for each suggestion
         let suggestions = suggestion.splice_lines(sm);
-        debug!("emit_suggestion_default: suggestions={:?}", suggestions);
+        debug!(?suggestions);
 
         if suggestions.is_empty() {
             // Suggestions coming from macros can have malformed spans. This is a heavy handed
@@ -1797,6 +1797,7 @@ impl EmitterWriter {
         for (complete, parts, highlights, only_capitalization) in
             suggestions.iter().take(MAX_SUGGESTIONS)
         {
+            debug!(?complete, ?parts, ?highlights);
             notice_capitalization |= only_capitalization;
 
             let has_deletion = parts.iter().any(|p| p.is_deletion(sm));
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 83b733d4c06..4b3c0c055ad 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1066,29 +1066,26 @@ impl Handler {
     }
 
     pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
-        if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
+        self.inner.borrow().has_errors().then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
     }
 
     pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
-        if self.inner.borrow().has_errors_or_lint_errors() {
-            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
-        } else {
-            None
-        }
+        self.inner
+            .borrow()
+            .has_errors_or_lint_errors()
+            .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
     }
     pub fn has_errors_or_delayed_span_bugs(&self) -> Option<ErrorGuaranteed> {
-        if self.inner.borrow().has_errors_or_delayed_span_bugs() {
-            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
-        } else {
-            None
-        }
+        self.inner
+            .borrow()
+            .has_errors_or_delayed_span_bugs()
+            .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
     }
     pub fn is_compilation_going_to_fail(&self) -> Option<ErrorGuaranteed> {
-        if self.inner.borrow().is_compilation_going_to_fail() {
-            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
-        } else {
-            None
-        }
+        self.inner
+            .borrow()
+            .is_compilation_going_to_fail()
+            .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
     }
 
     pub fn print_error_count(&self, registry: &Registry) {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 1fcbdfd9be5..5c845ae6d0b 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -238,12 +238,10 @@ macro_rules! configure {
 impl<'a> StripUnconfigured<'a> {
     pub fn configure<T: HasAttrs + HasTokens>(&self, mut node: T) -> Option<T> {
         self.process_cfg_attrs(&mut node);
-        if self.in_cfg(node.attrs()) {
+        self.in_cfg(node.attrs()).then(|| {
             self.try_configure_tokens(&mut node);
-            Some(node)
-        } else {
-            None
-        }
+            node
+        })
     }
 
     fn try_configure_tokens<T: HasTokens>(&self, node: &mut T) {
@@ -257,7 +255,7 @@ impl<'a> StripUnconfigured<'a> {
 
     fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option<ast::AttrVec> {
         attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
-        if self.in_cfg(&attrs) { Some(attrs) } else { None }
+        self.in_cfg(&attrs).then_some(attrs)
     }
 
     /// Performs cfg-expansion on `stream`, producing a new `AttrTokenStream`.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 21d211eefbe..7122ccdcd2e 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -164,8 +164,6 @@ declare_features! (
     (active, multiple_supertrait_upcastable, "CURRENT_RUSTC_VERSION", None, None),
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
     (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
-    /// Allows using `+bundled,+whole-archive` native libs.
-    (active, packed_bundled_libs, "1.67.0", None, None),
     /// Allows using `#[prelude_import]` on glob `use` items.
     (active, prelude_import, "1.2.0", None, None),
     /// Used to identify crates that contain the profiler runtime.
@@ -217,6 +215,8 @@ declare_features! (
     (active, linkage, "1.0.0", Some(29603), None),
     /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed.
     (active, needs_panic_runtime, "1.10.0", Some(32837), None),
+    /// Allows using `+bundled,+whole-archive` native libs.
+    (active, packed_bundled_libs, "CURRENT_RUSTC_VERSION", Some(108081), None),
     /// Allows using the `#![panic_runtime]` attribute.
     (active, panic_runtime, "1.10.0", Some(32837), None),
     /// Allows using `#[rustc_allow_const_fn_unstable]`.
@@ -473,6 +473,8 @@ declare_features! (
     (active, no_sanitize, "1.42.0", Some(39699), None),
     /// Allows using the `non_exhaustive_omitted_patterns` lint.
     (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
+    /// Allows `for<T>` binders in where-clauses
+    (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(1), None),
     /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
     /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
     /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 7cb3b6e1525..80ec1caf521 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -574,14 +574,11 @@ impl<'hir> Generics<'hir> {
 
     /// If there are generic parameters, return where to introduce a new one.
     pub fn span_for_param_suggestion(&self) -> Option<Span> {
-        if self.params.iter().any(|p| self.span.contains(p.span)) {
+        self.params.iter().any(|p| self.span.contains(p.span)).then(|| {
             // `fn foo<A>(t: impl Trait)`
             //          ^ suggest `, T: Trait` here
-            let span = self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo();
-            Some(span)
-        } else {
-            None
-        }
+            self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo()
+        })
     }
 
     /// `Span` where further predicates would be suggested, accounting for trailing commas, like
@@ -639,7 +636,7 @@ impl<'hir> Generics<'hir> {
                 // We include bounds that come from a `#[derive(_)]` but point at the user's code,
                 // as we use this method to get a span appropriate for suggestions.
                 let bs = bound.span();
-                if bs.can_be_used_for_suggestions() { Some(bs.shrink_to_hi()) } else { None }
+                bs.can_be_used_for_suggestions().then(|| bs.shrink_to_hi())
             },
         )
     }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 46dc4141e66..221721f5909 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -14,7 +14,7 @@ use crate::errors::{
     AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
     TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified,
 };
-use crate::middle::resolve_lifetime as rl;
+use crate::middle::resolve_bound_vars as rbv;
 use crate::require_c_abi_if_c_variadic;
 use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -225,32 +225,29 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let tcx = self.tcx();
         let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
 
-        match tcx.named_region(lifetime.hir_id) {
-            Some(rl::Region::Static) => tcx.lifetimes.re_static,
+        match tcx.named_bound_var(lifetime.hir_id) {
+            Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
 
-            Some(rl::Region::LateBound(debruijn, index, def_id)) => {
+            Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
                 let name = lifetime_name(def_id.expect_local());
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::from_u32(index),
                     kind: ty::BrNamed(def_id, name),
                 };
-                tcx.mk_region(ty::ReLateBound(debruijn, br))
+                tcx.mk_re_late_bound(debruijn, br)
             }
 
-            Some(rl::Region::EarlyBound(def_id)) => {
+            Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
                 let name = tcx.hir().ty_param_name(def_id.expect_local());
                 let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.param_def_id_to_index[&def_id];
-                tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }))
+                tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, index, name })
             }
 
-            Some(rl::Region::Free(scope, id)) => {
+            Some(rbv::ResolvedArg::Free(scope, id)) => {
                 let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                    scope,
-                    bound_region: ty::BrNamed(id, name),
-                }))
+                tcx.mk_re_free(scope, ty::BrNamed(id, name))
 
                 // (*) -- not late-bound, won't change
             }
@@ -263,7 +260,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     // elision. `resolve_lifetime` should have
                     // reported an error in this case -- but if
                     // not, let's error out.
-                    tcx.re_error_with_message(lifetime.ident.span, "unelided lifetime in signature")
+                    tcx.mk_re_error_with_message(
+                        lifetime.ident.span,
+                        "unelided lifetime in signature",
+                    )
                 })
             }
         }
@@ -477,7 +477,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             debug!(?param, "unelided lifetime in signature");
 
                             // This indicates an illegal lifetime in a non-assoc-trait position
-                            tcx.re_error_with_message(self.span, "unelided lifetime in signature")
+                            tcx.mk_re_error_with_message(
+                                self.span,
+                                "unelided lifetime in signature",
+                            )
                         })
                         .into(),
                     GenericParamDefKind::Type { has_default, .. } => {
@@ -1604,7 +1607,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             self.ast_region_to_region(lifetime, None)
         } else {
             self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
-                if tcx.named_region(lifetime.hir_id).is_some() {
+                if tcx.named_bound_var(lifetime.hir_id).is_some() {
                     self.ast_region_to_region(lifetime, None)
                 } else {
                     self.re_infer(None, span).unwrap_or_else(|| {
@@ -1622,7 +1625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         } else {
                             err.emit()
                         };
-                        tcx.re_error(e)
+                        tcx.mk_re_error(e)
                     })
                 }
             })
@@ -2597,6 +2600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         opt_self_ty: Option<Ty<'tcx>>,
         path: &hir::Path<'_>,
+        hir_id: hir::HirId,
         permit_variants: bool,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
@@ -2660,11 +2664,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     }
                 });
 
-                let def_id = def_id.expect_local();
-                let item_def_id = tcx.hir().ty_param_owner(def_id);
-                let generics = tcx.generics_of(item_def_id);
-                let index = generics.param_def_id_to_index[&def_id.to_def_id()];
-                tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
+                match tcx.named_bound_var(hir_id) {
+                    Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
+                        let name =
+                            tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
+                        let br = ty::BoundTy {
+                            var: ty::BoundVar::from_u32(index),
+                            kind: ty::BoundTyKind::Param(def_id, name),
+                        };
+                        tcx.mk_ty(ty::Bound(debruijn, br))
+                    }
+                    Some(rbv::ResolvedArg::EarlyBound(_)) => {
+                        let def_id = def_id.expect_local();
+                        let item_def_id = tcx.hir().ty_param_owner(def_id);
+                        let generics = tcx.generics_of(item_def_id);
+                        let index = generics.param_def_id_to_index[&def_id.to_def_id()];
+                        tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
+                    }
+                    arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
+                }
             }
             Res::SelfTyParam { .. } => {
                 // `Self` in trait or type alias.
@@ -2867,14 +2885,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             hir::TyKind::BareFn(bf) => {
                 require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span);
 
-                tcx.mk_fn_ptr(self.ty_of_fn(
+                let fn_ptr_ty = tcx.mk_fn_ptr(self.ty_of_fn(
                     ast_ty.hir_id,
                     bf.unsafety,
                     bf.abi,
                     bf.decl,
                     None,
                     Some(ast_ty),
-                ))
+                ));
+
+                if let Some(guar) =
+                    deny_non_region_late_bound(tcx, bf.generic_params, "function pointer")
+                {
+                    tcx.ty_error_with_guaranteed(guar)
+                } else {
+                    fn_ptr_ty
+                }
             }
             hir::TyKind::TraitObject(bounds, lifetime, repr) => {
                 self.maybe_lint_bare_trait(ast_ty, in_path);
@@ -2882,12 +2908,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
                     TraitObjectSyntax::DynStar => ty::DynStar,
                 };
-                self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr)
+
+                let object_ty = self.conv_object_ty_poly_trait_ref(
+                    ast_ty.span,
+                    bounds,
+                    lifetime,
+                    borrowed,
+                    repr,
+                );
+
+                if let Some(guar) = bounds.iter().find_map(|trait_ref| {
+                    deny_non_region_late_bound(tcx, trait_ref.bound_generic_params, "trait object")
+                }) {
+                    tcx.ty_error_with_guaranteed(guar)
+                } else {
+                    object_ty
+                }
             }
             hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
                 debug!(?maybe_qself, ?path);
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
-                self.res_to_ty(opt_self_ty, path, false)
+                self.res_to_ty(opt_self_ty, path, ast_ty.hir_id, false)
             }
             &hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
                 let opaque_ty = tcx.hir().item(item_id);
@@ -3343,3 +3384,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
     }
 }
+
+fn deny_non_region_late_bound(
+    tcx: TyCtxt<'_>,
+    params: &[hir::GenericParam<'_>],
+    where_: &str,
+) -> Option<ErrorGuaranteed> {
+    params.iter().find_map(|bad_param| {
+        let what = match bad_param.kind {
+            hir::GenericParamKind::Type { .. } => "type",
+            hir::GenericParamKind::Const { .. } => "const",
+            hir::GenericParamKind::Lifetime { .. } => return None,
+        };
+
+        let mut diag = tcx.sess.struct_span_err(
+            bad_param.span,
+            format!("late-bound {what} parameter not allowed on {where_} types"),
+        );
+
+        Some(if tcx.features().non_lifetime_binders { diag.emit() } else { diag.delay_as_bug() })
+    })
+}
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 6b0eade2d32..94e1fcebccd 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -464,14 +464,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         if let ty::ReFree(fr) = *r {
-            self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                bound_region: self
-                    .mapping
-                    .get(&fr.bound_region)
-                    .copied()
-                    .unwrap_or(fr.bound_region),
-                ..fr
-            }))
+            self.tcx.mk_re_free(
+                fr.scope,
+                self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region),
+            )
         } else {
             r
         }
@@ -777,13 +773,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                     }
                     let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
                     else {
-                        return tcx.re_error_with_message(return_span, "expected ReFree to map to ReEarlyBound")
+                        return tcx.mk_re_error_with_message(return_span, "expected ReFree to map to ReEarlyBound")
                     };
-                    tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+                    tcx.mk_re_early_bound(ty::EarlyBoundRegion {
                         def_id: e.def_id,
                         name: e.name,
                         index: (e.index as usize - num_trait_substs + num_impl_substs) as u32,
-                    }))
+                    })
                 });
                 debug!(%ty);
                 collected_tys.insert(def_id, ty);
@@ -1920,10 +1916,10 @@ pub(super) fn check_type_bounds<'tcx>(
             let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
             let bound_var = ty::BoundVariableKind::Region(kind);
             bound_vars.push(bound_var);
-            tcx.mk_region(ty::ReLateBound(
+            tcx.mk_re_late_bound(
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
-            ))
+            )
             .into()
         }
         GenericParamDefKind::Const { .. } => {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 955cacf03b1..4fc37856dfc 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -149,14 +149,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     );
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
-            let region = tcx.mk_region(ty::ReLateBound(
+            let region = tcx.mk_re_late_bound(
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
-            ));
-            let env_region = tcx.mk_region(ty::ReLateBound(
+            );
+            let env_region = tcx.mk_re_late_bound(
                 ty::INNERMOST,
                 ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
-            ));
+            );
             let va_list_ty = tcx.bound_type_of(did).subst(tcx, &[region.into()]);
             (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
         })
@@ -377,9 +377,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                     ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
                 (
                     1,
-                    vec![
-                        tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)),
-                    ],
+                    vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
                     tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
                 )
             }
@@ -430,8 +428,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             sym::raw_eq => {
                 let br =
                     ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
-                let param_ty =
-                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
+                let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
                 (1, vec![param_ty; 2], tcx.types.bool)
             }
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index c64d507f828..ee39fde1dcb 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -607,12 +607,11 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
                 // Same for the region. In our example, 'a corresponds
                 // to the 'me parameter.
                 let region_param = gat_generics.param_at(*region_a_idx, tcx);
-                let region_param =
-                    tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
-                        def_id: region_param.def_id,
-                        index: region_param.index,
-                        name: region_param.name,
-                    }));
+                let region_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                    def_id: region_param.def_id,
+                    index: region_param.index,
+                    name: region_param.name,
+                });
                 // The predicate we expect to see. (In our example,
                 // `Self: 'me`.)
                 let clause = ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
@@ -645,20 +644,18 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
                 debug!("required clause: {region_a} must outlive {region_b}");
                 // Translate into the generic parameters of the GAT.
                 let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
-                let region_a_param =
-                    tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
-                        def_id: region_a_param.def_id,
-                        index: region_a_param.index,
-                        name: region_a_param.name,
-                    }));
+                let region_a_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                    def_id: region_a_param.def_id,
+                    index: region_a_param.index,
+                    name: region_a_param.name,
+                });
                 // Same for the region.
                 let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
-                let region_b_param =
-                    tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
-                        def_id: region_b_param.def_id,
-                        index: region_b_param.index,
-                        name: region_b_param.name,
-                    }));
+                let region_b_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                    def_id: region_b_param.def_id,
+                    index: region_b_param.index,
+                    name: region_b_param.name,
+                });
                 // The predicate we expect to see.
                 let clause = ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
                     ty::OutlivesPredicate(region_a_param, region_b_param),
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 9f33d84ab52..8ebe576a224 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -41,8 +41,8 @@ use std::iter;
 
 mod generics_of;
 mod item_bounds;
-mod lifetimes;
 mod predicates_of;
+mod resolve_bound_vars;
 mod type_of;
 
 ///////////////////////////////////////////////////////////////////////////
@@ -53,7 +53,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 }
 
 pub fn provide(providers: &mut Providers) {
-    lifetimes::provide(providers);
+    resolve_bound_vars::provide(providers);
     *providers = Providers {
         opt_const_param_of: type_of::opt_const_param_of,
         type_of: type_of::type_of,
@@ -458,13 +458,11 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
                                         self.tcx.replace_late_bound_regions_uncached(
                                             poly_trait_ref,
                                             |_| {
-                                                self.tcx.mk_region(ty::ReEarlyBound(
-                                                    ty::EarlyBoundRegion {
-                                                        def_id: item_def_id,
-                                                        index: 0,
-                                                        name: Symbol::intern(&lt_name),
-                                                    },
-                                                ))
+                                                self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+                                                    def_id: item_def_id,
+                                                    index: 0,
+                                                    name: Symbol::intern(&lt_name),
+                                                })
                                             }
                                         ),
                                     ),
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 014ee9fcc20..7bcaeadbcf6 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -1,4 +1,4 @@
-use crate::middle::resolve_lifetime as rl;
+use crate::middle::resolve_bound_vars as rbv;
 use hir::{
     intravisit::{self, Visitor},
     GenericParamKind, HirId, Node,
@@ -394,10 +394,11 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
                 return;
             }
 
-            match self.tcx.named_region(lt.hir_id) {
-                Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
-                Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {}
-                Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => {
+            match self.tcx.named_bound_var(lt.hir_id) {
+                Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {}
+                Some(rbv::ResolvedArg::LateBound(debruijn, _, _))
+                    if debruijn < self.outer_index => {}
+                Some(rbv::ResolvedArg::LateBound(..) | rbv::ResolvedArg::Free(..)) | None => {
                     self.has_late_bound_regions = Some(lt.ident.span);
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index d0d67ae9257..5ac9003556d 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -284,11 +284,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
 
             let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
 
-            let dup_region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+            let dup_region = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
                 def_id: dup_def,
                 index: dup_index,
                 name: duplicate.name.ident().name,
-            }));
+            });
             predicates.push((
                 ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
                     ty::OutlivesPredicate(orig_region, dup_region),
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index d8606f759b2..8c388040fbf 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -16,7 +16,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::*;
+use rustc_middle::middle::resolve_bound_vars::*;
 use rustc_middle::ty::{self, ir::TypeVisitor, DefIdTree, TyCtxt, TypeSuperVisitable};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{sym, Ident};
@@ -24,59 +24,61 @@ use rustc_span::Span;
 use std::fmt;
 
 trait RegionExt {
-    fn early(param: &GenericParam<'_>) -> (LocalDefId, Region);
+    fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
 
-    fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
+    fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
 
     fn id(&self) -> Option<DefId>;
 
-    fn shifted(self, amount: u32) -> Region;
+    fn shifted(self, amount: u32) -> ResolvedArg;
 }
 
-impl RegionExt for Region {
-    fn early(param: &GenericParam<'_>) -> (LocalDefId, Region) {
-        debug!("Region::early: def_id={:?}", param.def_id);
-        (param.def_id, Region::EarlyBound(param.def_id.to_def_id()))
+impl RegionExt for ResolvedArg {
+    fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
+        debug!("ResolvedArg::early: def_id={:?}", param.def_id);
+        (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
     }
 
-    fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, Region) {
+    fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
         let depth = ty::INNERMOST;
         debug!(
-            "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
+            "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
             idx, param, depth, param.def_id,
         );
-        (param.def_id, Region::LateBound(depth, idx, param.def_id.to_def_id()))
+        (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id()))
     }
 
     fn id(&self) -> Option<DefId> {
         match *self {
-            Region::Static => None,
+            ResolvedArg::StaticLifetime => None,
 
-            Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id),
+            ResolvedArg::EarlyBound(id)
+            | ResolvedArg::LateBound(_, _, id)
+            | ResolvedArg::Free(_, id) => Some(id),
         }
     }
 
-    fn shifted(self, amount: u32) -> Region {
+    fn shifted(self, amount: u32) -> ResolvedArg {
         match self {
-            Region::LateBound(debruijn, idx, id) => {
-                Region::LateBound(debruijn.shifted_in(amount), idx, id)
+            ResolvedArg::LateBound(debruijn, idx, id) => {
+                ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
             }
             _ => self,
         }
     }
 }
 
-/// Maps the id of each lifetime reference to the lifetime decl
+/// Maps the id of each bound variable reference to the variable decl
 /// that it corresponds to.
 ///
-/// FIXME. This struct gets converted to a `ResolveLifetimes` for
+/// FIXME. This struct gets converted to a `ResolveBoundVars` for
 /// actual use. It has the same data, but indexed by `LocalDefId`. This
 /// is silly.
 #[derive(Debug, Default)]
-struct NamedRegionMap {
-    // maps from every use of a named (not anonymous) lifetime to a
-    // `Region` describing how that region is bound
-    defs: HirIdMap<Region>,
+struct NamedVarMap {
+    // maps from every use of a named (not anonymous) bound var to a
+    // `ResolvedArg` describing how that variable is bound
+    defs: HirIdMap<ResolvedArg>,
 
     // Maps relevant hir items to the bound vars on them. These include:
     // - function defs
@@ -87,9 +89,9 @@ struct NamedRegionMap {
     late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
 }
 
-struct LifetimeContext<'a, 'tcx> {
+struct BoundVarContext<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    map: &'a mut NamedRegionMap,
+    map: &'a mut NamedVarMap,
     scope: ScopeRef<'a>,
 }
 
@@ -102,7 +104,7 @@ enum Scope<'a> {
     Binder {
         /// We use an IndexMap here because we want these lifetimes in order
         /// for diagnostics.
-        lifetimes: FxIndexMap<LocalDefId, Region>,
+        bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
 
         scope_type: BinderScopeType,
 
@@ -141,7 +143,7 @@ enum Scope<'a> {
     /// inferred in a function body or potentially error outside one),
     /// for the default choice of lifetime in a trait object type.
     ObjectLifetimeDefault {
-        lifetime: Option<Region>,
+        lifetime: Option<ResolvedArg>,
         s: ScopeRef<'a>,
     },
 
@@ -150,7 +152,7 @@ enum Scope<'a> {
     /// lifetimes encountered when identifying the trait that an associated type
     /// is declared on.
     Supertrait {
-        lifetimes: Vec<ty::BoundVariableKind>,
+        bound_vars: Vec<ty::BoundVariableKind>,
         s: ScopeRef<'a>,
     },
 
@@ -185,9 +187,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
 impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {
-            Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f
+            Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
                 .debug_struct("Binder")
-                .field("lifetimes", lifetimes)
+                .field("bound_vars", bound_vars)
                 .field("scope_type", scope_type)
                 .field("hir_id", hir_id)
                 .field("where_bound_origin", where_bound_origin)
@@ -202,9 +204,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("lifetime", lifetime)
                 .field("s", &"..")
                 .finish(),
-            Scope::Supertrait { lifetimes, s: _ } => f
+            Scope::Supertrait { bound_vars, s: _ } => f
                 .debug_struct("Supertrait")
-                .field("lifetimes", lifetimes)
+                .field("bound_vars", bound_vars)
                 .field("s", &"..")
                 .finish(),
             Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
@@ -219,27 +221,27 @@ type ScopeRef<'a> = &'a Scope<'a>;
 
 pub(crate) fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
-        resolve_lifetimes,
+        resolve_bound_vars,
 
-        named_region_map: |tcx, id| tcx.resolve_lifetimes(id).defs.get(&id),
+        named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
         is_late_bound_map,
         object_lifetime_default,
-        late_bound_vars_map: |tcx, id| tcx.resolve_lifetimes(id).late_bound_vars.get(&id),
+        late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id),
 
         ..*providers
     };
 }
 
-/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
+/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
 /// You should not read the result of this query directly, but rather use
-/// `named_region_map`, `is_late_bound_map`, etc.
+/// `named_variable_map`, `is_late_bound_map`, etc.
 #[instrument(level = "debug", skip(tcx))]
-fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLifetimes {
-    let mut named_region_map =
-        NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
-    let mut visitor = LifetimeContext {
+fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
+    let mut named_variable_map =
+        NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() };
+    let mut visitor = BoundVarContext {
         tcx,
-        map: &mut named_region_map,
+        map: &mut named_variable_map,
         scope: &Scope::Root { opt_parent_item: None },
     };
     match tcx.hir().owner(local_def_id) {
@@ -260,13 +262,13 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
         hir::OwnerNode::Crate(_) => {}
     }
 
-    let mut rl = ResolveLifetimes::default();
+    let mut rl = ResolveBoundVars::default();
 
-    for (hir_id, v) in named_region_map.defs {
+    for (hir_id, v) in named_variable_map.defs {
         let map = rl.defs.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
-    for (hir_id, v) in named_region_map.late_bound_vars {
+    for (hir_id, v) in named_variable_map.late_bound_vars {
         let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
@@ -276,21 +278,33 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
     rl
 }
 
-fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &Region) -> ty::BoundVariableKind {
-    match region {
-        Region::LateBound(_, _, def_id) => {
+fn late_arg_as_bound_arg<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    arg: &ResolvedArg,
+    param: &GenericParam<'tcx>,
+) -> ty::BoundVariableKind {
+    match arg {
+        ResolvedArg::LateBound(_, _, def_id) => {
             let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
-            ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
+            match param.kind {
+                GenericParamKind::Lifetime { .. } => {
+                    ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
+                }
+                GenericParamKind::Type { .. } => {
+                    ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name))
+                }
+                GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
+            }
         }
-        _ => bug!("{:?} is not a late region", region),
+        _ => bug!("{:?} is not a late argument", arg),
     }
 }
 
-impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
     fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
         let mut scope = self.scope;
-        let mut supertrait_lifetimes = vec![];
+        let mut supertrait_bound_vars = vec![];
         loop {
             match scope {
                 Scope::Body { .. } | Scope::Root { .. } => {
@@ -301,14 +315,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     scope = s;
                 }
 
-                Scope::Supertrait { s, lifetimes } => {
-                    supertrait_lifetimes = lifetimes.clone();
+                Scope::Supertrait { s, bound_vars } => {
+                    supertrait_bound_vars = bound_vars.clone();
                     scope = s;
                 }
 
                 Scope::TraitRefBoundary { .. } => {
                     // We should only see super trait lifetimes if there is a `Binder` above
-                    assert!(supertrait_lifetimes.is_empty());
+                    assert!(supertrait_bound_vars.is_empty());
                     break (vec![], BinderScopeType::Normal);
                 }
 
@@ -316,14 +330,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     // Nested poly trait refs have the binders concatenated
                     let mut full_binders =
                         self.map.late_bound_vars.entry(*hir_id).or_default().clone();
-                    full_binders.extend(supertrait_lifetimes.into_iter());
+                    full_binders.extend(supertrait_bound_vars.into_iter());
                     break (full_binders, BinderScopeType::Concatenating);
                 }
             }
         }
     }
 }
-impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
     fn nested_visit_map(&mut self) -> Self::Map {
@@ -386,14 +400,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 }
             }
 
-            let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
+            let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
                 bound_generic_params
                     .iter()
-                    .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
                     .enumerate()
                     .map(|(late_bound_idx, param)| {
-                        let pair = Region::late(late_bound_idx as u32, param);
-                        let r = late_region_as_bound_region(self.tcx, &pair.1);
+                        let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                        let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
                         (pair, r)
                     })
                     .unzip();
@@ -401,7 +414,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             self.record_late_bound_vars(e.hir_id, binders);
             let scope = Scope::Binder {
                 hir_id: e.hir_id,
-                lifetimes,
+                bound_vars,
                 s: self.scope,
                 scope_type: BinderScopeType::Normal,
                 where_bound_origin: None,
@@ -461,7 +474,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 // conservatively add all resolved lifetimes. Otherwise we run into problems in
                 // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
                 let parent_item = self.tcx.hir().get_parent_item(item.hir_id());
-                let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(parent_item);
+                let resolved_lifetimes: &ResolveBoundVars =
+                    self.tcx.resolve_bound_vars(parent_item);
                 // We need to add *all* deps, since opaque tys may want them from *us*
                 for (&owner, defs) in resolved_lifetimes.defs.iter() {
                     defs.iter().for_each(|(&local_id, region)| {
@@ -478,35 +492,33 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 }
             }
             hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_),
+                origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
                 generics,
                 ..
             }) => {
                 // We want to start our early-bound indices at the end of the parent scope,
                 // not including any parent `impl Trait`s.
-                let mut lifetimes = FxIndexMap::default();
+                let mut bound_vars = FxIndexMap::default();
                 debug!(?generics.params);
                 for param in generics.params {
-                    match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            let (def_id, reg) = Region::early(&param);
-                            lifetimes.insert(def_id, reg);
-                        }
-                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
-                    }
+                    let (def_id, reg) = ResolvedArg::early(&param);
+                    bound_vars.insert(def_id, reg);
                 }
 
-                let scope = Scope::Binder {
-                    hir_id: item.hir_id(),
-                    lifetimes,
-                    s: self.scope,
-                    scope_type: BinderScopeType::Normal,
-                    where_bound_origin: None,
-                };
+                let scope = Scope::Root { opt_parent_item: Some(parent) };
                 self.with(scope, |this| {
-                    let scope = Scope::TraitRefBoundary { s: this.scope };
-                    this.with(scope, |this| intravisit::walk_item(this, item))
-                });
+                    let scope = Scope::Binder {
+                        hir_id: item.hir_id(),
+                        bound_vars,
+                        s: this.scope,
+                        scope_type: BinderScopeType::Normal,
+                        where_bound_origin: None,
+                    };
+                    this.with(scope, |this| {
+                        let scope = Scope::TraitRefBoundary { s: this.scope };
+                        this.with(scope, |this| intravisit::walk_item(this, item))
+                    });
+                })
             }
             hir::ItemKind::TyAlias(_, generics)
             | hir::ItemKind::Enum(_, generics)
@@ -516,18 +528,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             | hir::ItemKind::TraitAlias(generics, ..)
             | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
                 // These kinds of items have only early-bound lifetime parameters.
-                let lifetimes = generics
-                    .params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
-                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
-                    })
-                    .collect();
+                let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
                 self.record_late_bound_vars(item.hir_id(), vec![]);
                 let scope = Scope::Binder {
                     hir_id: item.hir_id(),
-                    lifetimes,
+                    bound_vars,
                     scope_type: BinderScopeType::Normal,
                     s: self.scope,
                     where_bound_origin: None,
@@ -562,21 +567,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
         match ty.kind {
             hir::TyKind::BareFn(c) => {
-                let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
+                let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
                     .generic_params
                     .iter()
-                    .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
                     .enumerate()
                     .map(|(late_bound_idx, param)| {
-                        let pair = Region::late(late_bound_idx as u32, param);
-                        let r = late_region_as_bound_region(self.tcx, &pair.1);
+                        let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                        let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
                         (pair, r)
                     })
                     .unzip();
                 self.record_late_bound_vars(ty.hir_id, binders);
                 let scope = Scope::Binder {
                     hir_id: ty.hir_id,
-                    lifetimes,
+                    bound_vars,
                     s: self.scope,
                     scope_type: BinderScopeType::Normal,
                     where_bound_origin: None,
@@ -674,7 +678,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     // well-supported at the moment, so this doesn't work.
                     // In the future, this should be fixed and this error should be removed.
                     let def = self.map.defs.get(&lifetime.hir_id).cloned();
-                    let Some(Region::LateBound(_, _, def_id)) = def else {
+                    let Some(ResolvedArg::LateBound(_, _, def_id)) = def else {
                         continue
                     };
                     let Some(def_id) = def_id.as_local() else {
@@ -722,18 +726,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             }
             Type(bounds, ty) => {
                 let generics = &trait_item.generics;
-                let lifetimes = generics
-                    .params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
-                        GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
-                    })
-                    .collect();
+                let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
                 self.record_late_bound_vars(trait_item.hir_id(), vec![]);
                 let scope = Scope::Binder {
                     hir_id: trait_item.hir_id(),
-                    lifetimes,
+                    bound_vars,
                     s: self.scope,
                     scope_type: BinderScopeType::Normal,
                     where_bound_origin: None,
@@ -768,18 +765,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             }),
             Type(ty) => {
                 let generics = &impl_item.generics;
-                let lifetimes: FxIndexMap<LocalDefId, Region> = generics
-                    .params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
-                        GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
-                    })
-                    .collect();
+                let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
+                    generics.params.iter().map(ResolvedArg::early).collect();
                 self.record_late_bound_vars(impl_item.hir_id(), vec![]);
                 let scope = Scope::Binder {
                     hir_id: impl_item.hir_id(),
-                    lifetimes,
+                    bound_vars,
                     s: self.scope,
                     scope_type: BinderScopeType::Normal,
                     where_bound_origin: None,
@@ -803,7 +794,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
         match lifetime_ref.res {
-            hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
+            hir::LifetimeName::Static => {
+                self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
+            }
             hir::LifetimeName::Param(param_def_id) => {
                 self.resolve_lifetime_ref(param_def_id, lifetime_ref)
             }
@@ -814,13 +807,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         }
     }
 
-    fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
+    fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) {
         for (i, segment) in path.segments.iter().enumerate() {
             let depth = path.segments.len() - i - 1;
             if let Some(args) = segment.args {
                 self.visit_segment_args(path.res, depth, args);
             }
         }
+        if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
+            self.resolve_type_ref(param_def_id.expect_local(), hir_id);
+        }
     }
 
     fn visit_fn(
@@ -869,24 +865,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         origin,
                         ..
                     }) => {
-                        let lifetimes: FxIndexMap<LocalDefId, Region> =
+
+                        let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
                             bound_generic_params
-                                .iter()
-                                .filter(|param| {
-                                    matches!(param.kind, GenericParamKind::Lifetime { .. })
-                                })
-                                .enumerate()
-                                .map(|(late_bound_idx, param)| {
-                                        Region::late(late_bound_idx as u32, param)
-                                })
-                                .collect();
-                        let binders: Vec<_> =
-                            lifetimes
-                                .iter()
-                                .map(|(_, region)| {
-                                     late_region_as_bound_region(this.tcx, region)
-                                })
-                                .collect();
+                            .iter()
+                            .enumerate()
+                            .map(|(late_bound_idx, param)| {
+                                let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                                let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
+                                (pair, r)
+                            })
+                            .unzip();
                         this.record_late_bound_vars(hir_id, binders.clone());
                         // Even if there are no lifetimes defined here, we still wrap it in a binder
                         // scope. If there happens to be a nested poly trait ref (an error), that
@@ -894,7 +883,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         // being wrong.
                         let scope = Scope::Binder {
                             hir_id,
-                            lifetimes,
+                            bound_vars,
                             s: this.scope,
                             scope_type: BinderScopeType::Normal,
                             where_bound_origin: Some(origin),
@@ -920,7 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                                 if lt.res != hir::LifetimeName::Static {
                                     continue;
                                 }
-                                this.insert_lifetime(lt, Region::Static);
+                                this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
                                 this.tcx
                                     .sess
                                     .struct_span_warn(
@@ -964,7 +953,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 self.record_late_bound_vars(*hir_id, binders);
                 let scope = Scope::Binder {
                     hir_id: *hir_id,
-                    lifetimes: FxIndexMap::default(),
+                    bound_vars: FxIndexMap::default(),
                     s: self.scope,
                     scope_type,
                     where_bound_origin: None,
@@ -983,16 +972,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
 
         let initial_bound_vars = binders.len() as u32;
-        let mut lifetimes: FxIndexMap<LocalDefId, Region> = FxIndexMap::default();
-        let binders_iter = trait_ref
-            .bound_generic_params
-            .iter()
-            .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
-            .enumerate()
-            .map(|(late_bound_idx, param)| {
-                let pair = Region::late(initial_bound_vars + late_bound_idx as u32, param);
-                let r = late_region_as_bound_region(self.tcx, &pair.1);
-                lifetimes.insert(pair.0, pair.1);
+        let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
+        let binders_iter =
+            trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
+                let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
+                let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
+                bound_vars.insert(pair.0, pair.1);
                 r
             });
         binders.extend(binders_iter);
@@ -1006,7 +991,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         // refs.
         let scope = Scope::Binder {
             hir_id: trait_ref.trait_ref.hir_ref_id,
-            lifetimes,
+            bound_vars,
             s: self.scope,
             scope_type,
             where_bound_origin: None,
@@ -1063,13 +1048,13 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifeti
     }
 }
 
-impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
     where
-        F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
+        F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
     {
-        let LifetimeContext { tcx, map, .. } = self;
-        let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope };
+        let BoundVarContext { tcx, map, .. } = self;
+        let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
         let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
         {
             let _enter = span.enter();
@@ -1110,23 +1095,25 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         generics: &'tcx hir::Generics<'tcx>,
         walk: F,
     ) where
-        F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
+        F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
     {
         let mut named_late_bound_vars = 0;
-        let lifetimes: FxIndexMap<LocalDefId, Region> = generics
+        let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
             .params
             .iter()
-            .filter_map(|param| match param.kind {
+            .map(|param| match param.kind {
                 GenericParamKind::Lifetime { .. } => {
                     if self.tcx.is_late_bound(param.hir_id) {
                         let late_bound_idx = named_late_bound_vars;
                         named_late_bound_vars += 1;
-                        Some(Region::late(late_bound_idx, param))
+                        ResolvedArg::late(late_bound_idx, param)
                     } else {
-                        Some(Region::early(param))
+                        ResolvedArg::early(param)
                     }
                 }
-                GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
+                GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
+                    ResolvedArg::early(param)
+                }
             })
             .collect();
 
@@ -1139,14 +1126,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             })
             .enumerate()
             .map(|(late_bound_idx, param)| {
-                let pair = Region::late(late_bound_idx as u32, param);
-                late_region_as_bound_region(self.tcx, &pair.1)
+                let pair = ResolvedArg::late(late_bound_idx as u32, param);
+                late_arg_as_bound_arg(self.tcx, &pair.1, param)
             })
             .collect();
         self.record_late_bound_vars(hir_id, binders);
         let scope = Scope::Binder {
             hir_id,
-            lifetimes,
+            bound_vars,
             s: self.scope,
             scope_type: BinderScopeType::Normal,
             where_bound_origin: None,
@@ -1177,15 +1164,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 Scope::Root { opt_parent_item } => {
                     if let Some(parent_item) = opt_parent_item
                         && let parent_generics = self.tcx.generics_of(parent_item)
-                        && parent_generics.param_def_id_to_index.contains_key(&region_def_id.to_def_id())
+                        && parent_generics.param_def_id_to_index(self.tcx, region_def_id.to_def_id()).is_some()
                     {
-                        break Some(Region::EarlyBound(region_def_id.to_def_id()));
+                        break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id()));
                     }
                     break None;
                 }
 
-                Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
-                    if let Some(&def) = lifetimes.get(&region_def_id) {
+                Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
+                    if let Some(&def) = bound_vars.get(&region_def_id) {
                         break Some(def.shifted(late_depth));
                     }
                     match scope_type {
@@ -1259,7 +1246,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         };
 
         if let Some(mut def) = result {
-            if let Region::EarlyBound(..) = def {
+            if let ResolvedArg::EarlyBound(..) = def {
                 // Do not free early-bound regions, only late-bound ones.
             } else if let Some(body_id) = outermost_body {
                 let fn_id = self.tcx.hir().body_owner(body_id);
@@ -1275,10 +1262,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         kind: hir::ImplItemKind::Fn(..),
                         ..
                     }) => {
-                        def = Region::Free(owner_id.to_def_id(), def.id().unwrap());
+                        def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap());
                     }
                     Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
-                        def = Region::Free(closure.def_id.to_def_id(), def.id().unwrap());
+                        def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap());
                     }
                     _ => {}
                 }
@@ -1329,6 +1316,57 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         );
     }
 
+    fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) {
+        // Walk up the scope chain, tracking the number of fn scopes
+        // that we pass through, until we find a lifetime with the
+        // given name or we run out of scopes.
+        // search.
+        let mut late_depth = 0;
+        let mut scope = self.scope;
+        let result = loop {
+            match *scope {
+                Scope::Body { s, .. } => {
+                    scope = s;
+                }
+
+                Scope::Root { opt_parent_item } => {
+                    if let Some(parent_item) = opt_parent_item
+                        && let parent_generics = self.tcx.generics_of(parent_item)
+                        && parent_generics.param_def_id_to_index(self.tcx, param_def_id.to_def_id()).is_some()
+                    {
+                        break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id()));
+                    }
+                    break None;
+                }
+
+                Scope::Binder { ref bound_vars, scope_type, s, .. } => {
+                    if let Some(&def) = bound_vars.get(&param_def_id) {
+                        break Some(def.shifted(late_depth));
+                    }
+                    match scope_type {
+                        BinderScopeType::Normal => late_depth += 1,
+                        BinderScopeType::Concatenating => {}
+                    }
+                    scope = s;
+                }
+
+                Scope::Elision { s, .. }
+                | Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::Supertrait { s, .. }
+                | Scope::TraitRefBoundary { s, .. } => {
+                    scope = s;
+                }
+            }
+        };
+
+        if let Some(def) = result {
+            self.map.defs.insert(hir_id, def);
+            return;
+        }
+
+        span_bug!(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}",);
+    }
+
     #[instrument(level = "debug", skip(self))]
     fn visit_segment_args(
         &mut self,
@@ -1415,10 +1453,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     if in_body {
                         None
                     } else {
-                        Some(Region::Static)
+                        Some(ResolvedArg::StaticLifetime)
                     }
                 }
-                ObjectLifetimeDefault::Static => Some(Region::Static),
+                ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
                 ObjectLifetimeDefault::Param(param_def_id) => {
                     // This index can be used with `generic_args` since `parent_count == 0`.
                     let index = generics.param_def_id_to_index[&param_def_id] as usize;
@@ -1507,18 +1545,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         // in the trait ref `YY<...>` in `Item: YY<...>`.
         for binding in generic_args.bindings {
             let scope = Scope::ObjectLifetimeDefault {
-                lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
+                lifetime: if has_lifetime_parameter {
+                    None
+                } else {
+                    Some(ResolvedArg::StaticLifetime)
+                },
                 s: self.scope,
             };
             if let Some(type_def_id) = type_def_id {
-                let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
-                    self.tcx,
-                    type_def_id,
-                    binding.ident,
-                );
+                let bound_vars =
+                    BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
                 self.with(scope, |this| {
                     let scope = Scope::Supertrait {
-                        lifetimes: lifetimes.unwrap_or_default(),
+                        bound_vars: bound_vars.unwrap_or_default(),
                         s: this.scope,
                     };
                     this.with(scope, |this| this.visit_assoc_type_binding(binding));
@@ -1541,7 +1580,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     /// ```
     /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
     /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
-    fn supertrait_hrtb_lifetimes(
+    fn supertrait_hrtb_vars(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
         assoc_name: Ident,
@@ -1626,7 +1665,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     scope = s;
                 }
 
-                Scope::Root { .. } | Scope::Elision { .. } => break Region::Static,
+                Scope::Root { .. } | Scope::Elision { .. } => break ResolvedArg::StaticLifetime,
 
                 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
 
@@ -1641,7 +1680,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
+    fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
         debug!(span = ?lifetime_ref.ident.span);
         self.map.defs.insert(lifetime_ref.hir_id, def);
     }
@@ -1649,7 +1688,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     /// Sometimes we resolve a lifetime, but later find that it is an
     /// error (esp. around impl trait). In that case, we remove the
     /// entry into `map.defs` so as not to confuse later code.
-    fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) {
+    fn uninsert_lifetime_on_error(
+        &mut self,
+        lifetime_ref: &'tcx hir::Lifetime,
+        bad_def: ResolvedArg,
+    ) {
         let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
         assert_eq!(old_value, Some(bad_def));
     }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 54fcccb0c11..600a4efd308 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -259,13 +259,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             }
             TraitItemKind::Const(ty, body_id) => body_id
                 .and_then(|body_id| {
-                    if is_suggestable_infer_ty(ty) {
-                        Some(infer_placeholder_type(
-                            tcx, def_id, body_id, ty.span, item.ident, "constant",
-                        ))
-                    } else {
-                        None
-                    }
+                    is_suggestable_infer_ty(ty)
+                        .then(|| infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant",))
                 })
                 .unwrap_or_else(|| icx.to_ty(ty)),
             TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty),
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index c2fa46e563e..a0f738a2799 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -204,7 +204,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         match tcx.hir().find(hir_id) {
             Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
-                generics.params.is_empty().not().then(|| generics.span)
+                generics.params.is_empty().not().then_some(generics.span)
             }
             _ => {
                 span_bug!(tcx.def_span(def_id), "main has a non-function type");
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 05f6d8e6072..dbd0c5abeac 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -74,15 +74,13 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
     // (as it's created inside the body itself, not passed in from outside).
-    let maybe_va_list = if fn_sig.c_variadic {
+    let maybe_va_list = fn_sig.c_variadic.then(|| {
         let span = body.params.last().unwrap().span;
         let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span));
         let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
 
-        Some(tcx.bound_type_of(va_list_did).subst(tcx, &[region.into()]))
-    } else {
-        None
-    };
+        tcx.bound_type_of(va_list_did).subst(tcx, &[region.into()])
+    });
 
     // Add formal parameters.
     let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 7173239ba61..ba503bf47e7 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1046,7 +1046,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.param_env,
                 )
                 .may_apply()
-                .then(|| deref_ty)
+                .then_some(deref_ty)
         })
     }
 
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 76e87a9e566..de7819e3c6a 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1269,10 +1269,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // ```
                 let ref_ty = match mutability {
                     hir::Mutability::Mut => {
-                        self.tcx.mk_mut_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
+                        self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, checked_ty)
                     }
                     hir::Mutability::Not => {
-                        self.tcx.mk_imm_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
+                        self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, checked_ty)
                     }
                 };
                 if self.can_coerce(ref_ty, expected) {
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 f434fb92289..d13d8ff8270 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
@@ -477,12 +477,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
         // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
         // that struct type.
-        let impl_trait_self_ref: Option<ty::TraitRef<'tcx>> =
-            self.tcx.impl_trait_ref(obligation.impl_def_id).map(|impl_def| impl_def.skip_binder());
-
-        let Some(impl_trait_self_ref) = impl_trait_self_ref else {
-            // It is possible that this is absent. In this case, we make no progress.
-            return Err(expr);
+        let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_def_id) {
+            self.tcx.mk_trait_ref(
+                obligation.impl_def_id,
+                ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_def_id),
+            )
+        } else {
+            self.tcx
+                .impl_trait_ref(obligation.impl_def_id)
+                .map(|impl_def| impl_def.skip_binder())
+                // It is possible that this is absent. In this case, we make no progress.
+                .ok_or(expr)?
         };
 
         // We only really care about the `Self` type itself, which we extract from the ref.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 9c7a84ce198..69a7235802b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -755,15 +755,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         errors.drain_filter(|error| {
-                let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
-                let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
-                let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
-                if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
-                    self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
-                    return true;
-                }
-                false
-            });
+            let Error::Invalid(
+                provided_idx,
+                expected_idx,
+                Compatibility::Incompatible(Some(e)),
+            ) = error else { return false };
+            let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
+            let trace =
+                mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
+            if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
+                self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
+                return true;
+            }
+            false
+        });
 
         // We're done if we found errors, but we already emitted them.
         if errors.is_empty() {
@@ -864,7 +869,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         let mut suggestion_text = SuggestionText::None;
 
+        let ty_to_snippet = |ty: Ty<'tcx>, expected_idx: ExpectedIdx| {
+            if ty.is_unit() {
+                "()".to_string()
+            } else if ty.is_suggestable(tcx, false) {
+                format!("/* {} */", ty)
+            } else if let Some(fn_def_id) = fn_def_id
+                && self.tcx.def_kind(fn_def_id).is_fn_like()
+                && let self_implicit =
+                    matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
+                && let Some(arg) = self.tcx.fn_arg_names(fn_def_id)
+                    .get(expected_idx.as_usize() + self_implicit)
+                && arg.name != kw::SelfLower
+            {
+                format!("/* {} */", arg.name)
+            } else {
+                "/* value */".to_string()
+            }
+        };
+
         let mut errors = errors.into_iter().peekable();
+        let mut suggestions = vec![];
         while let Some(error) = errors.next() {
             match error {
                 Error::Invalid(provided_idx, expected_idx, compatibility) => {
@@ -905,7 +930,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         "".to_string()
                     };
                     labels
-                        .push((provided_span, format!("argument{} unexpected", provided_ty_name)));
+                        .push((provided_span, format!("unexpected argument{}", provided_ty_name)));
+                    let mut span = provided_span;
+                    if arg_idx.index() > 0
+                        && let Some((_, prev)) = provided_arg_tys
+                            .get(ProvidedIdx::from_usize(arg_idx.index() - 1)
+                    ) {
+                        // Include previous comma
+                        span = span.with_lo(prev.hi());
+                    } else if let Some((_, next)) = provided_arg_tys.get(
+                        ProvidedIdx::from_usize(arg_idx.index() + 1),
+                    ) {
+                        // Include next comma
+                        span = span.until(*next);
+                    }
+                    suggestions.push((span, String::new()));
+
                     suggestion_text = match suggestion_text {
                         SuggestionText::None => SuggestionText::Remove(false),
                         SuggestionText::Remove(_) => SuggestionText::Remove(true),
@@ -1095,6 +1135,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
 
+        // Incorporate the argument changes in the removal suggestion.
+        // When a type is *missing*, and the rest are additional, we want to suggest these with a
+        // multipart suggestion, but in order to do so we need to figure out *where* the arg that
+        // was provided but had the wrong type should go, because when looking at `expected_idx`
+        // that is the position in the argument list in the definition, while `provided_idx` will
+        // not be present. So we have to look at what the *last* provided position was, and point
+        // one after to suggest the replacement. FIXME(estebank): This is hacky, and there's
+        // probably a better more involved change we can make to make this work.
+        // For example, if we have
+        // ```
+        // fn foo(i32, &'static str) {}
+        // foo((), (), ());
+        // ```
+        // what should be suggested is
+        // ```
+        // foo(/* i32 */, /* &str */);
+        // ```
+        // which includes the replacement of the first two `()` for the correct type, and the
+        // removal of the last `()`.
+        let mut prev = -1;
+        for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
+            // We want to point not at the *current* argument expression index, but rather at the
+            // index position where it *should have been*, which is *after* the previous one.
+            if let Some(provided_idx) = provided_idx {
+                prev = provided_idx.index() as i64;
+            }
+            let idx = ProvidedIdx::from_usize((prev + 1) as usize);
+            if let None = provided_idx
+                && let Some((_, arg_span)) = provided_arg_tys.get(idx)
+            {
+                // There is a type that was *not* found anywhere, so it isn't a move, but a
+                // replacement and we look at what type it should have been. This will allow us
+                // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
+                // was `fn foo(())`.
+                let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
+                suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
+            }
+        }
+
         // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
         if labels.len() <= 5 {
             for (span, label) in labels {
@@ -1112,7 +1191,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(format!("provide the argument{}", if plural { "s" } else { "" }))
             }
             SuggestionText::Remove(plural) => {
-                Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
+                err.multipart_suggestion(
+                    &format!("remove the extra argument{}", if plural { "s" } else { "" }),
+                    suggestions,
+                    Applicability::HasPlaceholders,
+                );
+                None
             }
             SuggestionText::Swap => Some("swap these arguments".to_string()),
             SuggestionText::Reorder => Some("reorder these arguments".to_string()),
@@ -1151,20 +1235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     // Propose a placeholder of the correct type
                     let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
-                    if expected_ty.is_unit() {
-                        "()".to_string()
-                    } else if expected_ty.is_suggestable(tcx, false) {
-                        format!("/* {} */", expected_ty)
-                    } else if let Some(fn_def_id) = fn_def_id
-                        && self.tcx.def_kind(fn_def_id).is_fn_like()
-                        && let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
-                        && let Some(arg) = self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
-                        && arg.name != kw::SelfLower
-                    {
-                        format!("/* {} */", arg.name)
-                    } else {
-                        "/* value */".to_string()
-                    }
+                    ty_to_snippet(expected_ty, expected_idx)
                 };
                 suggestion += &suggestion_text;
             }
@@ -1669,7 +1740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match *qpath {
             QPath::Resolved(ref maybe_qself, ref path) => {
                 let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
-                let ty = self.astconv().res_to_ty(self_ty, path, true);
+                let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true);
                 (path.res, self.handle_raw_ty(path_span, ty))
             }
             QPath::TypeRelative(ref qself, ref segment) => {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 29ed9a24ecf..3f61a1a83e5 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -271,15 +271,13 @@ pub fn resolve_interior<'a, 'tcx>(
                     },
                     _ => mk_bound_region(None),
                 };
-                let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
+                let r = fcx.tcx.mk_re_late_bound(current_depth, br);
                 r
             });
-            if captured_tys.insert(ty) {
+            captured_tys.insert(ty).then(|| {
                 cause.ty = ty;
-                Some(cause)
-            } else {
-                None
-            }
+                cause
+            })
         })
         .collect();
 
@@ -302,7 +300,7 @@ pub fn resolve_interior<'a, 'tcx>(
                     let var = ty::BoundVar::from_usize(bound_vars.len());
                     bound_vars.push(ty::BoundVariableKind::Region(kind));
                     counter += 1;
-                    fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind }))
+                    fcx.tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var, kind })
                 },
                 types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
                 consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
@@ -364,7 +362,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
                             let ty = tcx.mk_ref(
                                 // Use `ReErased` as `resolve_interior` is going to replace all the
                                 // regions anyway.
-                                tcx.mk_region(ty::ReErased),
+                                tcx.lifetimes.re_erased,
                                 ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
                             );
                             self.interior_visitor.record(
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 6bfdeda3a24..2b33d31994f 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -363,7 +363,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                      opportunistically resolved to {:?}",
                     vid, resolved_vid
                 );
-                let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
+                let r = self.tcx.mk_re_var(resolved_vid);
                 self.canonicalize_mode.canonicalize_free_region(self, r)
             }
 
@@ -737,8 +737,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
         let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) };
-        let region = ty::ReLateBound(self.binder_index, br);
-        self.interner().mk_region(region)
+        self.interner().mk_re_late_bound(self.binder_index, br)
     }
 
     /// Given a type variable `ty_var` of the given kind, first check
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index d5cb3fb2498..4552256545b 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -137,7 +137,7 @@ impl<'tcx> InferCtxt<'tcx> {
             CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
                 let universe_mapped = universe_map(universe);
                 let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, name };
-                self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
+                self.tcx.mk_re_placeholder(placeholder_mapped).into()
             }
 
             CanonicalVarKind::Const(ui, ty) => self
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 0c97217bd6a..b9cb9732ca3 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -642,15 +642,14 @@ pub fn make_query_region_constraints<'tcx>(
             let constraint = match *k {
                 // Swap regions because we are going from sub (<=) to outlives
                 // (>=).
-                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
-                    tcx.mk_region(ty::ReVar(v2)).into(),
-                    tcx.mk_region(ty::ReVar(v1)),
-                ),
+                Constraint::VarSubVar(v1, v2) => {
+                    ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), tcx.mk_re_var(v1))
+                }
                 Constraint::VarSubReg(v1, r2) => {
-                    ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
+                    ty::OutlivesPredicate(r2.into(), tcx.mk_re_var(v1))
                 }
                 Constraint::RegSubVar(r1, v2) => {
-                    ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
+                    ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), r1)
                 }
                 Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
             };
@@ -690,7 +689,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
     }
 
     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
-        self.infcx.tcx.mk_region(ty::RePlaceholder(placeholder))
+        self.infcx.tcx.mk_re_placeholder(placeholder)
     }
 
     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index 39f4d502259..4fe6c6618f6 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -2,7 +2,7 @@ use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime as rl;
+use rustc_middle::middle::resolve_bound_vars as rbv;
 use rustc_middle::ty::{self, Region, TyCtxt};
 
 /// This function calls the `visit_ty` method for the parameters
@@ -99,11 +99,11 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
             hir::TyKind::Ref(ref lifetime, _) => {
                 // the lifetime of the Ref
                 let hir_id = lifetime.hir_id;
-                match (self.tcx.named_region(hir_id), self.bound_region) {
+                match (self.tcx.named_bound_var(hir_id), self.bound_region) {
                     // Find the index of the named region that was part of the
                     // error. We will then search the function parameters for a bound
                     // region at the right depth with the same index
-                    (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+                    (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
                         debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                         if id == def_id {
                             self.found_type = Some(arg);
@@ -115,7 +115,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
                     // error. We will then search the function parameters for a bound
                     // region at the right depth with the same index
                     (
-                        Some(rl::Region::LateBound(debruijn_index, _, id)),
+                        Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
                         ty::BrNamed(def_id, _),
                     ) => {
                         debug!(
@@ -131,10 +131,10 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
 
                     (
                         Some(
-                            rl::Region::Static
-                            | rl::Region::Free(_, _)
-                            | rl::Region::EarlyBound(_)
-                            | rl::Region::LateBound(_, _, _),
+                            rbv::ResolvedArg::StaticLifetime
+                            | rbv::ResolvedArg::Free(_, _)
+                            | rbv::ResolvedArg::EarlyBound(_)
+                            | rbv::ResolvedArg::LateBound(_, _, _),
                         )
                         | None,
                         _,
@@ -186,9 +186,9 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
     }
 
     fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
-        match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
+        match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) {
             // the lifetime of the TyPath!
-            (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+            (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
                 debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                 if id == def_id {
                     self.found_it = true;
@@ -196,7 +196,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
                 }
             }
 
-            (Some(rl::Region::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
+            (Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
                 debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
                 debug!("id={:?}", id);
                 debug!("def_id={:?}", def_id);
@@ -208,10 +208,10 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
 
             (
                 Some(
-                    rl::Region::Static
-                    | rl::Region::EarlyBound(_)
-                    | rl::Region::LateBound(_, _, _)
-                    | rl::Region::Free(_, _),
+                    rbv::ResolvedArg::StaticLifetime
+                    | rbv::ResolvedArg::EarlyBound(_)
+                    | rbv::ResolvedArg::LateBound(_, _, _)
+                    | rbv::ResolvedArg::Free(_, _),
                 )
                 | None,
                 _,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 99431567eda..c1ea0a0d95e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -14,7 +14,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt};
+use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt};
 
 use std::fmt;
 
@@ -79,7 +79,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 Some(*sub_placeholder),
                 Some(*sup_placeholder),
@@ -95,7 +95,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 _,
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 Some(*sub_placeholder),
                 None,
@@ -111,7 +111,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
@@ -127,7 +127,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
                 _,
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
@@ -141,7 +141,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
                 SubregionOrigin::Subtype(box TypeTrace { cause, values }),
                 sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
             )) => self.try_report_trait_placeholder_mismatch(
-                Some(self.tcx().mk_region(ReVar(*vid))),
+                Some(self.tcx().mk_re_var(*vid)),
                 cause,
                 None,
                 Some(*sup_placeholder),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index 4c0f457b46a..5643d1d9f74 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -90,20 +90,18 @@ pub fn find_param_with_region<'tcx>(
                     r
                 }
             });
-            if found_anon_region {
+            found_anon_region.then(|| {
                 let ty_hir_id = fn_decl.inputs[index].hir_id;
                 let param_ty_span = hir.span(ty_hir_id);
                 let is_first = index == 0;
-                Some(AnonymousParamInfo {
+                AnonymousParamInfo {
                     param,
                     param_ty: new_param_ty,
                     param_ty_span,
                     bound_region,
                     is_first,
-                })
-            } else {
-                None
-            }
+                }
+            })
         })
 }
 
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index 39940f4592d..82a1bb1fd16 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -82,10 +82,10 @@ impl<'tcx> InferCtxt<'tcx> {
 
         let delegate = FnMutDelegate {
             regions: &mut |br: ty::BoundRegion| {
-                self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
+                self.tcx.mk_re_placeholder(ty::PlaceholderRegion {
                     universe: next_universe,
                     name: br.kind,
-                }))
+                })
             },
             types: &mut |bound_ty: ty::BoundTy| {
                 self.tcx.mk_placeholder(ty::PlaceholderType {
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 4a2210bdb68..ac203c4eb0b 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -382,7 +382,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                     // name the placeholder, then the placeholder is
                     // larger; otherwise, the only ancestor is `'static`.
                     Err(placeholder) if empty_ui.can_name(placeholder.universe) => {
-                        self.tcx().mk_region(RePlaceholder(placeholder))
+                        self.tcx().mk_re_placeholder(placeholder)
                     }
                     Err(_) => self.tcx().lifetimes.re_static,
                 };
@@ -1046,7 +1046,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
             ty::ReVar(rid) => match self.values[rid] {
                 VarValue::Empty(_) => r,
                 VarValue::Value(r) => r,
-                VarValue::ErrorValue => tcx.re_error_misc(),
+                VarValue::ErrorValue => tcx.mk_re_error_misc(),
             },
             _ => r,
         };
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 17e734f0700..bb734ccb20e 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1093,7 +1093,7 @@ impl<'tcx> InferCtxt<'tcx> {
     ) -> ty::Region<'tcx> {
         let region_var =
             self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
-        self.tcx.mk_region(ty::ReVar(region_var))
+        self.tcx.mk_re_var(region_var)
     }
 
     /// Return the universe that the region `r` was created in. For
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index c46edc33ff4..e413b2bb570 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -280,7 +280,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
         placeholder1: ty::PlaceholderRegion,
         placeholder2: ty::PlaceholderRegion,
     ) -> TypeError<'tcx> {
-        self.error(placeholder1, self.tcx.mk_region(ty::RePlaceholder(placeholder2)))
+        self.error(placeholder1, self.tcx.mk_re_placeholder(placeholder2))
     }
 
     fn error(
@@ -413,19 +413,19 @@ impl<'tcx> MiniGraph<'tcx> {
         for undo_entry in undo_log {
             match undo_entry {
                 &AddConstraint(Constraint::VarSubVar(a, b)) => {
-                    each_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b)));
+                    each_edge(tcx.mk_re_var(a), tcx.mk_re_var(b));
                 }
                 &AddConstraint(Constraint::RegSubVar(a, b)) => {
-                    each_edge(a, tcx.mk_region(ReVar(b)));
+                    each_edge(a, tcx.mk_re_var(b));
                 }
                 &AddConstraint(Constraint::VarSubReg(a, b)) => {
-                    each_edge(tcx.mk_region(ReVar(a)), b);
+                    each_edge(tcx.mk_re_var(a), b);
                 }
                 &AddConstraint(Constraint::RegSubReg(a, b)) => {
                     each_edge(a, b);
                 }
                 &AddGiven(a, b) => {
-                    each_edge(a, tcx.mk_region(ReVar(b)));
+                    each_edge(a, tcx.mk_re_var(b));
                 }
                 &AddVerify(i) => span_bug!(
                     verifys[i].origin.span(),
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index cb24375c7a3..33514eedfc3 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -651,7 +651,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
                 let unified_region = self.unification_table().probe_value(rid);
                 unified_region.0.unwrap_or_else(|| {
                     let root = self.unification_table().find(rid).vid;
-                    tcx.reuse_or_mk_region(region, ty::ReVar(root))
+                    tcx.mk_re_var(root)
                 })
             }
             _ => region,
@@ -675,7 +675,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     ) -> Region<'tcx> {
         let vars = TwoRegions { a, b };
         if let Some(&c) = self.combine_map(t).get(&vars) {
-            return tcx.mk_region(ReVar(c));
+            return tcx.mk_re_var(c);
         }
         let a_universe = self.universe(a);
         let b_universe = self.universe(b);
@@ -683,7 +683,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
         self.combine_map(t).insert(vars, c);
         self.undo_log.push(AddCombination(t, vars));
-        let new_r = tcx.mk_region(ReVar(c));
+        let new_r = tcx.mk_re_var(c);
         for old_r in [a, b] {
             match t {
                 Glb => self.make_subregion(origin.clone(), new_r, old_r),
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 008bf1e9c5d..2c246a5787c 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -95,7 +95,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx
                     .borrow_mut()
                     .unwrap_region_constraints()
                     .opportunistic_resolve_var(rid);
-                TypeFolder::interner(self).reuse_or_mk_region(r, ty::ReVar(resolved))
+                TypeFolder::interner(self).mk_re_var(resolved)
             }
             _ => r,
         }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index f18c0aa377f..cd793d36de6 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2007,7 +2007,7 @@ impl ExplicitOutlivesRequirements {
         inferred_outlives: &[ty::Region<'tcx>],
         predicate_span: Span,
     ) -> Vec<(usize, Span)> {
-        use rustc_middle::middle::resolve_lifetime::Region;
+        use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 
         bounds
             .iter()
@@ -2017,8 +2017,8 @@ impl ExplicitOutlivesRequirements {
                     return None;
                 };
 
-                let is_inferred = match tcx.named_region(lifetime.hir_id) {
-                    Some(Region::EarlyBound(def_id)) => inferred_outlives
+                let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
+                    Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
                         .iter()
                         .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
                     _ => false,
@@ -2097,7 +2097,7 @@ impl ExplicitOutlivesRequirements {
 
 impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-        use rustc_middle::middle::resolve_lifetime::Region;
+        use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 
         let def_id = item.owner_id.def_id;
         if let hir::ItemKind::Struct(_, hir_generics)
@@ -2120,8 +2120,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                 let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
                     match where_predicate {
                         hir::WherePredicate::RegionPredicate(predicate) => {
-                            if let Some(Region::EarlyBound(region_def_id)) =
-                                cx.tcx.named_region(predicate.lifetime.hir_id)
+                            if let Some(ResolvedArg::EarlyBound(region_def_id)) =
+                                cx.tcx.named_bound_var(predicate.lifetime.hir_id)
                             {
                                 (
                                     Self::lifetimes_outliving_lifetime(
@@ -2308,11 +2308,8 @@ impl EarlyLintPass for IncompleteFeatures {
             .for_each(|(&name, &span)| {
                 let note = rustc_feature::find_feature_issue(name, GateIssue::Language)
                     .map(|n| BuiltinIncompleteFeaturesNote { n });
-                let help = if HAS_MIN_FEATURES.contains(&name) {
-                    Some(BuiltinIncompleteFeaturesHelp)
-                } else {
-                    None
-                };
+                let help =
+                    HAS_MIN_FEATURES.contains(&name).then_some(BuiltinIncompleteFeaturesHelp);
                 cx.emit_spanned_lint(
                     INCOMPLETE_FEATURES,
                     span,
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 972240f42cf..9a9e2de7b5c 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -487,7 +487,7 @@ impl LintStore {
         let mut groups: Vec<_> = self
             .lint_groups
             .iter()
-            .filter_map(|(k, LintGroup { depr, .. })| if depr.is_none() { Some(k) } else { None })
+            .filter_map(|(k, LintGroup { depr, .. })| depr.is_none().then_some(k))
             .collect();
         groups.sort();
         let groups = groups.iter().map(|k| Symbol::intern(k));
@@ -1112,11 +1112,9 @@ impl<'tcx> LateContext<'tcx> {
                 .maybe_typeck_results()
                 .filter(|typeck_results| typeck_results.hir_owner == id.owner)
                 .or_else(|| {
-                    if self.tcx.has_typeck_results(id.owner.to_def_id()) {
-                        Some(self.tcx.typeck(id.owner.def_id))
-                    } else {
-                        None
-                    }
+                    self.tcx
+                        .has_typeck_results(id.owner.to_def_id())
+                        .then(|| self.tcx.typeck(id.owner.def_id))
                 })
                 .and_then(|typeck_results| typeck_results.type_dependent_def(id))
                 .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index 1add352e0c4..a3367ae4a9f 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -65,11 +65,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
             } else {
                 ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), end_span: pat.span.between(arg.span), var }
             } ;
-        let question_mark = if suggest_question_mark(cx, adt, substs, expr.span) {
-            Some(ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() })
-        } else {
-            None
-        };
+        let question_mark = suggest_question_mark(cx, adt, substs, expr.span)
+            .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() });
         let suggestion = ForLoopsOverFalliblesSuggestion {
             var,
             start_span: expr.span.with_hi(pat.span.lo()),
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 9227609cc8b..a9fb8b246c6 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -18,7 +18,7 @@ use rustc_index::vec::IndexVec;
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::mir;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::query::Providers;
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index ba93330d581..2eafc356dc3 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1062,7 +1062,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn span_if_local(self, id: DefId) -> Option<Span> {
-        if id.is_local() { Some(self.tcx.def_span(id)) } else { None }
+        id.is_local().then(|| self.tcx.def_span(id))
     }
 
     pub fn res_span(self, res: Res) -> Option<Span> {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index ada516aa032..bb617e692cc 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -353,7 +353,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
                                 var: ty::BoundVar::from_usize(i),
                                 kind: ty::BrAnon(i as u32, None),
                             };
-                            tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
+                            tcx.mk_re_late_bound(ty::INNERMOST, br).into()
                         }
                         CanonicalVarKind::Const(_, ty)
                         | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 8dc68b1f5a8..0b6774f1b1f 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -29,7 +29,7 @@ pub mod lib_features {
 pub mod limits;
 pub mod privacy;
 pub mod region;
-pub mod resolve_lifetime;
+pub mod resolve_bound_vars;
 pub mod stability;
 
 pub fn provide(providers: &mut crate::ty::query::Providers) {
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
index c3bf1c717d9..b96d07e7dc8 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
@@ -1,4 +1,4 @@
-//! Name resolution for lifetimes: type declarations.
+//! Name resolution for lifetimes and late-bound type and const variables: type declarations.
 
 use crate::ty;
 
@@ -8,10 +8,10 @@ use rustc_hir::{ItemLocalId, OwnerId};
 use rustc_macros::HashStable;
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
-pub enum Region {
-    Static,
-    EarlyBound(/* lifetime decl */ DefId),
-    LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId),
+pub enum ResolvedArg {
+    StaticLifetime,
+    EarlyBound(/* decl */ DefId),
+    LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId),
     Free(DefId, /* lifetime decl */ DefId),
 }
 
@@ -46,10 +46,10 @@ pub enum ObjectLifetimeDefault {
 /// Maps the id of each lifetime reference to the lifetime decl
 /// that it corresponds to.
 #[derive(Default, HashStable, Debug)]
-pub struct ResolveLifetimes {
+pub struct ResolveBoundVars {
     /// Maps from every use of a named (not anonymous) lifetime to a
     /// `Region` describing how that region is bound
-    pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Region>>,
+    pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, ResolvedArg>>,
 
     pub late_bound_vars: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index c596e91160c..3cb07b5b41e 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -414,7 +414,7 @@ impl<'tcx> Body<'tcx> {
         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
             let decl = &self.local_decls[local];
-            (decl.is_user_variable() && decl.mutability.is_mut()).then(|| local)
+            (decl.is_user_variable() && decl.mutability.is_mut()).then_some(local)
         })
     }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 4b34f6b4881..c793676146d 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1641,12 +1641,12 @@ rustc_queries! {
     /// Does lifetime resolution on items. Importantly, we can't resolve
     /// lifetimes directly on things like trait methods, because of trait params.
     /// See `rustc_resolve::late::lifetimes for details.
-    query resolve_lifetimes(_: hir::OwnerId) -> &'tcx ResolveLifetimes {
+    query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars {
         arena_cache
         desc { "resolving lifetimes" }
     }
-    query named_region_map(_: hir::OwnerId) ->
-        Option<&'tcx FxHashMap<ItemLocalId, Region>> {
+    query named_variable_map(_: hir::OwnerId) ->
+        Option<&'tcx FxHashMap<ItemLocalId, ResolvedArg>> {
         desc { "looking up a named region" }
     }
     query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 927f18f59b9..c7268d561e5 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,7 +1,9 @@
+use crate::middle::resolve_bound_vars as rbv;
 use crate::mir::interpret::LitToConstInput;
 use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_data_structures::intern::Interned;
 use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::HashStable;
 use std::fmt;
@@ -125,16 +127,27 @@ impl<'tcx> Const<'tcx> {
             }
         }
 
-        use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
         match expr.kind {
-            ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
-                // Find the name and index of the const parameter by indexing the generics of
-                // the parent item and construct a `ParamConst`.
-                let item_def_id = tcx.parent(def_id);
-                let generics = tcx.generics_of(item_def_id);
-                let index = generics.param_def_id_to_index[&def_id];
-                let name = tcx.item_name(def_id);
-                Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+            hir::ExprKind::Path(hir::QPath::Resolved(
+                _,
+                &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
+            )) => {
+                match tcx.named_bound_var(expr.hir_id) {
+                    Some(rbv::ResolvedArg::EarlyBound(_)) => {
+                        // Find the name and index of the const parameter by indexing the generics of
+                        // the parent item and construct a `ParamConst`.
+                        let item_def_id = tcx.parent(def_id);
+                        let generics = tcx.generics_of(item_def_id);
+                        let index = generics.param_def_id_to_index[&def_id];
+                        let name = tcx.item_name(def_id);
+                        Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+                    }
+                    Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
+                        ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
+                        ty,
+                    )),
+                    arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
+                }
             }
             _ => None,
         }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 4aef071cd98..f5322006bec 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -9,7 +9,7 @@ use crate::dep_graph::{DepGraph, DepKindStruct};
 use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::struct_lint_level;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::resolve_lifetime;
+use crate::middle::resolve_bound_vars;
 use crate::middle::stability;
 use crate::mir::interpret::{self, Allocation, ConstAllocation};
 use crate::mir::{
@@ -243,11 +243,20 @@ impl<'tcx> CtxtInterners<'tcx> {
     }
 }
 
+// For these preinterned values, an alternative would be to have
+// variable-length vectors that grow as needed. But that turned out to be
+// slightly more complex and no faster.
+
 const NUM_PREINTERNED_TY_VARS: u32 = 100;
 const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
 const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
 const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
 
+// This number may seem high, but it is reached in all but the smallest crates.
+const NUM_PREINTERNED_RE_VARS: u32 = 500;
+const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2;
+const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20;
+
 pub struct CommonTypes<'tcx> {
     pub unit: Ty<'tcx>,
     pub bool: Ty<'tcx>,
@@ -295,6 +304,14 @@ pub struct CommonLifetimes<'tcx> {
 
     /// Erased region, used outside of type inference.
     pub re_erased: Region<'tcx>,
+
+    /// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
+    pub re_vars: Vec<Region<'tcx>>,
+
+    /// Pre-interned values of the form:
+    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })
+    /// for small values of `i` and `v`.
+    pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
 }
 
 pub struct CommonConsts<'tcx> {
@@ -358,7 +375,31 @@ impl<'tcx> CommonLifetimes<'tcx> {
             ))
         };
 
-        CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) }
+        let re_vars =
+            (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
+
+        let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I)
+            .map(|i| {
+                (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
+                    .map(|v| {
+                        mk(ty::ReLateBound(
+                            ty::DebruijnIndex::from(i),
+                            ty::BoundRegion {
+                                var: ty::BoundVar::from(v),
+                                kind: ty::BrAnon(v, None),
+                            },
+                        ))
+                    })
+                    .collect()
+            })
+            .collect();
+
+        CommonLifetimes {
+            re_static: mk(ty::ReStatic),
+            re_erased: mk(ty::ReErased),
+            re_vars,
+            re_late_bounds,
+        }
     }
 }
 
@@ -697,15 +738,15 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Constructs a `RegionKind::ReError` lifetime.
     #[track_caller]
-    pub fn re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
-        self.mk_region(ty::ReError(reported))
+    pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
+        self.intern_region(ty::ReError(reported))
     }
 
     /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
     /// gets used.
     #[track_caller]
-    pub fn re_error_misc(self) -> Region<'tcx> {
-        self.re_error_with_message(
+    pub fn mk_re_error_misc(self) -> Region<'tcx> {
+        self.mk_re_error_with_message(
             DUMMY_SP,
             "RegionKind::ReError constructed but no error reported",
         )
@@ -714,9 +755,9 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
     /// `msg` to ensure it gets used.
     #[track_caller]
-    pub fn re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
+    pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
         let reported = self.sess.delay_span_bug(span, msg);
-        self.re_error(reported)
+        self.mk_re_error(reported)
     }
 
     /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
@@ -1113,13 +1154,11 @@ impl<'tcx> TyCtxt<'tcx> {
             ty::FnDef(_, _) => {
                 let sig = ret_ty.fn_sig(self);
                 let output = self.erase_late_bound_regions(sig.output());
-                if output.is_impl_trait() {
+                output.is_impl_trait().then(|| {
                     let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
                     let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
-                    Some((output, fn_decl.output.span()))
-                } else {
-                    None
-                }
+                    (output, fn_decl.output.span())
+                })
             }
             _ => None,
         }
@@ -1225,13 +1264,12 @@ macro_rules! nop_lift {
         impl<'a, 'tcx> Lift<'tcx> for $ty {
             type Lifted = $lifted;
             fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-                if tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0)) {
+                tcx.interners
+                    .$set
+                    .contains_pointer_to(&InternedInSet(&*self.0.0))
                     // SAFETY: `self` is interned and therefore valid
                     // for the entire lifetime of the `TyCtxt`.
-                    Some(unsafe { mem::transmute(self) })
-                } else {
-                    None
-                }
+                    .then(|| unsafe { mem::transmute(self) })
             }
         }
     };
@@ -1246,13 +1284,13 @@ impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
         if self.is_empty() {
             return Some(List::empty());
         }
-        if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) {
+
+        tcx.interners
+            .substs
+            .contains_pointer_to(&InternedInSet(self.as_substs()))
             // SAFETY: `self` is interned and therefore valid
             // for the entire lifetime of the `TyCtxt`.
-            Some(unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
-        } else {
-            None
-        }
+            .then(|| unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
     }
 }
 
@@ -1264,11 +1302,10 @@ macro_rules! nop_list_lift {
                 if self.is_empty() {
                     return Some(List::empty());
                 }
-                if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) {
-                    Some(unsafe { mem::transmute(self) })
-                } else {
-                    None
-                }
+                tcx.interners
+                    .$set
+                    .contains_pointer_to(&InternedInSet(self))
+                    .then(|| unsafe { mem::transmute(self) })
             }
         }
     };
@@ -1517,7 +1554,7 @@ macro_rules! direct_interners {
 }
 
 direct_interners! {
-    region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
+    region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
     const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
     const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
     layout: intern_layout(LayoutS): Layout -> Layout<'tcx>,
@@ -1631,13 +1668,6 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
-    /// `*r == kind`.
-    #[inline]
-    pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
-        if *r == kind { r } else { self.mk_region(kind) }
-    }
-
     // Avoid this in favour of more specific `mk_*` methods, where possible.
     #[allow(rustc::usage_of_ty_tykind)]
     #[inline]
@@ -1966,7 +1996,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
         match param.kind {
             GenericParamDefKind::Lifetime => {
-                self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
+                self.mk_re_early_bound(param.to_early_bound_region_data()).into()
             }
             GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
             GenericParamDefKind::Const { .. } => self
@@ -1998,6 +2028,66 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs))
     }
 
+    #[inline]
+    pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> {
+        self.intern_region(ty::ReEarlyBound(early_bound_region))
+    }
+
+    #[inline]
+    pub fn mk_re_late_bound(
+        self,
+        debruijn: ty::DebruijnIndex,
+        bound_region: ty::BoundRegion,
+    ) -> Region<'tcx> {
+        // Use a pre-interned one when possible.
+        if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
+            && var.as_u32() == v
+            && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
+            && let Some(re) = inner.get(v as usize).copied()
+        {
+            re
+        } else {
+            self.intern_region(ty::ReLateBound(debruijn, bound_region))
+        }
+    }
+
+    #[inline]
+    pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> {
+        self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
+    }
+
+    #[inline]
+    pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> {
+        // Use a pre-interned one when possible.
+        self.lifetimes
+            .re_vars
+            .get(v.as_usize())
+            .copied()
+            .unwrap_or_else(|| self.intern_region(ty::ReVar(v)))
+    }
+
+    #[inline]
+    pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
+        self.intern_region(ty::RePlaceholder(placeholder))
+    }
+
+    // Avoid this in favour of more specific `mk_re_*` methods, where possible,
+    // to avoid the cost of the `match`.
+    pub fn mk_region(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> {
+        match kind {
+            ty::ReEarlyBound(region) => self.mk_re_early_bound(region),
+            ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region),
+            ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
+                self.mk_re_free(scope, bound_region)
+            }
+            ty::ReStatic => self.lifetimes.re_static,
+            ty::ReVar(vid) => self.mk_re_var(vid),
+            ty::RePlaceholder(region) => self.mk_re_placeholder(region),
+            ty::ReErased => self.lifetimes.re_erased,
+            ty::ReError(reported) => self.mk_re_error(reported),
+        }
+    }
+
     pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
         self.mk_place_elem(place, PlaceElem::Field(f, ty))
     }
@@ -2278,9 +2368,9 @@ impl<'tcx> TyCtxt<'tcx> {
         Some(&*candidates)
     }
 
-    pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
+    pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
         debug!(?id, "named_region");
-        self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
+        self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
     }
 
     pub fn is_late_bound(self, id: HirId) -> bool {
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 9afa37e9ef3..106ce9990e1 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -290,7 +290,7 @@ impl DeepRejectCtxt {
             // Impls cannot contain these types as these cannot be named directly.
             ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
 
-            ty::Placeholder(..) => false,
+            ty::Placeholder(..) | ty::Bound(..) => false,
 
             // Depending on the value of `treat_obligation_params`, we either
             // treat generic parameters like placeholders or like inference variables.
@@ -310,7 +310,7 @@ impl DeepRejectCtxt {
 
             ty::Error(_) => true,
 
-            ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Bound(..) => {
+            ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {
                 bug!("unexpected obligation type: {:?}", obligation_ty)
             }
         }
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 352daa8fc29..ee36e60bff1 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -234,7 +234,7 @@ where
                     // debruijn index. Then we adjust it to the
                     // correct depth.
                     assert_eq!(debruijn1, ty::INNERMOST);
-                    self.tcx.reuse_or_mk_region(region, ty::ReLateBound(debruijn, br))
+                    self.tcx.mk_re_late_bound(debruijn, br)
                 } else {
                     region
                 }
@@ -349,10 +349,7 @@ impl<'tcx> TyCtxt<'tcx> {
         T: TypeFoldable<'tcx>,
     {
         self.replace_late_bound_regions_uncached(value, |br| {
-            self.mk_region(ty::ReFree(ty::FreeRegion {
-                scope: all_outlive_scope,
-                bound_region: br.kind,
-            }))
+            self.mk_re_free(all_outlive_scope, br.kind)
         })
     }
 
@@ -365,10 +362,10 @@ impl<'tcx> TyCtxt<'tcx> {
             value,
             FnMutDelegate {
                 regions: &mut |r: ty::BoundRegion| {
-                    self.mk_region(ty::ReLateBound(
+                    self.mk_re_late_bound(
                         ty::INNERMOST,
                         ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
-                    ))
+                    )
                 },
                 types: &mut |t: ty::BoundTy| {
                     self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
@@ -409,7 +406,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     })
                     .expect_region();
                 let br = ty::BoundRegion { var, kind };
-                self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
+                self.tcx.mk_re_late_bound(ty::INNERMOST, br)
             }
             fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
                 let entry = self.map.entry(bt.var);
@@ -479,8 +476,7 @@ impl<'tcx> ir::TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
         match *r {
             ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
                 let debruijn = debruijn.shifted_in(self.amount);
-                let shifted = ty::ReLateBound(debruijn, br);
-                self.tcx.mk_region(shifted)
+                self.tcx.mk_re_late_bound(debruijn, br)
             }
             _ => r,
         }
@@ -521,7 +517,7 @@ pub fn shift_region<'tcx>(
 ) -> ty::Region<'tcx> {
     match *region {
         ty::ReLateBound(debruijn, br) if amount > 0 => {
-            tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
+            tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
         }
         _ => region,
     }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index ea95a38f272..c29a94c9714 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -100,7 +100,7 @@ impl GenericParamDef {
         preceding_substs: &[ty::GenericArg<'tcx>],
     ) -> ty::GenericArg<'tcx> {
         match &self.kind {
-            ty::GenericParamDefKind::Lifetime => tcx.re_error_misc().into(),
+            ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
             ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
             ty::GenericParamDefKind::Const { .. } => {
                 tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into()
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 55f2395e531..c6c3c1f08de 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -584,7 +584,7 @@ impl<'tcx> Instance<'tcx> {
     /// this function returns `None`, then the MIR body does not require substitution during
     /// codegen.
     fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
-        if self.def.has_polymorphic_mir_body() { Some(self.substs) } else { None }
+        self.def.has_polymorphic_mir_body().then_some(self.substs)
     }
 
     pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: &T) -> T
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 66c878c8b63..8aeef4684b3 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -143,7 +143,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                     )
                     .emit();
 
-                self.interner().re_error(e)
+                self.interner().mk_re_error(e)
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 303675d3ca5..8849e7eab33 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -57,7 +57,7 @@ trivially_parameterized_over_tcx! {
     crate::metadata::ModChild,
     crate::middle::codegen_fn_attrs::CodegenFnAttrs,
     crate::middle::exported_symbols::SymbolExportInfo,
-    crate::middle::resolve_lifetime::ObjectLifetimeDefault,
+    crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
     crate::mir::ConstQualifs,
     ty::AssocItemContainer,
     ty::DeducedParamAttrs,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index f50a5d89d3d..1a228e99eff 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -182,7 +182,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
 
     /// Convenience wrapper for `highlighting_region`.
     pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
-        self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number)
+        self.highlighting_region(self.tcx.mk_re_var(vid), number)
     }
 
     /// Returns `Some(n)` with the number to use for the given region, if any.
@@ -2271,7 +2271,7 @@ impl<'a, 'tcx> ty::ir::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
         };
         if let ty::ReLateBound(debruijn1, br) = *region {
             assert_eq!(debruijn1, ty::INNERMOST);
-            self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
+            self.tcx.mk_re_late_bound(self.current_index, br)
         } else {
             region
         }
@@ -2383,10 +2383,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
-                                return tcx.mk_region(ty::ReLateBound(
+                                return tcx.mk_re_late_bound(
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
-                                ));
+                                );
                             }
                         }
 
@@ -2398,10 +2398,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = ty::BrNamed(def_id, name);
-                                return tcx.mk_region(ty::ReLateBound(
+                                return tcx.mk_re_late_bound(
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
-                                ));
+                                );
                             }
                         }
 
@@ -2411,10 +2411,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = br.kind;
-                                return tcx.mk_region(ty::ReLateBound(
+                                return tcx.mk_re_late_bound(
                                     ty::INNERMOST,
                                     ty::BoundRegion { var: br.var, kind },
-                                ));
+                                );
                             }
                         }
 
@@ -2426,7 +2426,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                     start_or_continue(&mut self, "for<", ", ");
                     do_continue(&mut self, name);
                 }
-                tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
+                tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
             };
             let mut folder = RegionFolder {
                 tcx,
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index ed54aa96f5b..f1128d7c8bb 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -6,7 +6,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
 use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use crate::middle::lib_features::LibFeatures;
 use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
+use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
 use crate::middle::stability::{self, DeprecationEntry};
 use crate::mir;
 use crate::mir::interpret::GlobalId;
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index c613b3627f2..85c63131bff 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1187,7 +1187,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> {
             if index == self.index {
                 Err(())
             } else {
-                Ok(self.interner().mk_region(ty::ReLateBound(index.shifted_out(1), bv)))
+                Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv))
             }
         } else {
             r.try_super_fold_with(self)
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a6ab7440c8e..6b4a6a17aef 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -267,13 +267,11 @@ pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
 impl<'tcx> InternalSubsts<'tcx> {
     /// Checks whether all elements of this list are types, if so, transmute.
     pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> {
-        if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) {
+        self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))).then(|| {
             assert_eq!(TYPE_TAG, 0);
             // SAFETY: All elements are types, see `List<Ty<'tcx>>::as_substs`.
-            Some(unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) })
-        } else {
-            None
-        }
+            unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) }
+        })
     }
 
     /// Interpret these substitutions as the substitutions of a closure type.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 35831ff8706..7f5ffe6f27a 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -564,14 +564,14 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         closure_def_id: DefId,
         closure_substs: SubstsRef<'tcx>,
-        env_region: ty::RegionKind<'tcx>,
+        env_region: ty::Region<'tcx>,
     ) -> Option<Ty<'tcx>> {
         let closure_ty = self.mk_closure(closure_def_id, closure_substs);
         let closure_kind_ty = closure_substs.as_closure().kind_ty();
         let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
         let env_ty = match closure_kind {
-            ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
-            ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
+            ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty),
+            ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty),
             ty::ClosureKind::FnOnce => closure_ty,
         };
         Some(env_ty)
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 38b1fa91d0a..dac9bf0a883 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -319,7 +319,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // See the notes for `ExprKind::Array` in `as_rvalue` and for
                 // `ExprKind::Borrow` above.
                 let is_union = adt_def.is_union();
-                let active_field_index = if is_union { Some(fields[0].name.index()) } else { None };
+                let active_field_index = is_union.then(|| fields[0].name.index());
 
                 let scope = this.local_scope();
 
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index ad7a568a231..8859f5002e4 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -563,14 +563,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let not_contained =
                     self.values_not_contained_in_range(&*range, options).unwrap_or(false);
 
-                if not_contained {
+                not_contained.then(|| {
                     // No switch values are contained in the pattern range,
                     // so the pattern can be matched only if this test fails.
-                    let otherwise = options.len();
-                    Some(otherwise)
-                } else {
-                    None
-                }
+                    options.len()
+                })
             }
 
             (&TestKind::SwitchInt { .. }, _) => None,
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 10df4b22952..c9fa599f52d 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -140,7 +140,7 @@ impl<'tcx> Cx<'tcx> {
                     var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                     kind: ty::BrEnv,
                 };
-                let env_region = ty::ReLateBound(ty::INNERMOST, br);
+                let env_region = self.tcx.mk_re_late_bound(ty::INNERMOST, br);
                 let closure_env_ty =
                     self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
                 let liberated_closure_env_ty = self.tcx.erase_late_bound_regions(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index 977c4b4ae6c..e5b7d685c49 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -172,7 +172,7 @@ impl IntRange {
         ty: Ty<'tcx>,
         end: &RangeEnd,
     ) -> Option<IntRange> {
-        if Self::is_integral(ty) {
+        Self::is_integral(ty).then(|| {
             // Perform a shift if the underlying types are signed,
             // which makes the interval arithmetic simpler.
             let bias = IntRange::signed_bias(tcx, ty);
@@ -182,10 +182,8 @@ impl IntRange {
                 // This should have been caught earlier by E0030.
                 bug!("malformed range pattern: {}..={}", lo, (hi - offset));
             }
-            Some(IntRange { range: lo..=(hi - offset), bias })
-        } else {
-            None
-        }
+            IntRange { range: lo..=(hi - offset), bias }
+        })
     }
 
     // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 47ca0a87fcc..41306dd80fb 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -203,11 +203,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 if !lower_overflow && !higher_overflow {
                     self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
                         span,
-                        teach: if self.tcx.sess.teach(&error_code!(E0030)) {
-                            Some(())
-                        } else {
-                            None
-                        },
+                        teach: self.tcx.sess.teach(&error_code!(E0030)).then_some(()),
                     });
                 }
                 PatKind::Wild
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 2890fa32cc9..633a5674f1f 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -254,13 +254,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
     ) {
         // Compute the place that we are storing to, if any
         let destination = match &statement.kind {
-            StatementKind::Assign(assign) => {
-                if assign.1.is_safe_to_remove() {
-                    Some(assign.0)
-                } else {
-                    None
-                }
-            }
+            StatementKind::Assign(assign) => assign.1.is_safe_to_remove().then_some(assign.0),
             StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => {
                 Some(**place)
             }
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index aa19b1fdb5e..66d32b954e4 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -111,11 +111,9 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
     /// If the given predicate is the trait `fmt::Pointer`, returns the bound parameter type.
     fn is_pointer_trait(&self, bound: &PredicateKind<'tcx>) -> Option<Ty<'tcx>> {
         if let ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) = bound {
-            if self.tcx.is_diagnostic_item(sym::Pointer, predicate.def_id()) {
-                Some(predicate.trait_ref.self_ty())
-            } else {
-                None
-            }
+            self.tcx
+                .is_diagnostic_item(sym::Pointer, predicate.def_id())
+                .then(|| predicate.trait_ref.self_ty())
         } else {
             None
         }
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 194c41c6ba1..2ca33a624e2 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -3,7 +3,7 @@ use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, AdtDef, Const, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants};
 
@@ -141,10 +141,7 @@ impl EnumSizeOpt {
                         self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
                     let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
 
-                    let tmp_ty = tcx.mk_ty(ty::Array(
-                        tcx.types.usize,
-                        Const::from_target_usize(tcx, num_variants as u64),
-                    ));
+                    let tmp_ty = tcx.mk_array(tcx.types.usize, num_variants as u64);
 
                     let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span));
                     let store_live = Statement {
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index 65c15d9c674..c1e7f62dea5 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -2,7 +2,7 @@ use either::Either;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
-use rustc_middle::middle::resolve_lifetime::Set1;
+use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{ParamEnv, TyCtxt};
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 0cb88f3c3a9..a74f408d774 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1283,22 +1283,16 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_delim_args_inner(&mut self) -> Option<DelimArgs> {
-        if self.check(&token::OpenDelim(Delimiter::Parenthesis))
+        let delimited = self.check(&token::OpenDelim(Delimiter::Parenthesis))
             || self.check(&token::OpenDelim(Delimiter::Bracket))
-            || self.check(&token::OpenDelim(Delimiter::Brace))
-        {
-            match self.parse_token_tree() {
-                // We've confirmed above that there is a delimiter so unwrapping is OK.
-                TokenTree::Delimited(dspan, delim, tokens) => Some(DelimArgs {
-                    dspan,
-                    delim: MacDelimiter::from_token(delim).unwrap(),
-                    tokens,
-                }),
-                _ => unreachable!(),
-            }
-        } else {
-            None
-        }
+            || self.check(&token::OpenDelim(Delimiter::Brace));
+
+        delimited.then(|| {
+            // We've confirmed above that there is a delimiter so unwrapping is OK.
+            let TokenTree::Delimited(dspan, delim, tokens) = self.parse_token_tree() else { unreachable!() };
+
+            DelimArgs { dspan, delim: MacDelimiter::from_token(delim).unwrap(), tokens }
+        })
     }
 
     fn parse_or_use_outer_attributes(
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 2e706a00cf7..49959a8981c 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -404,7 +404,7 @@ impl<'a> Parser<'a> {
 
         let is_first_invocation = style == PathStyle::Expr;
         // Take a snapshot before attempting to parse - we can restore this later.
-        let snapshot = if is_first_invocation { Some(self.clone()) } else { None };
+        let snapshot = is_first_invocation.then(|| self.clone());
 
         debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
         match self.parse_angle_args(ty_generics) {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 5b92563fc35..4f4252b532e 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -450,8 +450,7 @@ impl<'a> Parser<'a> {
 
     fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
         let and_span = self.prev_token.span;
-        let mut opt_lifetime =
-            if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
+        let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
         let mut mutbl = self.parse_mutability();
         if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
             // A lifetime is invalid here: it would be part of a bare trait bound, which requires
@@ -871,7 +870,7 @@ impl<'a> Parser<'a> {
             None
         };
 
-        let maybe = if self.eat(&token::Question) { Some(self.prev_token.span) } else { None };
+        let maybe = self.eat(&token::Question).then_some(self.prev_token.span);
 
         Ok(BoundModifiers { maybe, maybe_const })
     }
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 34a4fd02ea6..8a3cedfee79 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -835,7 +835,7 @@ impl<'a> Parser<'a> {
             );
         }
 
-        if found { Some(cur) } else { None }
+        found.then_some(cur)
     }
 
     fn suggest_format(&mut self) {
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 225095948af..7cff8996d24 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -18,7 +18,7 @@ use rustc_hir::{
 };
 use rustc_hir::{MethodKind, Target, Unsafety};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{ParamEnv, TyCtxt};
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 10ffa87efe3..0ae7096642c 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -32,11 +32,8 @@ fn collect_item(tcx: TyCtxt<'_>, items: &mut DiagnosticItems, name: Symbol, item
     if let Some(original_def_id) = items.name_to_id.insert(name, item_def_id) {
         if original_def_id != item_def_id {
             let orig_span = tcx.hir().span_if_local(original_def_id);
-            let orig_crate_name = if orig_span.is_some() {
-                None
-            } else {
-                Some(tcx.crate_name(original_def_id.krate))
-            };
+            let orig_crate_name =
+                orig_span.is_none().then(|| tcx.crate_name(original_def_id.krate));
             match tcx.hir().span_if_local(item_def_id) {
                 Some(span) => tcx.sess.emit_err(DuplicateDiagnosticItem { span, name }),
                 None => tcx.sess.emit_err(DuplicateDiagnosticItemInCrate {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 7299fc9705c..13a576014a2 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -281,7 +281,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         self.recurse_with_stability_attrs(
             depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
             stab,
-            if inherit_const_stability.yes() { const_stab } else { None },
+            inherit_const_stability.yes().then_some(const_stab).flatten(),
             visit_children,
         );
     }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 4675bd79c46..0a0c94e1dfb 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -270,10 +270,11 @@ where
             | ty::Ref(..)
             | ty::FnPtr(..)
             | ty::Param(..)
+            | ty::Bound(..)
             | ty::Error(_)
             | ty::GeneratorWitness(..)
             | ty::GeneratorWitnessMIR(..) => {}
-            ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => {
+            ty::Placeholder(..) | ty::Infer(..) => {
                 bug!("unexpected type: {:?}", ty)
             }
         }
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index a81595b2420..29513df460f 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -242,8 +242,7 @@ impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
         record_graph: bool,
         record_stats: bool,
     ) -> Self {
-        let record_graph =
-            if record_graph { Some(Lock::new(DepGraphQuery::new(prev_node_count))) } else { None };
+        let record_graph = record_graph.then(|| Lock::new(DepGraphQuery::new(prev_node_count)));
         let status = Lock::new(EncoderState::new(encoder, record_stats));
         GraphEncoder { status, record_graph }
     }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index d3bcbbabf55..324de7461cd 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -21,7 +21,7 @@ use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
-use rustc_middle::middle::resolve_lifetime::Set1;
+use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::ty::DefIdTree;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
@@ -2505,7 +2505,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
             let res = match kind {
                 ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()),
-                NormalRibKind => Res::Err,
+                NormalRibKind => {
+                    if self.r.session.features_untracked().non_lifetime_binders {
+                        Res::Def(def_kind, def_id.to_def_id())
+                    } else {
+                        Res::Err
+                    }
+                }
                 _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
             };
             self.r.record_partial_res(param.id, PartialRes::new(res));
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index a3195a64366..5205d055cf9 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1700,11 +1700,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                                         let crate_mod =
                                             Res::Def(DefKind::Mod, crate_id.as_def_id());
 
-                                        if filter_fn(crate_mod) {
-                                            Some(TypoSuggestion::typo_from_ident(*ident, crate_mod))
-                                        } else {
-                                            None
-                                        }
+                                        filter_fn(crate_mod).then(|| {
+                                            TypoSuggestion::typo_from_ident(*ident, crate_mod)
+                                        })
                                     })
                             }));
 
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index a967f4b940c..3425e24585c 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -344,7 +344,7 @@ fn preprocess_link(link: &str) -> String {
     let link = link.strip_suffix("()").unwrap_or(link);
     let link = link.strip_suffix("{}").unwrap_or(link);
     let link = link.strip_suffix("[]").unwrap_or(link);
-    let link = if link != "!" { link.strip_suffix("!").unwrap_or(link) } else { link };
+    let link = if link != "!" { link.strip_suffix('!').unwrap_or(link) } else { link };
     strip_generics_from_path(link).unwrap_or_else(|_| link.to_string())
 }
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index e8bc19f88e3..4da6acad2c0 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2544,7 +2544,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         }
 
         // Only use this directory if it has a file we can expect to always find.
-        if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
+        candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
     };
 
     let working_dir = std::env::current_dir().unwrap_or_else(|e| {
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index c851145440b..bd32adbbdbb 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -4,7 +4,7 @@ use crate::cgu_reuse_tracker::CguReuse;
 use crate::parse::ParseSess;
 use rustc_ast::token;
 use rustc_ast::util::literal::LitError;
-use rustc_errors::MultiSpan;
+use rustc_errors::{error_code, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, MultiSpan};
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
@@ -27,12 +27,22 @@ pub struct CguNotRecorded<'a> {
     pub cgu_name: &'a str,
 }
 
-#[derive(Diagnostic)]
-#[diag(session_feature_gate_error, code = "E0658")]
-pub struct FeatureGateError<'a> {
-    #[primary_span]
+pub struct FeatureGateError {
     pub span: MultiSpan,
-    pub explain: &'a str,
+    pub explain: DiagnosticMessage,
+}
+
+impl<'a, T: EmissionGuarantee> IntoDiagnostic<'a, T> for FeatureGateError {
+    #[track_caller]
+    fn into_diagnostic(
+        self,
+        handler: &'a rustc_errors::Handler,
+    ) -> rustc_errors::DiagnosticBuilder<'a, T> {
+        let mut diag = handler.struct_diagnostic(self.explain);
+        diag.set_span(self.span);
+        diag.code(error_code!(E0658));
+        diag
+    }
 }
 
 #[derive(Subdiagnostic)]
@@ -322,11 +332,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
                 .take_while(|c| *c != 'i' && *c != 'u')
                 .all(|c| c.to_digit(base).is_some());
 
-        if valid {
-            Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
-        } else {
-            None
-        }
+        valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
     }
 
     let token::Lit { kind, symbol, suffix, .. } = lit;
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index b6a328908ce..2075ed57a94 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -217,7 +217,7 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
                 // Look for the target rustlib directory in the suspected sysroot.
                 let mut rustlib_path = rustc_target::target_rustlib_path(&p, "dummy");
                 rustlib_path.pop(); // pop off the dummy target.
-                if rustlib_path.exists() { Some(p) } else { None }
+                rustlib_path.exists().then_some(p)
             }
             None => None,
         }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index d9e68320f8f..c784582012a 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -809,7 +809,7 @@ mod parse {
         if v.is_some() {
             let mut bool_arg = None;
             if parse_opt_bool(&mut bool_arg, v) {
-                *slot = if bool_arg.unwrap() { Some(MirSpanview::Statement) } else { None };
+                *slot = bool_arg.unwrap().then_some(MirSpanview::Statement);
                 return true;
             }
         }
@@ -850,7 +850,7 @@ mod parse {
         if v.is_some() {
             let mut bool_arg = None;
             if parse_opt_bool(&mut bool_arg, v) {
-                *slot = if bool_arg.unwrap() { Some(InstrumentCoverage::All) } else { None };
+                *slot = bool_arg.unwrap().then_some(InstrumentCoverage::All);
                 return true;
             }
         }
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 2aa8ca9e4a9..cbdcc5581e5 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -88,7 +88,7 @@ pub fn feature_err<'a>(
     sess: &'a ParseSess,
     feature: Symbol,
     span: impl Into<MultiSpan>,
-    explain: &str,
+    explain: impl Into<DiagnosticMessage>,
 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
     feature_err_issue(sess, feature, span, GateIssue::Language, explain)
 }
@@ -103,7 +103,7 @@ pub fn feature_err_issue<'a>(
     feature: Symbol,
     span: impl Into<MultiSpan>,
     issue: GateIssue,
-    explain: &str,
+    explain: impl Into<DiagnosticMessage>,
 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
     let span = span.into();
 
@@ -114,7 +114,7 @@ pub fn feature_err_issue<'a>(
             .map(|err| err.cancel());
     }
 
-    let mut err = sess.create_err(FeatureGateError { span, explain });
+    let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() });
     add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
     err
 }
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index cdda052f529..2340d501d5a 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -299,7 +299,7 @@ impl DefId {
 
     #[inline]
     pub fn as_local(self) -> Option<LocalDefId> {
-        if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None }
+        self.is_local().then(|| LocalDefId { local_def_index: self.index })
     }
 
     #[inline]
@@ -320,7 +320,7 @@ impl DefId {
 
     #[inline]
     pub fn as_crate_root(self) -> Option<CrateNum> {
-        if self.is_crate_root() { Some(self.krate) } else { None }
+        self.is_crate_root().then_some(self.krate)
     }
 
     #[inline]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 56835a2466a..37d2aea42ad 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1016,6 +1016,7 @@ symbols! {
         non_ascii_idents,
         non_exhaustive,
         non_exhaustive_omitted_patterns_lint,
+        non_lifetime_binders,
         non_modrs_mods,
         nontemporal_store,
         noop_method_borrow,
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 547a5907660..d81722e59a6 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -244,8 +244,7 @@ fn compute_symbol_name<'tcx>(
     // project.
     let avoid_cross_crate_conflicts = is_generic(substs) || is_globally_shared_function;
 
-    let instantiating_crate =
-        if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None };
+    let instantiating_crate = avoid_cross_crate_conflicts.then(compute_instantiating_crate);
 
     // Pick the crate responsible for the symbol mangling version, which has to:
     // 1. be stable for each instance, whether it's being defined or imported
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 52ed64868c0..91d96655b64 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -60,7 +60,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     ) -> Option<(DefId, SubstsRef<'tcx>)> {
         let tcx = self.tcx;
         let param_env = obligation.param_env;
-        let trait_ref = tcx.erase_late_bound_regions(trait_ref);
+        let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
         let trait_self_ty = trait_ref.self_ty();
 
         let mut self_match_impls = vec![];
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 135232d1b20..45a4cf2a083 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -82,11 +82,8 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
                     upvars.iter().find_map(|(upvar_id, upvar)| {
                         let upvar_ty = typeck_results.node_type(*upvar_id);
                         let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
-                        if ty_matches(ty::Binder::dummy(upvar_ty)) {
-                            Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
-                        } else {
-                            None
-                        }
+                        ty_matches(ty::Binder::dummy(upvar_ty))
+                            .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
                     })
                 })
             }
@@ -770,15 +767,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             obligation.param_env,
                             real_trait_pred_and_ty,
                         );
-                        if obligations
+                        let may_hold = obligations
                             .iter()
                             .chain([&obligation])
                             .all(|obligation| self.predicate_may_hold(obligation))
-                        {
-                            Some(steps)
-                        } else {
-                            None
-                        }
+                            .then_some(steps);
+
+                        may_hold
                     })
                 {
                     if steps > 0 {
@@ -1061,7 +1056,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
-        let ty = self.tcx.erase_late_bound_regions(self_ty);
+        let ty = self.instantiate_binder_with_placeholders(self_ty);
         let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { return false };
         let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
         let ty::Param(param) = inner_ty.kind() else { return false };
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 41ee8cd9d3f..2d299486ee6 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -523,16 +523,14 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
 
     let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
     let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
-        if pred.visit_with(&mut visitor).is_continue() {
-            Some(Obligation::new(
+        pred.visit_with(&mut visitor).is_continue().then(|| {
+            Obligation::new(
                 tcx,
                 ObligationCause::dummy_with_span(*span),
                 param_env,
                 ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
-            ))
-        } else {
-            None
-        }
+            )
+        })
     });
 
     let infcx = tcx.infer_ctxt().ignoring_regions().build();
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 7ef39b20107..4963f2d75fa 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -307,7 +307,7 @@ fn predicate_references_self<'tcx>(
     match predicate.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
             // In the case of a trait predicate, we can skip the "self" type.
-            if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+            data.trait_ref.substs[1..].iter().any(has_self_ty).then_some(sp)
         }
         ty::PredicateKind::Clause(ty::Clause::Projection(ref data)) => {
             // And similarly for projections. This should be redundant with
@@ -325,7 +325,7 @@ fn predicate_references_self<'tcx>(
             //
             // This is ALT2 in issue #56288, see that for discussion of the
             // possible alternatives.
-            if data.projection_ty.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+            data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp)
         }
         ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"),
 
@@ -527,8 +527,7 @@ fn virtual_call_violation_for_method<'tcx>(
                 }
             }
 
-            let trait_object_ty =
-                object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
+            let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static);
 
             // e.g., `Rc<dyn Trait>`
             let trait_object_receiver =
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a380d4697ea..7ddffe595be 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -767,7 +767,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderRegion { universe, name: br.kind };
                 self.mapped_regions.insert(p, br);
-                self.infcx.tcx.mk_region(ty::RePlaceholder(p))
+                self.infcx.tcx.mk_re_placeholder(p)
             }
             _ => r,
         }
@@ -888,7 +888,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
                         let db = ty::DebruijnIndex::from_usize(
                             self.universe_indices.len() - index + self.current_index.as_usize() - 1,
                         );
-                        self.interner().mk_region(ty::ReLateBound(db, *replace_var))
+                        self.interner().mk_re_late_bound(db, *replace_var)
                     }
                     None => r1,
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 0d42cd8250a..21ef4e24fdb 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -21,11 +21,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
         tcx: TyCtxt<'tcx>,
         key: &ParamEnvAnd<'tcx, Self>,
     ) -> Option<Self::QueryResponse> {
-        if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
-            Some(DropckOutlivesResult::default())
-        } else {
-            None
-        }
+        trivial_dropck_outlives(tcx, key.value.dropped_ty).then(DropckOutlivesResult::default)
     }
 
     fn perform_query(
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 e9f7c3bc4cc..dae602908a3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -396,7 +396,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // still be provided by a manual implementation for
                     // this trait and type.
                 }
-                ty::Param(..) | ty::Alias(ty::Projection, ..) => {
+                ty::Param(..)
+                | ty::Alias(ty::Projection, ..)
+                | ty::Placeholder(..)
+                | ty::Bound(..) => {
                     // In these cases, we don't know what the actual
                     // type is. Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -448,6 +451,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         );
 
         self.infcx.probe(|_snapshot| {
+            if obligation.has_non_region_late_bound() {
+                return;
+            }
+
             // The code below doesn't care about regions, and the
             // self-ty here doesn't escape this probe, so just erase
             // any LBR.
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index dc5bcb48cad..9770813e86d 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -540,13 +540,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                 let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
                                 let bound_var = ty::BoundVariableKind::Region(kind);
                                 bound_vars.push(bound_var);
-                                tcx.mk_region(ty::ReLateBound(
+                                tcx.mk_re_late_bound(
                                     ty::INNERMOST,
                                     ty::BoundRegion {
                                         var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                                         kind,
                                     },
-                                ))
+                                )
                                 .into()
                             }
                             GenericParamDefKind::Const { .. } => {
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index fc9678233c3..27feedc48be 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -378,11 +378,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             let self_ty = trait_ref.self_ty();
                             let (trait_desc, self_desc) = with_no_trimmed_paths!({
                                 let trait_desc = trait_ref.print_only_trait_path().to_string();
-                                let self_desc = if self_ty.has_concrete_skeleton() {
-                                    Some(self_ty.to_string())
-                                } else {
-                                    None
-                                };
+                                let self_desc =
+                                    self_ty.has_concrete_skeleton().then(|| self_ty.to_string());
                                 (trait_desc, self_desc)
                             });
                             let cause = if let Conflict::Upstream = conflict {
@@ -3023,7 +3020,7 @@ fn bind_generator_hidden_types_above<'tcx>(
                             kind: ty::BrAnon(counter, None),
                         };
                         counter += 1;
-                        r = tcx.mk_region(ty::ReLateBound(current_depth, br));
+                        r = tcx.mk_re_late_bound(current_depth, br);
                     }
                     r
                 })
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 0f9196de4fb..c3dcd64b2c2 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -113,7 +113,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
                     // Only report the `Self` type if it has at least
                     // some outer concrete shell; otherwise, it's
                     // not adding much information.
-                    self_ty: if self_ty.has_concrete_skeleton() { Some(self_ty) } else { None },
+                    self_ty: self_ty.has_concrete_skeleton().then_some(self_ty),
                     intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
                     involves_placeholder: overlap.involves_placeholder,
                 }
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 20725c656de..bb2b3ac6609 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -732,7 +732,7 @@ fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
                 var: ty::BoundVar::from_usize(substs.len()),
                 kind: ty::BrAnon(substs.len() as u32, None),
             };
-            tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
+            tcx.mk_re_late_bound(ty::INNERMOST, br).into()
         }
 
         ty::GenericParamDefKind::Const { .. } => tcx
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 2978fc4ed8c..9abbd0c5b34 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -521,8 +521,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
 
 impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'tcx>> {
     fn lower_into(self, interner: RustInterner<'tcx>) -> Region<'tcx> {
-        let kind = match self.data(interner) {
-            chalk_ir::LifetimeData::BoundVar(var) => ty::ReLateBound(
+        let tcx = interner.tcx;
+        match self.data(interner) {
+            chalk_ir::LifetimeData::BoundVar(var) => tcx.mk_re_late_bound(
                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
                 ty::BoundRegion {
                     var: ty::BoundVar::from_usize(var.index),
@@ -530,15 +531,14 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
                 },
             ),
             chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
-            chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
+            chalk_ir::LifetimeData::Placeholder(p) => tcx.mk_re_placeholder(ty::Placeholder {
                 universe: ty::UniverseIndex::from_usize(p.ui.counter),
                 name: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
             }),
-            chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
-            chalk_ir::LifetimeData::Erased => return interner.tcx.lifetimes.re_erased,
+            chalk_ir::LifetimeData::Static => tcx.lifetimes.re_static,
+            chalk_ir::LifetimeData::Erased => tcx.lifetimes.re_erased,
             chalk_ir::LifetimeData::Phantom(void, _) => match *void {},
-        };
-        interner.tcx.mk_region(kind)
+        }
     }
 }
 
@@ -1025,7 +1025,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for NamedBoundVarSubstitutor<'a, 'tcx> {
                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
                     Some(idx) => {
                         let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) };
-                        return self.tcx.mk_region(ty::ReLateBound(index, new_br));
+                        return self.tcx.mk_re_late_bound(index, new_br);
                     }
                     None => panic!("Missing `BrNamed`."),
                 },
@@ -1107,7 +1107,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                         var: ty::BoundVar::from_u32(*idx),
                         kind: ty::BrAnon(*idx, None),
                     };
-                    self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
+                    self.tcx.mk_re_late_bound(self.binder_index, br)
                 }
                 None => {
                     let idx = self.named_regions.len() as u32;
@@ -1116,7 +1116,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                         kind: ty::BrAnon(idx, None),
                     };
                     self.named_regions.insert(_re.def_id, idx);
-                    self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
+                    self.tcx.mk_re_late_bound(self.binder_index, br)
                 }
             },
 
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index ad5527f5a77..8b32c0119e0 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -70,7 +70,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                 kind: ty::BoundRegionKind::BrEnv,
             };
-            let env_region = ty::ReLateBound(ty::INNERMOST, br);
+            let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
             let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
 
             let sig = sig.skip_binder();
@@ -95,8 +95,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
                 kind: ty::BoundRegionKind::BrEnv,
             };
-            let env_region = ty::ReLateBound(ty::INNERMOST, br);
-            let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
+            let env_ty = tcx.mk_mut_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), ty);
 
             let pin_did = tcx.require_lang_item(LangItem::Pin, None);
             let pin_adt_ref = tcx.adt_def(pin_did);
@@ -207,11 +206,8 @@ fn fn_abi_of_instance<'tcx>(
 
     let sig = fn_sig_for_fn_abi(tcx, instance, param_env);
 
-    let caller_location = if instance.def.requires_caller_location(tcx) {
-        Some(tcx.caller_location_ty())
-    } else {
-        None
-    };
+    let caller_location =
+        instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty());
 
     fn_abi_new_uncached(
         &LayoutCx { tcx, param_env },
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 5a0b8594104..9e3e13e7004 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -3502,8 +3502,10 @@ pub trait Iterator {
         }
     }
 
-    /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
-    /// of another.
+    /// [Lexicographically](Ord#lexicographical-comparison) compares the [`PartialOrd`] elements of
+    /// this [`Iterator`] with those of another. The comparison works like short-circuit
+    /// evaluation, returning a result without comparing the remaining elements.
+    /// As soon as an order can be determined, the evaluation stops and a result is returned.
     ///
     /// # Examples
     ///
@@ -3513,9 +3515,25 @@ pub trait Iterator {
     /// assert_eq!([1.].iter().partial_cmp([1.].iter()), Some(Ordering::Equal));
     /// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
     /// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater));
+    /// ```
     ///
+    /// For floating-point numbers, NaN does not have a total order and will result
+    /// in `None` when compared:
+    ///
+    /// ```
     /// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None);
     /// ```
+    ///
+    /// The results are determined by the order of evaluation.
+    ///
+    /// ```
+    /// use std::cmp::Ordering;
+    ///
+    /// assert_eq!([1.0, f64::NAN].iter().partial_cmp([2.0, f64::NAN].iter()), Some(Ordering::Less));
+    /// assert_eq!([2.0, f64::NAN].iter().partial_cmp([1.0, f64::NAN].iter()), Some(Ordering::Greater));
+    /// assert_eq!([f64::NAN, 1.0].iter().partial_cmp([f64::NAN, 2.0].iter()), None);
+    /// ```
+    ///
     #[stable(feature = "iter_order", since = "1.5.0")]
     fn partial_cmp<I>(self, other: I) -> Option<Ordering>
     where
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 1675ed158c9..ff7821fb9ff 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -58,9 +58,10 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
         clippy_lint_warn.iter().for_each(|v| clippy_lint_levels.push(format!("-W{}", v)));
         clippy_lint_forbid.iter().for_each(|v| clippy_lint_levels.push(format!("-F{}", v)));
         args.extend(clippy_lint_levels);
+        args.extend(builder.config.free_args.clone());
         args
     } else {
-        vec![]
+        builder.config.free_args.clone()
     }
 }
 
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index e5fad538969..cd027a4abb7 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -97,6 +97,10 @@ pub struct Config {
     pub cmd: Subcommand,
     pub incremental: bool,
     pub dry_run: DryRun,
+    /// Arguments appearing after `--` to be forwarded to tools,
+    /// e.g. `--fix-broken` or test arguments.
+    pub free_args: Vec<String>,
+
     /// `None` if we shouldn't download CI compiler artifacts, or the commit to download if we should.
     #[cfg(not(test))]
     download_rustc_commit: Option<String>,
@@ -866,6 +870,7 @@ impl Config {
         config.keep_stage = flags.keep_stage;
         config.keep_stage_std = flags.keep_stage_std;
         config.color = flags.color;
+        config.free_args = flags.free_args.clone().unwrap_or_default();
         if let Some(value) = flags.deny_warnings {
             config.deny_warnings = value;
         }
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index ff927ed561b..f07e710a9e6 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -80,6 +80,10 @@ pub struct Flags {
     pub llvm_profile_generate: bool,
     pub llvm_bolt_profile_generate: bool,
     pub llvm_bolt_profile_use: Option<String>,
+
+    /// Arguments appearing after `--` to be forwarded to tools,
+    /// e.g. `--fix-broken` or test arguments.
+    pub free_args: Option<Vec<String>>,
 }
 
 #[derive(Debug)]
@@ -157,6 +161,12 @@ impl Default for Subcommand {
 
 impl Flags {
     pub fn parse(args: &[String]) -> Flags {
+        let (args, free_args) = if let Some(pos) = args.iter().position(|s| s == "--") {
+            let (args, free) = args.split_at(pos);
+            (args, Some(free[1..].to_vec()))
+        } else {
+            (args, None)
+        };
         let mut subcommand_help = String::from(
             "\
 Usage: x.py <subcommand> [options] [<paths>...]
@@ -709,6 +719,7 @@ Arguments:
             llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
             llvm_bolt_profile_generate: matches.opt_present("llvm-bolt-profile-generate"),
             llvm_bolt_profile_use: matches.opt_str("llvm-bolt-profile-use"),
+            free_args,
         }
     }
 }
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index e0280854541..e14440f57a8 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -183,6 +183,7 @@ impl Step for Miri {
         // Forward arguments.
         miri.arg("--").arg("--target").arg(target.rustc_target_arg());
         miri.args(builder.config.cmd.args());
+        miri.args(&builder.config.free_args);
 
         // miri tests need to know about the stage sysroot
         miri.env("MIRI_SYSROOT", &miri_sysroot);
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index f8835fe11a8..9cd6107b43a 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1588,6 +1588,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             .collect();
 
         test_args.append(&mut builder.config.cmd.test_args());
+        test_args.extend(builder.config.free_args.iter().map(|s| s.as_str()));
 
         // On Windows, replace forward slashes in test-args by backslashes
         // so the correct filters are passed to libtest
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 65736bb16fc..10af968e34f 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -11,6 +11,8 @@ pub(crate) mod types;
 pub(crate) mod utils;
 
 use rustc_ast as ast;
+use rustc_ast::token::{Token, TokenKind};
+use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
 use rustc_hir as hir;
@@ -19,7 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
 use rustc_hir::PredicateOrigin;
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
-use rustc_middle::middle::resolve_lifetime as rl;
+use rustc_middle::middle::resolve_bound_vars as rbv;
 use rustc_middle::ty::fold::ir::TypeFolder;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::TypeVisitable;
@@ -198,11 +200,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
 }
 
 fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
-    let def = cx.tcx.named_region(lifetime.hir_id);
+    let def = cx.tcx.named_bound_var(lifetime.hir_id);
     if let Some(
-        rl::Region::EarlyBound(node_id)
-        | rl::Region::LateBound(_, _, node_id)
-        | rl::Region::Free(_, node_id),
+        rbv::ResolvedArg::EarlyBound(node_id)
+        | rbv::ResolvedArg::LateBound(_, _, node_id)
+        | rbv::ResolvedArg::Free(_, node_id),
     ) = def
     {
         if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
@@ -2079,8 +2081,8 @@ impl<'hir> hir::intravisit::Visitor<'hir> for OneLevelVisitor<'hir> {
     fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
         if self.item.is_none()
             && item.ident == self.looking_for
-            && matches!(item.kind, hir::ItemKind::Use(_, _))
-            || item.owner_id.def_id == self.target_def_id
+            && (matches!(item.kind, hir::ItemKind::Use(_, _))
+                || item.owner_id.def_id == self.target_def_id)
         {
             self.item = Some(item);
         }
@@ -2096,34 +2098,149 @@ fn get_all_import_attributes<'hir>(
     tcx: TyCtxt<'hir>,
     target_def_id: LocalDefId,
     attributes: &mut Vec<ast::Attribute>,
+    is_inline: bool,
 ) {
     let hir_map = tcx.hir();
     let mut visitor = OneLevelVisitor::new(hir_map, target_def_id);
     let mut visited = FxHashSet::default();
     // If the item is an import and has at least a path with two parts, we go into it.
-    while let hir::ItemKind::Use(path, _) = item.kind &&
-        path.segments.len() > 1 &&
-        let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res &&
-        visited.insert(def_id)
-    {
-        if let Some(hir::Node::Item(parent_item)) = hir_map.get_if_local(def_id) {
-            // We add the attributes from this import into the list.
-            attributes.extend_from_slice(hir_map.attrs(item.hir_id()));
-            // We get the `Ident` we will be looking for into `item`.
-            let looking_for = path.segments[path.segments.len() - 1].ident;
-            visitor.reset(looking_for);
-            hir::intravisit::walk_item(&mut visitor, parent_item);
-            if let Some(i) = visitor.item {
-                item = i;
-            } else {
-                break;
+    while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) {
+        // We add the attributes from this import into the list.
+        add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
+
+        let def_id = if path.segments.len() > 1 {
+            match path.segments[path.segments.len() - 2].res {
+                hir::def::Res::Def(_, def_id) => def_id,
+                _ => break,
+            }
+        } else {
+            // If the path doesn't have a parent, then the parent is the current module.
+            tcx.parent(item.owner_id.def_id.to_def_id())
+        };
+
+        let Some(parent) = hir_map.get_if_local(def_id) else { break };
+
+        // We get the `Ident` we will be looking for into `item`.
+        let looking_for = path.segments[path.segments.len() - 1].ident;
+        visitor.reset(looking_for);
+
+        match parent {
+            hir::Node::Item(parent_item) => {
+                hir::intravisit::walk_item(&mut visitor, parent_item);
+            }
+            hir::Node::Crate(m) => {
+                hir::intravisit::walk_mod(
+                    &mut visitor,
+                    m,
+                    tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()),
+                );
             }
+            _ => break,
+        }
+        if let Some(i) = visitor.item {
+            item = i;
         } else {
             break;
         }
     }
 }
 
+fn filter_tokens_from_list(
+    args_tokens: TokenStream,
+    should_retain: impl Fn(&TokenTree) -> bool,
+) -> Vec<TokenTree> {
+    let mut tokens = Vec::with_capacity(args_tokens.len());
+    let mut skip_next_comma = false;
+    for token in args_tokens.into_trees() {
+        match token {
+            TokenTree::Token(Token { kind: TokenKind::Comma, .. }, _) if skip_next_comma => {
+                skip_next_comma = false;
+            }
+            token if should_retain(&token) => {
+                skip_next_comma = false;
+                tokens.push(token);
+            }
+            _ => {
+                skip_next_comma = true;
+            }
+        }
+    }
+    tokens
+}
+
+/// When inlining items, we merge its attributes (and all the reexports attributes too) with the
+/// final reexport. For example:
+///
+/// ```ignore (just an example)
+/// #[doc(hidden, cfg(feature = "foo"))]
+/// pub struct Foo;
+///
+/// #[doc(cfg(feature = "bar"))]
+/// #[doc(hidden, no_inline)]
+/// pub use Foo as Foo1;
+///
+/// #[doc(inline)]
+/// pub use Foo2 as Bar;
+/// ```
+///
+/// So `Bar` at the end will have both `cfg(feature = "...")`. However, we don't want to merge all
+/// attributes so we filter out the following ones:
+/// * `doc(inline)`
+/// * `doc(no_inline)`
+/// * `doc(hidden)`
+fn add_without_unwanted_attributes(
+    attrs: &mut Vec<ast::Attribute>,
+    new_attrs: &[ast::Attribute],
+    is_inline: bool,
+) {
+    // If it's `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything.
+    if !is_inline {
+        attrs.extend_from_slice(new_attrs);
+        return;
+    }
+    for attr in new_attrs {
+        let mut attr = attr.clone();
+        match attr.kind {
+            ast::AttrKind::Normal(ref mut normal) => {
+                if let [ident] = &*normal.item.path.segments &&
+                    let ident = ident.ident.name &&
+                    ident == sym::doc
+                {
+                    match normal.item.args {
+                        ast::AttrArgs::Delimited(ref mut args) => {
+                            let tokens =
+                                filter_tokens_from_list(args.tokens.clone(), |token| {
+                                    !matches!(
+                                        token,
+                                        TokenTree::Token(
+                                            Token {
+                                                kind: TokenKind::Ident(
+                                                    sym::hidden | sym::inline | sym::no_inline,
+                                                    _,
+                                                ),
+                                                ..
+                                            },
+                                            _,
+                                        ),
+                                    )
+                                });
+                            args.tokens = TokenStream::new(tokens);
+                            attrs.push(attr);
+                        }
+                        ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {
+                            attrs.push(attr);
+                            continue;
+                        }
+                    }
+                }
+            }
+            ast::AttrKind::DocComment(..) => {
+                attrs.push(attr);
+            }
+        }
+    }
+}
+
 fn clean_maybe_renamed_item<'tcx>(
     cx: &mut DocContext<'tcx>,
     item: &hir::Item<'tcx>,
@@ -2212,19 +2329,20 @@ fn clean_maybe_renamed_item<'tcx>(
         {
             // First, we add the attributes from the current import.
             extra_attrs.extend_from_slice(inline::load_attrs(cx, import_id.to_def_id()));
+            let is_inline = extra_attrs.lists(sym::doc).get_word_attr(sym::inline).is_some();
             // Then we get all the various imports' attributes.
-            get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs);
+            get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs, is_inline);
+            add_without_unwanted_attributes(&mut extra_attrs, inline::load_attrs(cx, def_id), is_inline);
+        } else {
+            // We only keep the item's attributes.
+            extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
         }
 
-        let mut item = if !extra_attrs.is_empty() {
-            extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
-            let attrs = Attributes::from_ast(&extra_attrs);
-            let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
+        let attrs = Attributes::from_ast(&extra_attrs);
+        let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
 
-            Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg)
-        } else {
-            Item::from_def_id_and_parts(def_id, Some(name), kind, cx)
-        };
+        let mut item =
+            Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg);
         item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id());
         vec![item]
     })
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 1ed0b0bc2d5..aa406f30cbe 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -361,7 +361,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
             for _ in 0..padding_amout {
                 br_with_padding.push_str(" ");
             }
-            let where_preds = where_preds.to_string().replace("\n", &br_with_padding);
+            let where_preds = where_preds.to_string().replace('\n', &br_with_padding);
 
             if ending == Ending::Newline {
                 let mut clause = " ".repeat(indent.saturating_sub(1));
@@ -1419,12 +1419,12 @@ impl clean::FnDecl {
             format!(
                 "({pad}{args}{close}){arrow}",
                 pad = if self.inputs.values.is_empty() { "" } else { &full_pad },
-                args = args.replace("\n", &full_pad),
+                args = args.replace('\n', &full_pad),
                 close = close_pad,
                 arrow = arrow
             )
         } else {
-            format!("({args}){arrow}", args = args.replace("\n", " "), arrow = arrow)
+            format!("({args}){arrow}", args = args.replace('\n', " "), arrow = arrow)
         };
 
         write!(f, "{}", output)
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index d88409c356e..fc550936165 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -505,13 +505,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
     if let FnRetTy::Return(ty) = sig.decl.output
         && let Some((out, Mutability::Mut, _)) = get_ref_lm(ty)
     {
-        let out_region = cx.tcx.named_region(out.hir_id);
+        let out_region = cx.tcx.named_bound_var(out.hir_id);
         let args: Option<Vec<_>> = sig
             .decl
             .inputs
             .iter()
             .filter_map(get_ref_lm)
-            .filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region)
+            .filter(|&(lt, _, _)| cx.tcx.named_bound_var(lt.hir_id) == out_region)
             .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span))
             .collect();
         if let Some(args) = args
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index ef3abb9514f..409f7563184 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -10,7 +10,7 @@ use std::path::Path;
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 940;
-const ISSUES_ENTRY_LIMIT: usize = 2001;
+const ISSUES_ENTRY_LIMIT: usize = 1978;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     for dir in Walk::new(&path.join("ui")) {
diff --git a/tests/rustdoc/reexport-attr-merge.rs b/tests/rustdoc/reexport-attr-merge.rs
new file mode 100644
index 00000000000..f6c23a1365f
--- /dev/null
+++ b/tests/rustdoc/reexport-attr-merge.rs
@@ -0,0 +1,33 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/59368>.
+// The goal is to ensure that `doc(hidden)`, `doc(inline)` and `doc(no_inline)`
+// are not copied from an item when inlined.
+
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+// @has 'foo/index.html'
+
+#[doc(hidden, cfg(feature = "foo"))]
+pub struct Foo;
+
+#[doc(hidden, no_inline, cfg(feature = "bar"))]
+pub use Foo as Foo1;
+
+#[doc(hidden, inline)]
+pub use Foo1 as Foo2;
+
+// First we ensure that only the reexport `Bar2` and the inlined struct `Bar`
+// are inlined.
+// @count - '//a[@class="struct"]' 2
+// Then we check that both `cfg` are displayed.
+// @has - '//*[@class="stab portability"]' 'foo'
+// @has - '//*[@class="stab portability"]' 'bar'
+// And finally we check that the only element displayed is `Bar`.
+// @has - '//a[@class="struct"]' 'Bar'
+#[doc(inline)]
+pub use Foo2 as Bar;
+
+// This one should appear but `Bar2` won't be linked because there is no
+// `#[doc(inline)]`.
+// @has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;'
+pub use Foo2 as Bar2;
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
index 77ea8ef0520..d1b9d7a40b4 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
@@ -7,7 +7,10 @@ LL |   fn oom() -> ! {
    |  _-^^^^^^^^^^^^
 LL | |     loop {}
 LL | | }
-   | |_- argument of type `core::alloc::Layout` unexpected
+   | | -
+   | | |
+   | |_unexpected argument of type `core::alloc::Layout`
+   |   help: remove the extra argument
    |
 note: function defined here
   --> $DIR/alloc-error-handler-bad-signature-3.rs:10:4
@@ -15,10 +18,6 @@ note: function defined here
 LL | fn oom() -> ! {
    |    ^^^
    = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: remove the extra argument
-   |
-LL | fn oom() -> !() {
-   |              ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/argument-suggestions/basic.stderr b/tests/ui/argument-suggestions/basic.stderr
index 062b3768858..c74186285f9 100644
--- a/tests/ui/argument-suggestions/basic.stderr
+++ b/tests/ui/argument-suggestions/basic.stderr
@@ -16,17 +16,16 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/basic.rs:21:5
    |
 LL |     extra("");
-   |     ^^^^^ -- argument of type `&'static str` unexpected
+   |     ^^^^^ --
+   |           |
+   |           unexpected argument of type `&'static str`
+   |           help: remove the extra argument
    |
 note: function defined here
   --> $DIR/basic.rs:14:4
    |
 LL | fn extra() {}
    |    ^^^^^
-help: remove the extra argument
-   |
-LL |     extra();
-   |          ~~
 
 error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/basic.rs:22:5
diff --git a/tests/ui/argument-suggestions/exotic-calls.stderr b/tests/ui/argument-suggestions/exotic-calls.stderr
index 0580e53c510..ff795b507f2 100644
--- a/tests/ui/argument-suggestions/exotic-calls.stderr
+++ b/tests/ui/argument-suggestions/exotic-calls.stderr
@@ -2,65 +2,61 @@ error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:2:5
    |
 LL |     t(1i32);
-   |     ^ ---- argument of type `i32` unexpected
+   |     ^ ----
+   |       |
+   |       unexpected argument of type `i32`
+   |       help: remove the extra argument
    |
 note: callable defined here
   --> $DIR/exotic-calls.rs:1:11
    |
 LL | fn foo<T: Fn()>(t: T) {
    |           ^^^^
-help: remove the extra argument
-   |
-LL |     t();
-   |      ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:7:5
    |
 LL |     t(1i32);
-   |     ^ ---- argument of type `i32` unexpected
+   |     ^ ----
+   |       |
+   |       unexpected argument of type `i32`
+   |       help: remove the extra argument
    |
 note: type parameter defined here
   --> $DIR/exotic-calls.rs:6:11
    |
 LL | fn bar(t: impl Fn()) {
    |           ^^^^^^^^^
-help: remove the extra argument
-   |
-LL |     t();
-   |      ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:16:5
    |
 LL |     baz()(1i32)
-   |     ^^^^^ ---- argument of type `i32` unexpected
+   |     ^^^^^ ----
+   |           |
+   |           unexpected argument of type `i32`
+   |           help: remove the extra argument
    |
 note: opaque type defined here
   --> $DIR/exotic-calls.rs:11:13
    |
 LL | fn baz() -> impl Fn() {
    |             ^^^^^^^^^
-help: remove the extra argument
-   |
-LL |     baz()()
-   |          ~~
 
 error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/exotic-calls.rs:22:5
    |
 LL |     x(1i32);
-   |     ^ ---- argument of type `i32` unexpected
+   |     ^ ----
+   |       |
+   |       unexpected argument of type `i32`
+   |       help: remove the extra argument
    |
 note: closure defined here
   --> $DIR/exotic-calls.rs:21:13
    |
 LL |     let x = || {};
    |             ^^
-help: remove the extra argument
-   |
-LL |     x();
-   |      ~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr
index 48787b0c352..0911685b428 100644
--- a/tests/ui/argument-suggestions/extra_arguments.stderr
+++ b/tests/ui/argument-suggestions/extra_arguments.stderr
@@ -2,57 +2,54 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/extra_arguments.rs:7:3
    |
 LL |   empty("");
-   |   ^^^^^ -- argument of type `&'static str` unexpected
+   |   ^^^^^ --
+   |         |
+   |         unexpected argument of type `&'static str`
+   |         help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:1:4
    |
 LL | fn empty() {}
    |    ^^^^^
-help: remove the extra argument
-   |
-LL |   empty();
-   |        ~~
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:9:3
    |
 LL |   one_arg(1, 1);
-   |   ^^^^^^^    - argument of type `{integer}` unexpected
+   |   ^^^^^^^  ---
+   |            | |
+   |            | unexpected argument of type `{integer}`
+   |            help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
    |
 LL | fn one_arg(_a: i32) {}
    |    ^^^^^^^ -------
-help: remove the extra argument
-   |
-LL |   one_arg(1);
-   |          ~~~
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/extra_arguments.rs:10:3
    |
 LL |   one_arg(1, "");
-   |   ^^^^^^^    -- argument of type `&'static str` unexpected
+   |   ^^^^^^^  ----
+   |            | |
+   |            | unexpected argument of type `&'static str`
+   |            help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
    |
 LL | fn one_arg(_a: i32) {}
    |    ^^^^^^^ -------
-help: remove the extra argument
-   |
-LL |   one_arg(1);
-   |          ~~~
 
 error[E0061]: this function takes 1 argument but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:11:3
    |
 LL |   one_arg(1, "", 1.0);
-   |   ^^^^^^^    --  --- argument of type `{float}` unexpected
+   |   ^^^^^^^    --  --- unexpected argument of type `{float}`
    |              |
-   |              argument of type `&'static str` unexpected
+   |              unexpected argument of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
@@ -61,80 +58,77 @@ LL | fn one_arg(_a: i32) {}
    |    ^^^^^^^ -------
 help: remove the extra arguments
    |
-LL |   one_arg(1);
-   |          ~~~
+LL -   one_arg(1, "", 1.0);
+LL +   one_arg(1);
+   |
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:13:3
    |
 LL |   two_arg_same(1, 1, 1);
-   |   ^^^^^^^^^^^^       - argument of type `{integer}` unexpected
+   |   ^^^^^^^^^^^^     ---
+   |                    | |
+   |                    | unexpected argument of type `{integer}`
+   |                    help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
-help: remove the extra argument
-   |
-LL |   two_arg_same(1, 1);
-   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:14:3
    |
 LL |   two_arg_same(1, 1, 1.0);
-   |   ^^^^^^^^^^^^       --- argument of type `{float}` unexpected
+   |   ^^^^^^^^^^^^     -----
+   |                    | |
+   |                    | unexpected argument of type `{float}`
+   |                    help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
-help: remove the extra argument
-   |
-LL |   two_arg_same(1, 1);
-   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:16:3
    |
 LL |   two_arg_diff(1, 1, "");
-   |   ^^^^^^^^^^^^    - argument of type `{integer}` unexpected
+   |   ^^^^^^^^^^^^  ---
+   |                 | |
+   |                 | unexpected argument of type `{integer}`
+   |                 help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
    |
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
-help: remove the extra argument
-   |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:17:3
    |
 LL |   two_arg_diff(1, "", "");
-   |   ^^^^^^^^^^^^        -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^^^      ----
+   |                     | |
+   |                     | unexpected argument of type `&'static str`
+   |                     help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
    |
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
-help: remove the extra argument
-   |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/extra_arguments.rs:18:3
    |
 LL |   two_arg_diff(1, 1, "", "");
-   |   ^^^^^^^^^^^^    -      -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^^^    -      -- unexpected argument of type `&'static str`
    |                   |
-   |                   argument of type `{integer}` unexpected
+   |                   unexpected argument of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -143,16 +137,17 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 help: remove the extra arguments
    |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
+LL -   two_arg_diff(1, 1, "", "");
+LL +   two_arg_diff(1, "");
+   |
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
   --> $DIR/extra_arguments.rs:19:3
    |
 LL |   two_arg_diff(1, "", 1, "");
-   |   ^^^^^^^^^^^^        -  -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^^^        -  -- unexpected argument of type `&'static str`
    |                       |
-   |                       argument of type `{integer}` unexpected
+   |                       unexpected argument of type `{integer}`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
@@ -161,78 +156,78 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 help: remove the extra arguments
    |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
+LL -   two_arg_diff(1, "", 1, "");
+LL +   two_arg_diff(1, "");
+   |
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:22:3
    |
 LL |   two_arg_same(1, 1,     "");
-   |   ^^^^^^^^^^^^           -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^^^     --------
+   |                    |     |
+   |                    |     unexpected argument of type `&'static str`
+   |                    help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
-help: remove the extra argument
-   |
-LL |   two_arg_same(1, 1);
-   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:23:3
    |
 LL |   two_arg_diff(1, 1,     "");
-   |   ^^^^^^^^^^^^    - argument of type `{integer}` unexpected
+   |   ^^^^^^^^^^^^  ---
+   |                 | |
+   |                 | unexpected argument of type `{integer}`
+   |                 help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
    |
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
-help: remove the extra argument
-   |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:24:3
    |
-LL |   two_arg_same(
-   |   ^^^^^^^^^^^^
-...
-LL |     ""
-   |     -- argument of type `&'static str` unexpected
+LL |     two_arg_same(
+   |     ^^^^^^^^^^^^
+LL |       1,
+LL |       1,
+   |  ______-
+LL | |     ""
+   | |     --
+   | |_____||
+   |       |help: remove the extra argument
+   |       unexpected argument of type `&'static str`
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:3:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
-help: remove the extra argument
-   |
-LL |   two_arg_same(1, 1);
-   |               ~~~~~~
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/extra_arguments.rs:30:3
    |
-LL |   two_arg_diff(
-   |   ^^^^^^^^^^^^
-LL |     1,
-LL |     1,
-   |     - argument of type `{integer}` unexpected
+LL |     two_arg_diff(
+   |     ^^^^^^^^^^^^
+LL |       1,
+   |  ______-
+LL | |     1,
+   | |     -
+   | |     |
+   | |_____unexpected argument of type `{integer}`
+   |       help: remove the extra argument
    |
 note: function defined here
   --> $DIR/extra_arguments.rs:4:4
    |
 LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
-help: remove the extra argument
-   |
-LL |   two_arg_diff(1, "");
-   |               ~~~~~~~
 
 error: aborting due to 14 previous errors
 
diff --git a/tests/ui/argument-suggestions/issue-101097.stderr b/tests/ui/argument-suggestions/issue-101097.stderr
index 7582082ac72..061f510144b 100644
--- a/tests/ui/argument-suggestions/issue-101097.stderr
+++ b/tests/ui/argument-suggestions/issue-101097.stderr
@@ -4,7 +4,7 @@ error[E0061]: this function takes 6 arguments but 7 arguments were supplied
 LL |     f(C, A, A, A, B, B, C);
    |     ^ -     -  -  - expected `C`, found `B`
    |       |     |  |
-   |       |     |  argument of type `A` unexpected
+   |       |     |  unexpected argument of type `A`
    |       |     expected `B`, found `A`
    |       expected `A`, found `C`
    |
@@ -64,8 +64,8 @@ error[E0308]: arguments to this function are incorrect
 LL |     f(A, A, D, D, B, B);
    |     ^       -  -  ---- two arguments of type `C` and `C` are missing
    |             |  |
-   |             |  argument of type `D` unexpected
-   |             argument of type `D` unexpected
+   |             |  unexpected argument of type `D`
+   |             unexpected argument of type `D`
    |
 note: function defined here
   --> $DIR/issue-101097.rs:6:4
diff --git a/tests/ui/argument-suggestions/issue-97484.stderr b/tests/ui/argument-suggestions/issue-97484.stderr
index c2e6e001b17..a86cbbf1802 100644
--- a/tests/ui/argument-suggestions/issue-97484.stderr
+++ b/tests/ui/argument-suggestions/issue-97484.stderr
@@ -2,11 +2,11 @@ error[E0061]: this function takes 4 arguments but 7 arguments were supplied
   --> $DIR/issue-97484.rs:12:5
    |
 LL |     foo(&&A, B, C, D, E, F, G);
-   |     ^^^      -  -     -  - argument of type `F` unexpected
+   |     ^^^      -  -     -  - unexpected argument of type `F`
    |              |  |     |
    |              |  |     expected `&E`, found `E`
-   |              |  argument of type `C` unexpected
-   |              argument of type `B` unexpected
+   |              |  unexpected argument of type `C`
+   |              unexpected argument of type `B`
    |
 note: function defined here
   --> $DIR/issue-97484.rs:9:4
@@ -19,8 +19,9 @@ LL |     foo(&&A, B, C, D, &E, F, G);
    |                       ~~
 help: remove the extra arguments
    |
-LL |     foo(&&A, D, /* &E */, G);
-   |        ~~~~~~~~~~~~~~~~~~~~~
+LL -     foo(&&A, B, C, D, E, F, G);
+LL +     foo(&&A, D, /* &E */, G);
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/argument-suggestions/mixed_cases.stderr b/tests/ui/argument-suggestions/mixed_cases.stderr
index 8cf48060a63..c645dd38179 100644
--- a/tests/ui/argument-suggestions/mixed_cases.stderr
+++ b/tests/ui/argument-suggestions/mixed_cases.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/mixed_cases.rs:10:3
    |
 LL |   two_args(1, "", X {});
-   |   ^^^^^^^^    --  ---- argument of type `X` unexpected
+   |   ^^^^^^^^    --  ---- unexpected argument of type `X`
    |               |
    |               expected `f32`, found `&str`
    |
@@ -13,16 +13,17 @@ LL | fn two_args(_a: i32, _b: f32) {}
    |    ^^^^^^^^ -------  -------
 help: remove the extra argument
    |
-LL |   two_args(1, /* f32 */);
-   |           ~~~~~~~~~~~~~~
+LL -   two_args(1, "", X {});
+LL +   two_args(1, /* f32 */);
+   |
 
 error[E0061]: this function takes 3 arguments but 4 arguments were supplied
   --> $DIR/mixed_cases.rs:11:3
    |
 LL |   three_args(1, "", X {}, "");
-   |   ^^^^^^^^^^    --  ----  -- argument of type `&'static str` unexpected
+   |   ^^^^^^^^^^    --  ----  -- unexpected argument of type `&'static str`
    |                 |   |
-   |                 |   argument of type `X` unexpected
+   |                 |   unexpected argument of type `X`
    |                 an argument of type `f32` is missing
    |
 note: function defined here
@@ -58,7 +59,7 @@ error[E0308]: arguments to this function are incorrect
   --> $DIR/mixed_cases.rs:17:3
    |
 LL |   three_args(1, "", X {});
-   |   ^^^^^^^^^^    --  ---- argument of type `X` unexpected
+   |   ^^^^^^^^^^    --  ---- unexpected argument of type `X`
    |                 |
    |                 an argument of type `f32` is missing
    |
diff --git a/tests/ui/issues/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs
index 6753860e9ff..6753860e9ff 100644
--- a/tests/ui/issues/issue-38821.rs
+++ b/tests/ui/associated-types/issue-38821.rs
diff --git a/tests/ui/issues/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr
index a52a9c138f1..a52a9c138f1 100644
--- a/tests/ui/issues/issue-38821.stderr
+++ b/tests/ui/associated-types/issue-38821.stderr
diff --git a/tests/ui/issues/issue-83924.fixed b/tests/ui/borrowck/issue-83924.fixed
index aa40da12b87..aa40da12b87 100644
--- a/tests/ui/issues/issue-83924.fixed
+++ b/tests/ui/borrowck/issue-83924.fixed
diff --git a/tests/ui/issues/issue-83924.rs b/tests/ui/borrowck/issue-83924.rs
index 22b80fe2f38..22b80fe2f38 100644
--- a/tests/ui/issues/issue-83924.rs
+++ b/tests/ui/borrowck/issue-83924.rs
diff --git a/tests/ui/issues/issue-83924.stderr b/tests/ui/borrowck/issue-83924.stderr
index 572414df2bf..572414df2bf 100644
--- a/tests/ui/issues/issue-83924.stderr
+++ b/tests/ui/borrowck/issue-83924.stderr
diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/bounds-lifetime.stderr
index a0395ed4904..a3427e21cde 100644
--- a/tests/ui/bounds-lifetime.stderr
+++ b/tests/ui/bounds-lifetime.stderr
@@ -16,17 +16,24 @@ error: lifetime bounds cannot be used in this context
 LL | type C = for<'b, 'a: 'b +> fn();
    |                      ^^
 
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/bounds-lifetime.rs:4:18
    |
 LL | type D = for<'a, T> fn();
    |                  ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/bounds-lifetime.rs:5:18
    |
 LL | type E = dyn for<T> Fn();
    |                  ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
 error: aborting due to 5 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr
index 3c3b43d8cf3..9f4deaa774d 100644
--- a/tests/ui/closures/binder/disallow-const.stderr
+++ b/tests/ui/closures/binder/disallow-const.stderr
@@ -1,8 +1,12 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/disallow-const.rs:4:15
    |
 LL |     for<const N: i32> || -> () {};
    |               ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr
index 51b6773edea..22882ca2ba6 100644
--- a/tests/ui/closures/binder/disallow-ty.stderr
+++ b/tests/ui/closures/binder/disallow-ty.stderr
@@ -1,8 +1,12 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/disallow-ty.rs:4:9
    |
 LL |     for<T> || -> () {};
    |         ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr
index 4d6560e96e5..69b0f741156 100644
--- a/tests/ui/conditional-compilation/cfg-generic-params.stderr
+++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr
@@ -1,21 +1,3 @@
-error: only lifetime parameters can be used in this context
-  --> $DIR/cfg-generic-params.rs:7:45
-   |
-LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
-   |                                             ^
-
-error: only lifetime parameters can be used in this context
-  --> $DIR/cfg-generic-params.rs:11:51
-   |
-LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
-   |                                                   ^
-
-error: only lifetime parameters can be used in this context
-  --> $DIR/cfg-generic-params.rs:15:54
-   |
-LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
-   |                                                      ^
-
 error: cannot find attribute `unknown` in this scope
   --> $DIR/cfg-generic-params.rs:19:29
    |
@@ -46,5 +28,33 @@ error: cannot find attribute `unknown` in this scope
 LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
    |                                           ^^^^^^^
 
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:7:45
+   |
+LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
+   |                                             ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:11:51
+   |
+LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
+   |                                                   ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/cfg-generic-params.rs:15:54
+   |
+LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
+   |                                                      ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
 error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/issues/issue-33903.rs b/tests/ui/consts/issue-33903.rs
index 613aa121a47..613aa121a47 100644
--- a/tests/ui/issues/issue-33903.rs
+++ b/tests/ui/consts/issue-33903.rs
diff --git a/tests/ui/issues/issue-54582.rs b/tests/ui/consts/issue-54582.rs
index 8c50cac67f8..8c50cac67f8 100644
--- a/tests/ui/issues/issue-54582.rs
+++ b/tests/ui/consts/issue-54582.rs
diff --git a/tests/ui/issues/issue-2735-2.rs b/tests/ui/drop/issue-2735-2.rs
index 70ebce9d35a..70ebce9d35a 100644
--- a/tests/ui/issues/issue-2735-2.rs
+++ b/tests/ui/drop/issue-2735-2.rs
diff --git a/tests/ui/issues/issue-2735-3.rs b/tests/ui/drop/issue-2735-3.rs
index 23301537835..23301537835 100644
--- a/tests/ui/issues/issue-2735-3.rs
+++ b/tests/ui/drop/issue-2735-3.rs
diff --git a/tests/ui/issues/issue-2735.rs b/tests/ui/drop/issue-2735.rs
index 20d3949a9f9..20d3949a9f9 100644
--- a/tests/ui/issues/issue-2735.rs
+++ b/tests/ui/drop/issue-2735.rs
diff --git a/tests/ui/error-codes/E0057.stderr b/tests/ui/error-codes/E0057.stderr
index 163737895fe..9b0cf069824 100644
--- a/tests/ui/error-codes/E0057.stderr
+++ b/tests/ui/error-codes/E0057.stderr
@@ -18,17 +18,16 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/E0057.rs:5:13
    |
 LL |     let c = f(2, 3);
-   |             ^    - argument of type `{integer}` unexpected
+   |             ^  ---
+   |                | |
+   |                | unexpected argument of type `{integer}`
+   |                help: remove the extra argument
    |
 note: closure defined here
   --> $DIR/E0057.rs:2:13
    |
 LL |     let f = |x| x * 3;
    |             ^^^
-help: remove the extra argument
-   |
-LL |     let c = f(2);
-   |              ~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs
new file mode 100644
index 00000000000..221e9133fcc
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs
@@ -0,0 +1,4 @@
+fn foo() where for<T> T:, {}
+//~^ ERROR only lifetime parameters can be used in this context
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr
new file mode 100644
index 00000000000..75645e32401
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr
@@ -0,0 +1,12 @@
+error[E0658]: only lifetime parameters can be used in this context
+  --> $DIR/feature-gate-non_lifetime_binders.rs:1:20
+   |
+LL | fn foo() where for<T> T:, {}
+   |                    ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/issues/issue-75307.rs b/tests/ui/fmt/issue-75307.rs
index cffa6bea8ed..cffa6bea8ed 100644
--- a/tests/ui/issues/issue-75307.rs
+++ b/tests/ui/fmt/issue-75307.rs
diff --git a/tests/ui/issues/issue-75307.stderr b/tests/ui/fmt/issue-75307.stderr
index c5b0b11e7d0..c5b0b11e7d0 100644
--- a/tests/ui/issues/issue-75307.stderr
+++ b/tests/ui/fmt/issue-75307.stderr
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
index f31aa554634..d605c9e0df7 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
+++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
@@ -1,14 +1,21 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/hrtb-wrong-kind.rs:1:18
    |
 LL | fn a() where for<T> T: Copy {}
    |                  ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
   --> $DIR/hrtb-wrong-kind.rs:4:24
    |
 LL | fn b() where for<const C: usize> [(); C]: Copy {}
    |                        ^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/issues/issue-39292.rs b/tests/ui/higher-rank-trait-bounds/issue-39292.rs
index 968cf08916f..968cf08916f 100644
--- a/tests/ui/issues/issue-39292.rs
+++ b/tests/ui/higher-rank-trait-bounds/issue-39292.rs
diff --git a/tests/ui/issues/issue-16939.stderr b/tests/ui/issues/issue-16939.stderr
index 76645645464..6db29bc61b1 100644
--- a/tests/ui/issues/issue-16939.stderr
+++ b/tests/ui/issues/issue-16939.stderr
@@ -2,17 +2,16 @@ error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/issue-16939.rs:5:9
    |
 LL |     |t| f(t);
-   |         ^ - argument unexpected
+   |         ^ -
+   |           |
+   |           unexpected argument
+   |           help: remove the extra argument
    |
 note: callable defined here
   --> $DIR/issue-16939.rs:4:12
    |
 LL | fn _foo<F: Fn()> (f: F) {
    |            ^^^^
-help: remove the extra argument
-   |
-LL |     |t| f();
-   |          ~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-26094.rs b/tests/ui/issues/issue-26094.rs
index d3d670aa92a..abf3543ddb9 100644
--- a/tests/ui/issues/issue-26094.rs
+++ b/tests/ui/issues/issue-26094.rs
@@ -1,6 +1,6 @@
 macro_rules! some_macro {
     ($other: expr) => ({
-        $other(None) //~ NOTE argument of type `Option<_>` unexpected
+        $other(None) //~ NOTE unexpected argument of type `Option<_>`
     })
 }
 
diff --git a/tests/ui/issues/issue-26094.stderr b/tests/ui/issues/issue-26094.stderr
index 881a6e538ee..608d2c7aff9 100644
--- a/tests/ui/issues/issue-26094.stderr
+++ b/tests/ui/issues/issue-26094.stderr
@@ -2,7 +2,10 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/issue-26094.rs:10:17
    |
 LL |         $other(None)
-   |                ---- argument of type `Option<_>` unexpected
+   |                ----
+   |                |
+   |                unexpected argument of type `Option<_>`
+   |                help: remove the extra argument
 ...
 LL |     some_macro!(some_function);
    |                 ^^^^^^^^^^^^^
@@ -12,10 +15,6 @@ note: function defined here
    |
 LL | fn some_function() {}
    |    ^^^^^^^^^^^^^
-help: remove the extra argument
-   |
-LL |         some_function()
-   |         ~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-4935.stderr b/tests/ui/issues/issue-4935.stderr
index bb45fa08338..e544e424403 100644
--- a/tests/ui/issues/issue-4935.stderr
+++ b/tests/ui/issues/issue-4935.stderr
@@ -2,17 +2,16 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/issue-4935.rs:5:13
    |
 LL | fn main() { foo(5, 6) }
-   |             ^^^    - argument of type `{integer}` unexpected
+   |             ^^^  ---
+   |                  | |
+   |                  | unexpected argument of type `{integer}`
+   |                  help: remove the extra argument
    |
 note: function defined here
   --> $DIR/issue-4935.rs:3:4
    |
 LL | fn foo(a: usize) {}
    |    ^^^ --------
-help: remove the extra argument
-   |
-LL | fn main() { foo(5) }
-   |                ~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-50576.rs b/tests/ui/loops/issue-50576.rs
index e0c36b8273a..e0c36b8273a 100644
--- a/tests/ui/issues/issue-50576.rs
+++ b/tests/ui/loops/issue-50576.rs
diff --git a/tests/ui/issues/issue-50576.stderr b/tests/ui/loops/issue-50576.stderr
index 4ec22fde910..4ec22fde910 100644
--- a/tests/ui/issues/issue-50576.stderr
+++ b/tests/ui/loops/issue-50576.stderr
diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr
index 81269b73b9a..0f37e8f09a9 100644
--- a/tests/ui/methods/method-call-err-msg.stderr
+++ b/tests/ui/methods/method-call-err-msg.stderr
@@ -2,17 +2,16 @@ error[E0061]: this method takes 0 arguments but 1 argument was supplied
   --> $DIR/method-call-err-msg.rs:13:7
    |
 LL |     x.zero(0)
-   |       ^^^^ - argument of type `{integer}` unexpected
+   |       ^^^^ -
+   |            |
+   |            unexpected argument of type `{integer}`
+   |            help: remove the extra argument
    |
 note: associated function defined here
   --> $DIR/method-call-err-msg.rs:5:8
    |
 LL |     fn zero(self) -> Foo { self }
    |        ^^^^
-help: remove the extra argument
-   |
-LL |     x.zero()
-   |           ~~
 
 error[E0061]: this method takes 1 argument but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:14:7
diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.stderr b/tests/ui/mismatched_types/overloaded-calls-bad.stderr
index 3a895acbdb5..cd483e7ad2c 100644
--- a/tests/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/tests/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -32,7 +32,7 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:37:15
    |
 LL |     let ans = s("burma", "shave");
-   |               ^ -------  ------- argument of type `&'static str` unexpected
+   |               ^ -------  ------- unexpected argument of type `&'static str`
    |                 |
    |                 expected `isize`, found `&str`
    |
@@ -43,8 +43,9 @@ LL | impl FnMut<(isize,)> for S {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: remove the extra argument
    |
-LL |     let ans = s(/* isize */);
-   |                ~~~~~~~~~~~~~
+LL -     let ans = s("burma", "shave");
+LL +     let ans = s(/* isize */);
+   |
 
 error[E0308]: mismatched types
   --> $DIR/overloaded-calls-bad.rs:40:7
diff --git a/tests/ui/issues/issue-22536-copy-mustnt-zero.rs b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs
index 017f36484c1..017f36484c1 100644
--- a/tests/ui/issues/issue-22536-copy-mustnt-zero.rs
+++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs
diff --git a/tests/ui/issues/issue-27583.rs b/tests/ui/nll/issue-27583.rs
index 84c94c7c905..84c94c7c905 100644
--- a/tests/ui/issues/issue-27583.rs
+++ b/tests/ui/nll/issue-27583.rs
diff --git a/tests/ui/issues/issue-48179.rs b/tests/ui/nll/issue-48179.rs
index f81203dc412..f81203dc412 100644
--- a/tests/ui/issues/issue-48179.rs
+++ b/tests/ui/nll/issue-48179.rs
diff --git a/tests/ui/issues/issue-75777.rs b/tests/ui/nll/issue-75777.rs
index a1e438bc617..a1e438bc617 100644
--- a/tests/ui/issues/issue-75777.rs
+++ b/tests/ui/nll/issue-75777.rs
diff --git a/tests/ui/issues/issue-75777.stderr b/tests/ui/nll/issue-75777.stderr
index 370cd72fd55..370cd72fd55 100644
--- a/tests/ui/issues/issue-75777.stderr
+++ b/tests/ui/nll/issue-75777.stderr
diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.stderr b/tests/ui/parser/recover-fn-ptr-with-generics.stderr
index 1da9c18571b..069fcffe9a0 100644
--- a/tests/ui/parser/recover-fn-ptr-with-generics.stderr
+++ b/tests/ui/parser/recover-fn-ptr-with-generics.stderr
@@ -88,12 +88,6 @@ error: expected identifier, found `>`
 LL |     type QuiteBroken = fn<const>();
    |                                ^ expected identifier
 
-error: lifetime bounds cannot be used in this context
-  --> $DIR/recover-fn-ptr-with-generics.rs:22:26
-   |
-LL |     let _: extern fn<'a: 'static>();
-   |                          ^^^^^^^
-
 error[E0412]: cannot find type `T` in this scope
   --> $DIR/recover-fn-ptr-with-generics.rs:5:27
    |
@@ -106,6 +100,12 @@ error[E0412]: cannot find type `T` in this scope
 LL |     type Identity = fn<T>(T) -> T;
    |                                 ^ not found in this scope
 
+error: lifetime bounds cannot be used in this context
+  --> $DIR/recover-fn-ptr-with-generics.rs:22:26
+   |
+LL |     let _: extern fn<'a: 'static>();
+   |                          ^^^^^^^
+
 error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/issues/issue-40003.rs b/tests/ui/recursion_limit/issue-40003.rs
index 5e61361f987..5e61361f987 100644
--- a/tests/ui/issues/issue-40003.rs
+++ b/tests/ui/recursion_limit/issue-40003.rs
diff --git a/tests/ui/resolve/resolve-primitive-fallback.stderr b/tests/ui/resolve/resolve-primitive-fallback.stderr
index 964302e924c..f803f9da2af 100644
--- a/tests/ui/resolve/resolve-primitive-fallback.stderr
+++ b/tests/ui/resolve/resolve-primitive-fallback.stderr
@@ -24,14 +24,13 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/resolve-primitive-fallback.rs:3:5
    |
 LL |     std::mem::size_of(u16);
-   |     ^^^^^^^^^^^^^^^^^ --- argument unexpected
+   |     ^^^^^^^^^^^^^^^^^ ---
+   |                       |
+   |                       unexpected argument
+   |                       help: remove the extra argument
    |
 note: function defined here
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-help: remove the extra argument
-   |
-LL |     std::mem::size_of();
-   |                      ~~
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr
index 15179954adc..f0dea66f612 100644
--- a/tests/ui/span/issue-34264.stderr
+++ b/tests/ui/span/issue-34264.stderr
@@ -54,17 +54,16 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:7:5
    |
 LL |     foo(Some(42), 2, "");
-   |     ^^^              -- argument of type `&'static str` unexpected
+   |     ^^^            ----
+   |                    | |
+   |                    | unexpected argument of type `&'static str`
+   |                    help: remove the extra argument
    |
 note: function defined here
   --> $DIR/issue-34264.rs:1:4
    |
 LL | fn foo(Option<i32>, String) {}
    |    ^^^ -----------  ------
-help: remove the extra argument
-   |
-LL |     foo(Some(42), 2);
-   |        ~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-34264.rs:8:13
@@ -84,17 +83,16 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:10:5
    |
 LL |     bar(1, 2, 3);
-   |     ^^^       - argument of type `{integer}` unexpected
+   |     ^^^     ---
+   |             | |
+   |             | unexpected argument of type `{integer}`
+   |             help: remove the extra argument
    |
 note: function defined here
   --> $DIR/issue-34264.rs:3:4
    |
 LL | fn bar(x, y: usize) {}
    |    ^^^ -  --------
-help: remove the extra argument
-   |
-LL |     bar(1, 2);
-   |        ~~~~~~
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
index e9736363816..510b99bb5af 100644
--- a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
+++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
@@ -2,7 +2,7 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:6:34
    |
 LL |     let _: Option<(i32, bool)> = Some(1, 2);
-   |                                  ^^^^    - argument of type `{integer}` unexpected
+   |                                  ^^^^    - unexpected argument of type `{integer}`
    |
 note: expected `(i32, bool)`, found integer
   --> $DIR/args-instead-of-tuple-errors.rs:6:39
@@ -22,14 +22,15 @@ note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: remove the extra argument
    |
-LL |     let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
-   |                                      ~~~~~~~~~~~~~~~~~~~
+LL -     let _: Option<(i32, bool)> = Some(1, 2);
+LL +     let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
+   |
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:8:5
    |
 LL |     int_bool(1, 2);
-   |     ^^^^^^^^    - argument of type `{integer}` unexpected
+   |     ^^^^^^^^    - unexpected argument of type `{integer}`
    |
 note: expected `(i32, bool)`, found integer
   --> $DIR/args-instead-of-tuple-errors.rs:8:14
@@ -45,8 +46,9 @@ LL | fn int_bool(_: (i32, bool)) {
    |    ^^^^^^^^ --------------
 help: remove the extra argument
    |
-LL |     int_bool(/* (i32, bool) */);
-   |             ~~~~~~~~~~~~~~~~~~~
+LL -     int_bool(1, 2);
+LL +     int_bool(/* (i32, bool) */);
+   |
 
 error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:11:28
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
new file mode 100644
index 00000000000..d254c0ae3ef
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
@@ -0,0 +1,11 @@
+// Regression test for #108072: do not ICE upon unmet trait alias constraint
+
+#![feature(trait_alias)]
+
+trait IteratorAlias = Iterator;
+
+fn f(_: impl IteratorAlias) {}
+
+fn main() {
+    f(()) //~ `()` is not an iterator
+}
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
new file mode 100644
index 00000000000..39f974f962c
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
@@ -0,0 +1,19 @@
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-108072-unmet-trait-alias-bound.rs:10:7
+   |
+LL |     f(())
+   |     - ^^ `()` is not an iterator
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+   = note: required for `()` to implement `IteratorAlias`
+note: required by a bound in `f`
+  --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14
+   |
+LL | fn f(_: impl IteratorAlias) {}
+   |              ^^^^^^^^^^^^^ required by this bound in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/basic.rs b/tests/ui/traits/non_lifetime_binders/basic.rs
new file mode 100644
index 00000000000..a797aae65db
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/basic.rs
@@ -0,0 +1,19 @@
+// check-pass
+// Basic test that show's we can succesfully typeck a `for<T>` where clause.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait {}
+
+impl<T: ?Sized> Trait for T {}
+
+fn foo()
+where
+    for<T> T: Trait,
+{
+}
+
+fn main() {
+    foo();
+}
diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr
new file mode 100644
index 00000000000..fddc5d9fc25
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/basic.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/basic.rs:4:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/fail.rs b/tests/ui/traits/non_lifetime_binders/fail.rs
new file mode 100644
index 00000000000..460f68907e8
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/fail.rs
@@ -0,0 +1,23 @@
+// Error reporting for where `for<T> T: Trait` doesn't hold
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait {}
+
+fn fail()
+where
+    for<T> T: Trait,
+{}
+
+fn auto_trait()
+where
+    for<T> T: Send,
+{}
+
+fn main() {
+    fail();
+    //~^ ERROR the trait bound `T: Trait` is not satisfied
+    auto_trait();
+    //~^ ERROR `T` cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr
new file mode 100644
index 00000000000..ba5953193a4
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/fail.stderr
@@ -0,0 +1,43 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/fail.rs:3:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/fail.rs:19:5
+   |
+LL |     fail();
+   |     ^^^^ the trait `Trait` is not implemented for `T`
+   |
+note: required by a bound in `fail`
+  --> $DIR/fail.rs:10:15
+   |
+LL | fn fail()
+   |    ---- required by a bound in this
+LL | where
+LL |     for<T> T: Trait,
+   |               ^^^^^ required by this bound in `fail`
+
+error[E0277]: `T` cannot be sent between threads safely
+  --> $DIR/fail.rs:21:5
+   |
+LL |     auto_trait();
+   |     ^^^^^^^^^^ `T` cannot be sent between threads safely
+   |
+   = help: the trait `Send` is not implemented for `T`
+note: required by a bound in `auto_trait`
+  --> $DIR/fail.rs:15:15
+   |
+LL | fn auto_trait()
+   |    ---------- required by a bound in this
+LL | where
+LL |     for<T> T: Send,
+   |               ^^^^ required by this bound in `auto_trait`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.rs b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
new file mode 100644
index 00000000000..8fb7dd27605
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
@@ -0,0 +1,13 @@
+// Tests to make sure that we reject polymorphic dyn trait.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Test<T> {}
+
+fn foo() -> &'static dyn for<T> Test<T> {
+    //~^ ERROR late-bound type parameter not allowed on trait object types
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
new file mode 100644
index 00000000000..44071107de4
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/on-dyn.rs:3:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on trait object types
+  --> $DIR/on-dyn.rs:8:30
+   |
+LL | fn foo() -> &'static dyn for<T> Test<T> {
+   |                              ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.rs b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
new file mode 100644
index 00000000000..0aaff52b6d8
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
@@ -0,0 +1,13 @@
+// Tests to make sure that we reject polymorphic fn ptrs.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn foo() -> for<T> fn(T) {
+    //~^ ERROR late-bound type parameter not allowed on function pointer types
+    todo!()
+}
+
+fn main() {
+    foo()(1i32);
+}
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
new file mode 100644
index 00000000000..bb7dccaf07d
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/on-ptr.rs:3:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on function pointer types
+  --> $DIR/on-ptr.rs:6:17
+   |
+LL | fn foo() -> for<T> fn(T) {
+   |                 ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/tuple/wrong_argument_ice-3.stderr b/tests/ui/tuple/wrong_argument_ice-3.stderr
index 75dfe716395..7143c959478 100644
--- a/tests/ui/tuple/wrong_argument_ice-3.stderr
+++ b/tests/ui/tuple/wrong_argument_ice-3.stderr
@@ -2,7 +2,7 @@ error[E0061]: this method takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice-3.rs:9:16
    |
 LL |         groups.push(new_group, vec![process]);
-   |                ^^^^            ------------- argument of type `Vec<&Process>` unexpected
+   |                ^^^^            ------------- unexpected argument of type `Vec<&Process>`
    |
 note: expected `(Vec<String>, Vec<Process>)`, found `Vec<String>`
   --> $DIR/wrong_argument_ice-3.rs:9:21
@@ -15,8 +15,9 @@ note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: remove the extra argument
    |
-LL |         groups.push(/* (Vec<String>, Vec<Process>) */);
-   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL -         groups.push(new_group, vec![process]);
+LL +         groups.push(/* (Vec<String>, Vec<Process>) */);
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/tuple/wrong_argument_ice-4.stderr b/tests/ui/tuple/wrong_argument_ice-4.stderr
index a2686ab9440..d8569ebf6b6 100644
--- a/tests/ui/tuple/wrong_argument_ice-4.stderr
+++ b/tests/ui/tuple/wrong_argument_ice-4.stderr
@@ -6,17 +6,16 @@ LL |       (|| {})(|| {
 LL | |
 LL | |         let b = 1;
 LL | |     });
-   | |_____- argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]` unexpected
+   | |     -
+   | |     |
+   | |_____unexpected argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]`
+   |       help: remove the extra argument
    |
 note: closure defined here
   --> $DIR/wrong_argument_ice-4.rs:2:6
    |
 LL |     (|| {})(|| {
    |      ^^
-help: remove the extra argument
-   |
-LL |     (|| {})();
-   |            ~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type/type-ascription-instead-of-initializer.stderr b/tests/ui/type/type-ascription-instead-of-initializer.stderr
index ba8d15d0b73..429501c2762 100644
--- a/tests/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/tests/ui/type/type-ascription-instead-of-initializer.stderr
@@ -11,14 +11,13 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/type-ascription-instead-of-initializer.rs:2:12
    |
 LL |     let x: Vec::with_capacity(10, 20);
-   |            ^^^^^^^^^^^^^^^^^^     -- argument of type `{integer}` unexpected
+   |            ^^^^^^^^^^^^^^^^^^   ----
+   |                                 | |
+   |                                 | unexpected argument of type `{integer}`
+   |                                 help: remove the extra argument
    |
 note: associated function defined here
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-help: remove the extra argument
-   |
-LL |     let x: Vec::with_capacity(10);
-   |                              ~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-53712.rs b/tests/ui/typeck/issue-53712.rs
index 2353904d79d..2353904d79d 100644
--- a/tests/ui/issues/issue-53712.rs
+++ b/tests/ui/typeck/issue-53712.rs
diff --git a/tests/ui/issues/issue-53712.stderr b/tests/ui/typeck/issue-53712.stderr
index db85919afcb..db85919afcb 100644
--- a/tests/ui/issues/issue-53712.stderr
+++ b/tests/ui/typeck/issue-53712.stderr
diff --git a/tests/ui/issues/issue-7813.rs b/tests/ui/typeck/issue-7813.rs
index ce549bde601..ce549bde601 100644
--- a/tests/ui/issues/issue-7813.rs
+++ b/tests/ui/typeck/issue-7813.rs
diff --git a/tests/ui/issues/issue-7813.stderr b/tests/ui/typeck/issue-7813.stderr
index 2a747f679a8..2a747f679a8 100644
--- a/tests/ui/issues/issue-7813.stderr
+++ b/tests/ui/typeck/issue-7813.stderr
diff --git a/tests/ui/typeck/remove-extra-argument.stderr b/tests/ui/typeck/remove-extra-argument.stderr
index b734bcd4eb0..72ddebab486 100644
--- a/tests/ui/typeck/remove-extra-argument.stderr
+++ b/tests/ui/typeck/remove-extra-argument.stderr
@@ -2,17 +2,16 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/remove-extra-argument.rs:6:5
    |
 LL |     l(vec![], vec![])
-   |     ^         ------ argument of type `Vec<_>` unexpected
+   |     ^       --------
+   |             | |
+   |             | unexpected argument of type `Vec<_>`
+   |             help: remove the extra argument
    |
 note: function defined here
   --> $DIR/remove-extra-argument.rs:3:4
    |
 LL | fn l(_a: Vec<u8>) {}
    |    ^ -----------
-help: remove the extra argument
-   |
-LL |     l(vec![])
-   |      ~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/typeck/struct-enum-wrong-args.stderr b/tests/ui/typeck/struct-enum-wrong-args.stderr
index fbced928a8a..57cbd1d2005 100644
--- a/tests/ui/typeck/struct-enum-wrong-args.stderr
+++ b/tests/ui/typeck/struct-enum-wrong-args.stderr
@@ -2,29 +2,29 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:6:13
    |
 LL |     let _ = Some(3, 2);
-   |             ^^^^    - argument of type `{integer}` unexpected
+   |             ^^^^  ---
+   |                   | |
+   |                   | unexpected argument of type `{integer}`
+   |                   help: remove the extra argument
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
-help: remove the extra argument
-   |
-LL |     let _ = Some(3);
-   |                 ~~~
 
 error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:7:13
    |
 LL |     let _ = Ok(3, 6, 2);
-   |             ^^    -  - argument of type `{integer}` unexpected
+   |             ^^    -  - unexpected argument of type `{integer}`
    |                   |
-   |                   argument of type `{integer}` unexpected
+   |                   unexpected argument of type `{integer}`
    |
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
 help: remove the extra arguments
    |
-LL |     let _ = Ok(3);
-   |               ~~~
+LL -     let _ = Ok(3, 6, 2);
+LL +     let _ = Ok(3);
+   |
 
 error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:8:13
@@ -59,17 +59,16 @@ error[E0061]: this struct takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:10:13
    |
 LL |     let _ = Wrapper(5, 2);
-   |             ^^^^^^^    - argument of type `{integer}` unexpected
+   |             ^^^^^^^  ---
+   |                      | |
+   |                      | unexpected argument of type `{integer}`
+   |                      help: remove the extra argument
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:2:8
    |
 LL | struct Wrapper(i32);
    |        ^^^^^^^
-help: remove the extra argument
-   |
-LL |     let _ = Wrapper(5);
-   |                    ~~~
 
 error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:11:13
@@ -107,17 +106,16 @@ error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:13:13
    |
 LL |     let _ = DoubleWrapper(5, 2, 7);
-   |             ^^^^^^^^^^^^^       - argument of type `{integer}` unexpected
+   |             ^^^^^^^^^^^^^     ---
+   |                               | |
+   |                               | unexpected argument of type `{integer}`
+   |                               help: remove the extra argument
    |
 note: tuple struct defined here
   --> $DIR/struct-enum-wrong-args.rs:3:8
    |
 LL | struct DoubleWrapper(i32, i32);
    |        ^^^^^^^^^^^^^
-help: remove the extra argument
-   |
-LL |     let _ = DoubleWrapper(5, 2);
-   |                          ~~~~~~
 
 error: aborting due to 8 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index 883bc8720e2..8a9d9403366 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -630,7 +630,7 @@ style-team = [
 "/src/stage0.json" =                         ["bootstrap"]
 "/tests/ui" =                                ["compiler"]
 "/src/tools/cargo" =                         ["@ehuss", "@joshtriplett"]
-"/src/tools/compiletest" =                   ["bootstrap"]
+"/src/tools/compiletest" =                   ["bootstrap", "@wesleywiser", "@oli-obk"]
 "/src/tools/linkchecker" =                   ["@ehuss"]
 "/src/tools/rust-installer" =                ["bootstrap"]
 "/src/tools/rustbook" =                      ["@ehuss"]