about summary refs log tree commit diff
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/arena.rs7
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs27
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs1
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs4
-rw-r--r--compiler/rustc_middle/src/lib.rs47
-rw-r--r--compiler/rustc_middle/src/lint.rs11
-rw-r--r--compiler/rustc_middle/src/middle/region.rs1
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs185
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs43
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs6
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs22
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs1
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs1
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs1
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs11
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs46
-rw-r--r--compiler/rustc_middle/src/query/erase.rs16
-rw-r--r--compiler/rustc_middle/src/query/mod.rs54
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs44
-rw-r--r--compiler/rustc_middle/src/thir.rs1
-rw-r--r--compiler/rustc_middle/src/traits/solve/cache.rs6
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs1
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs3
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs3
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs58
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs15
-rw-r--r--compiler/rustc_middle/src/ty/context.rs78
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs1
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs105
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs503
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs33
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs1
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs1
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs7
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs14
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs5
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs1
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs4
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs196
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs33
-rw-r--r--compiler/rustc_middle/src/ty/region.rs72
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs1
-rw-r--r--compiler/rustc_middle/src/ty/rvalue_scopes.rs1
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs32
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs315
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs12
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs5
-rw-r--r--compiler/rustc_middle/src/ty/util.rs5
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs98
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs12
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs1
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs1
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs1
-rw-r--r--compiler/rustc_middle/src/values.rs6
62 files changed, 605 insertions, 1572 deletions
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 7392eb6c2bb..bf6ab800064 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -61,7 +61,10 @@ macro_rules! arena_types {
             [] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>,
             [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>,
             [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>,
-            [] canonical_goal_evaluation: rustc_next_trait_solver::solve::inspect::GoalEvaluationStep<rustc_middle::ty::TyCtxt<'tcx>>,
+            [] canonical_goal_evaluation:
+                rustc_next_trait_solver::solve::inspect::CanonicalGoalEvaluationStep<
+                    rustc_middle::ty::TyCtxt<'tcx>
+                >,
             [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>,
             [] type_op_subtype:
                 rustc_middle::infer::canonical::Canonical<'tcx,
@@ -105,7 +108,7 @@ macro_rules! arena_types {
             [decode] trait_impl_trait_tys:
                 rustc_data_structures::unord::UnordMap<
                     rustc_hir::def_id::DefId,
-                    rustc_middle::ty::EarlyBinder<rustc_middle::ty::Ty<'tcx>>
+                    rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>>
                 >,
             [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
             [] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index f3f24f77177..ff8d2919705 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -321,7 +321,7 @@ impl<'hir> Map<'hir> {
 
     /// Returns an iterator of the `DefId`s for all body-owners in this
     /// crate. If you would prefer to iterate over the bodies
-    /// themselves, you can do `self.hir().krate().body_ids.iter()`.
+    /// themselves, you can do `self.hir().krate().owners.iter()`.
     #[inline]
     pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
         self.tcx.hir_crate_items(()).body_owners.iter().copied()
@@ -508,7 +508,17 @@ impl<'hir> Map<'hir> {
     /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
     /// Used exclusively for diagnostics, to avoid suggestion function calls.
     pub fn is_inside_const_context(self, hir_id: HirId) -> bool {
-        self.body_const_context(self.enclosing_body_owner(hir_id)).is_some()
+        for (_, node) in self.parent_iter(hir_id) {
+            if let Some((def_id, _)) = node.associated_body() {
+                return self.body_const_context(def_id).is_some();
+            }
+            if let Node::Expr(e) = node {
+                if let ExprKind::ConstBlock(_) = e.kind {
+                    return true;
+                }
+            }
+        }
+        false
     }
 
     /// Retrieves the `HirId` for `id`'s enclosing function *if* the `id` block or return is
@@ -891,7 +901,6 @@ impl<'hir> Map<'hir> {
             Node::Variant(variant) => variant.span,
             Node::Field(field) => field.span,
             Node::AnonConst(constant) => constant.span,
-            Node::ConstBlock(constant) => self.body(constant.body).value.span,
             Node::Expr(expr) => expr.span,
             Node::ExprField(field) => field.span,
             Node::Stmt(stmt) => stmt.span,
@@ -1016,7 +1025,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
     let krate = tcx.hir_crate(());
     let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash");
 
-    let upstream_crates = upstream_crates(tcx);
+    let upstream_crates = upstream_crates_for_hashing(tcx);
 
     let resolutions = tcx.resolutions(());
 
@@ -1085,9 +1094,9 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
     Svh::new(crate_hash)
 }
 
-fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
+fn upstream_crates_for_hashing(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
     let mut upstream_crates: Vec<_> = tcx
-        .crates(())
+        .crates_including_speculative(())
         .iter()
         .map(|&cnum| {
             let stable_crate_id = tcx.stable_crate_id(cnum);
@@ -1161,7 +1170,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
             format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
         }
         Node::AnonConst(_) => node_str("const"),
-        Node::ConstBlock(_) => node_str("const"),
         Node::Expr(_) => node_str("expr"),
         Node::ExprField(_) => node_str("expr field"),
         Node::Stmt(_) => node_str("stmt"),
@@ -1311,11 +1319,6 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
         intravisit::walk_anon_const(self, c)
     }
 
-    fn visit_inline_const(&mut self, c: &'hir ConstBlock) {
-        self.body_owners.push(c.def_id);
-        intravisit::walk_inline_const(self, c)
-    }
-
     fn visit_expr(&mut self, ex: &'hir Expr<'hir>) {
         if let ExprKind::Closure(closure) = ex.kind {
             self.body_owners.push(closure.def_id);
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 34748afa863..d39422b2b04 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -121,7 +121,7 @@ impl<'tcx> TyCtxt<'tcx> {
         LocalModDefId::new_unchecked(id)
     }
 
-    pub fn impl_subject(self, def_id: DefId) -> EarlyBinder<ImplSubject<'tcx>> {
+    pub fn impl_subject(self, def_id: DefId) -> EarlyBinder<'tcx, ImplSubject<'tcx>> {
         match self.impl_trait_ref(def_id) {
             Some(t) => t.map_bound(ImplSubject::Trait),
             None => self.type_of(def_id).map_bound(ImplSubject::Inherent),
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index d35b9fc46e4..bf10a71dbae 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -10,6 +10,7 @@ use rustc_hir::def_id::{DefId, DefPathHash};
 use rustc_session::StableCrateId;
 use rustc_span::def_id::{CrateNum, LocalDefId};
 use rustc_span::{ExpnHash, ExpnId, DUMMY_SP};
+use tracing::instrument;
 
 macro_rules! declare_hooks {
     ($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 49bf03e9c75..dba71d88f40 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -32,7 +32,7 @@ use std::collections::hash_map::Entry;
 use crate::infer::MemberConstraint;
 use crate::mir::ConstraintCategory;
 use crate::ty::GenericArg;
-use crate::ty::{self, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
+use crate::ty::{self, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
 
 pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>;
 pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo<TyCtxt<'tcx>>;
@@ -141,7 +141,7 @@ impl<'tcx, R> QueryResponse<'tcx, R> {
 }
 
 pub type QueryOutlivesConstraint<'tcx> =
-    (ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
+    (ty::OutlivesPredicate<'tcx, GenericArg<'tcx>>, ConstraintCategory<'tcx>);
 
 TrivialTypeTraversalImpls! {
     crate::infer::canonical::Certainty,
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 04fd4c8d0f7..d47e393c912 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -22,49 +22,46 @@
 //!
 //! This API is completely unstable and subject to change.
 
+// tidy-alphabetical-start
+#![allow(internal_features)]
+#![allow(rustc::diagnostic_outside_of_impl)]
+#![allow(rustc::potential_query_instability)]
+#![allow(rustc::untranslatable_diagnostic)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
-#![feature(min_exhaustive_patterns)]
-#![feature(rustdoc_internals)]
 #![feature(allocator_api)]
 #![feature(array_windows)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(closure_track_caller)]
-#![feature(core_intrinsics)]
+#![feature(const_option)]
 #![feature(const_type_name)]
-#![feature(discriminant_kind)]
+#![feature(core_intrinsics)]
 #![feature(coroutines)]
-#![feature(stmt_expr_attributes)]
+#![feature(decl_macro)]
+#![feature(discriminant_kind)]
+#![feature(extern_types)]
+#![feature(extract_if)]
 #![feature(if_let_guard)]
+#![feature(intra_doc_pointers)]
 #![feature(iter_from_coroutine)]
+#![feature(let_chains)]
+#![feature(macro_metavar_expr)]
+#![feature(min_exhaustive_patterns)]
+#![feature(min_specialization)]
 #![feature(negative_impls)]
 #![feature(never_type)]
-#![feature(extern_types)]
 #![feature(new_uninit)]
-#![feature(let_chains)]
-#![feature(min_specialization)]
-#![feature(trusted_len)]
-#![feature(type_alias_impl_trait)]
-#![feature(strict_provenance)]
+#![feature(ptr_alignment_type)]
 #![feature(rustc_attrs)]
-#![feature(control_flow_enum)]
+#![feature(rustdoc_internals)]
+#![feature(strict_provenance)]
 #![feature(trait_upcasting)]
+#![feature(trusted_len)]
 #![feature(try_blocks)]
-#![feature(decl_macro)]
-#![feature(extract_if)]
-#![feature(intra_doc_pointers)]
+#![feature(type_alias_impl_trait)]
 #![feature(yeet_expr)]
-#![feature(const_option)]
-#![feature(ptr_alignment_type)]
-#![feature(macro_metavar_expr)]
-#![allow(internal_features)]
-#![allow(rustc::potential_query_instability)]
-#![allow(rustc::diagnostic_outside_of_impl)]
-#![allow(rustc::untranslatable_diagnostic)]
-
-#[macro_use]
-extern crate tracing;
+// tidy-alphabetical-end
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 086582e60a3..4e655ca2027 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -2,7 +2,7 @@ use std::cmp;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sorted_map::SortedMap;
-use rustc_errors::{Diag, DiagMessage, MultiSpan};
+use rustc_errors::{Diag, MultiSpan};
 use rustc_hir::{HirId, ItemLocalId};
 use rustc_macros::HashStable;
 use rustc_session::lint::{
@@ -12,6 +12,7 @@ use rustc_session::lint::{
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::{symbol, DesugaringKind, Span, Symbol, DUMMY_SP};
+use tracing::instrument;
 
 use crate::ty::TyCtxt;
 
@@ -269,7 +270,6 @@ pub fn lint_level(
     level: Level,
     src: LintLevelSource,
     span: Option<MultiSpan>,
-    msg: impl Into<DiagMessage>,
     decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
 ) {
     // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
@@ -281,7 +281,6 @@ pub fn lint_level(
         level: Level,
         src: LintLevelSource,
         span: Option<MultiSpan>,
-        msg: impl Into<DiagMessage>,
         decorate: Box<dyn '_ + for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>)>,
     ) {
         // Check for future incompatibility lints and issue a stronger warning.
@@ -350,10 +349,6 @@ pub fn lint_level(
             }
         }
 
-        // Delay evaluating and setting the primary message until after we've
-        // suppressed the lint due to macros.
-        err.primary_message(msg);
-
         err.is_lint(lint.name_lower(), has_future_breakage);
 
         // Lint diagnostics that are covered by the expect level will not be emitted outside
@@ -418,7 +413,7 @@ pub fn lint_level(
         explain_lint_level_source(lint, level, src, &mut err);
         err.emit()
     }
-    lint_level_impl(sess, lint, level, src, span, msg, Box::new(decorate))
+    lint_level_impl(sess, lint, level, src, span, Box::new(decorate))
 }
 
 /// Returns whether `span` originates in a foreign crate's external macro.
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index de07ba9700a..6e89dc494fa 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -13,6 +13,7 @@ use rustc_hir as hir;
 use rustc_hir::{HirId, HirIdMap, Node};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::{Span, DUMMY_SP};
+use tracing::debug;
 
 use std::fmt;
 use std::ops::Deref;
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 67bd53f53da..8cf1bedf0da 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -9,20 +9,21 @@ use rustc_attr::{
     self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
 };
 use rustc_data_structures::unord::UnordMap;
-use rustc_errors::{Applicability, Diag};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee};
 use rustc_feature::GateIssue;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
 use rustc_hir::{self as hir, HirId};
-use rustc_macros::{Decodable, Encodable, HashStable};
+use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
-use rustc_session::lint::{BuiltinLintDiag, Level, Lint, LintBuffer};
+use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer};
 use rustc_session::parse::feature_err_issue;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use std::num::NonZero;
+use tracing::debug;
 
 #[derive(PartialEq, Clone, Copy, Debug)]
 pub enum StabilityLevel {
@@ -125,90 +126,104 @@ pub fn report_unstable(
     }
 }
 
-pub fn deprecation_suggestion(
-    diag: &mut Diag<'_, ()>,
-    kind: &str,
-    suggestion: Option<Symbol>,
-    span: Span,
-) {
-    if let Some(suggestion) = suggestion {
-        diag.span_suggestion_verbose(
-            span,
-            format!("replace the use of the deprecated {kind}"),
-            suggestion,
-            Applicability::MachineApplicable,
-        );
-    }
-}
-
 fn deprecation_lint(is_in_effect: bool) -> &'static Lint {
     if is_in_effect { DEPRECATED } else { DEPRECATED_IN_FUTURE }
 }
 
-fn deprecation_message(
-    is_in_effect: bool,
-    since: DeprecatedSince,
-    note: Option<Symbol>,
-    kind: &str,
-    path: &str,
-) -> String {
-    let message = if is_in_effect {
-        format!("use of deprecated {kind} `{path}`")
+#[derive(Subdiagnostic)]
+#[suggestion(
+    middle_deprecated_suggestion,
+    code = "{suggestion}",
+    style = "verbose",
+    applicability = "machine-applicable"
+)]
+pub struct DeprecationSuggestion {
+    #[primary_span]
+    pub span: Span,
+
+    pub kind: String,
+    pub suggestion: Symbol,
+}
+
+pub struct Deprecated {
+    pub sub: Option<DeprecationSuggestion>,
+
+    // FIXME: make this translatable
+    pub kind: String,
+    pub path: String,
+    pub note: Option<Symbol>,
+    pub since_kind: DeprecatedSinceKind,
+}
+
+impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated {
+    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
+        diag.primary_message(match &self.since_kind {
+            DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated,
+            DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future,
+            DeprecatedSinceKind::InVersion(_) => {
+                crate::fluent_generated::middle_deprecated_in_version
+            }
+        });
+        diag.arg("kind", self.kind);
+        diag.arg("path", self.path);
+        if let DeprecatedSinceKind::InVersion(version) = self.since_kind {
+            diag.arg("version", version);
+        }
+        if let Some(note) = self.note {
+            diag.arg("has_note", true);
+            diag.arg("note", note);
+        } else {
+            diag.arg("has_note", false);
+        }
+        if let Some(sub) = self.sub {
+            diag.subdiagnostic(diag.dcx, sub);
+        }
+    }
+}
+
+fn deprecated_since_kind(is_in_effect: bool, since: DeprecatedSince) -> DeprecatedSinceKind {
+    if is_in_effect {
+        DeprecatedSinceKind::InEffect
     } else {
         match since {
-            DeprecatedSince::RustcVersion(version) => format!(
-                "use of {kind} `{path}` that will be deprecated in future version {version}"
-            ),
-            DeprecatedSince::Future => {
-                format!("use of {kind} `{path}` that will be deprecated in a future Rust version")
+            DeprecatedSince::RustcVersion(version) => {
+                DeprecatedSinceKind::InVersion(version.to_string())
             }
+            DeprecatedSince::Future => DeprecatedSinceKind::InFuture,
             DeprecatedSince::NonStandard(_)
             | DeprecatedSince::Unspecified
             | DeprecatedSince::Err => {
                 unreachable!("this deprecation is always in effect; {since:?}")
             }
         }
-    };
-
-    match note {
-        Some(reason) => format!("{message}: {reason}"),
-        None => message,
     }
 }
 
-pub fn deprecation_message_and_lint(
-    depr: &Deprecation,
-    kind: &str,
-    path: &str,
-) -> (String, &'static Lint) {
-    let is_in_effect = depr.is_in_effect();
-    (
-        deprecation_message(is_in_effect, depr.since, depr.note, kind, path),
-        deprecation_lint(is_in_effect),
-    )
-}
-
-pub fn early_report_deprecation(
+pub fn early_report_macro_deprecation(
     lint_buffer: &mut LintBuffer,
-    message: String,
-    suggestion: Option<Symbol>,
-    lint: &'static Lint,
+    depr: &Deprecation,
     span: Span,
     node_id: NodeId,
+    path: String,
 ) {
     if span.in_derive_expansion() {
         return;
     }
 
-    let diag = BuiltinLintDiag::DeprecatedMacro(suggestion, span);
-    lint_buffer.buffer_lint_with_diagnostic(lint, node_id, span, message, diag);
+    let is_in_effect = depr.is_in_effect();
+    let diag = BuiltinLintDiag::DeprecatedMacro {
+        suggestion: depr.suggestion,
+        suggestion_span: span,
+        note: depr.note,
+        path,
+        since_kind: deprecated_since_kind(is_in_effect, depr.since.clone()),
+    };
+    lint_buffer.buffer_lint(deprecation_lint(is_in_effect), node_id, span, diag);
 }
 
 fn late_report_deprecation(
     tcx: TyCtxt<'_>,
-    message: String,
-    suggestion: Option<Symbol>,
-    lint: &'static Lint,
+    depr: &Deprecation,
     span: Span,
     method_span: Option<Span>,
     hir_id: HirId,
@@ -217,13 +232,26 @@ fn late_report_deprecation(
     if span.in_derive_expansion() {
         return;
     }
+
+    let def_path = with_no_trimmed_paths!(tcx.def_path_str(def_id));
+    let def_kind = tcx.def_descr(def_id);
+    let is_in_effect = depr.is_in_effect();
+
     let method_span = method_span.unwrap_or(span);
-    tcx.node_span_lint(lint, hir_id, method_span, message, |diag| {
-        if let hir::Node::Expr(_) = tcx.hir_node(hir_id) {
-            let kind = tcx.def_descr(def_id);
-            deprecation_suggestion(diag, kind, suggestion, method_span);
-        }
-    });
+    let suggestion =
+        if let hir::Node::Expr(_) = tcx.hir_node(hir_id) { depr.suggestion } else { None };
+    let diag = Deprecated {
+        sub: suggestion.map(|suggestion| DeprecationSuggestion {
+            span: method_span,
+            kind: def_kind.to_owned(),
+            suggestion,
+        }),
+        kind: def_kind.to_owned(),
+        path: def_path,
+        note: depr.note,
+        since_kind: deprecated_since_kind(is_in_effect, depr.since),
+    };
+    tcx.emit_node_span_lint(deprecation_lint(is_in_effect), hir_id, method_span, diag);
 }
 
 /// Result of `TyCtxt::eval_stability`.
@@ -352,28 +380,9 @@ impl<'tcx> TyCtxt<'tcx> {
                     // Calculating message for lint involves calling `self.def_path_str`.
                     // Which by default to calculate visible path will invoke expensive `visible_parent_map` query.
                     // So we skip message calculation altogether, if lint is allowed.
-                    let is_in_effect = depr_attr.is_in_effect();
-                    let lint = deprecation_lint(is_in_effect);
+                    let lint = deprecation_lint(depr_attr.is_in_effect());
                     if self.lint_level_at_node(lint, id).0 != Level::Allow {
-                        let def_path = with_no_trimmed_paths!(self.def_path_str(def_id));
-                        let def_kind = self.def_descr(def_id);
-
-                        late_report_deprecation(
-                            self,
-                            deprecation_message(
-                                is_in_effect,
-                                depr_attr.since,
-                                depr_attr.note,
-                                def_kind,
-                                &def_path,
-                            ),
-                            depr_attr.suggestion,
-                            lint,
-                            span,
-                            method_span,
-                            id,
-                            def_id,
-                        );
+                        late_report_deprecation(self, depr_attr, span, method_span, id, def_id);
                     }
                 }
             };
@@ -586,7 +595,9 @@ impl<'tcx> TyCtxt<'tcx> {
         unmarked: impl FnOnce(Span, DefId),
     ) -> bool {
         let soft_handler = |lint, span, msg: String| {
-            self.node_span_lint(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |_| {})
+            self.node_span_lint(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
+                lint.primary_message(msg);
+            })
         };
         let eval_result =
             self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index d025dc360a2..e107c2c12bd 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -220,7 +220,10 @@ pub enum Const<'tcx> {
 }
 
 impl<'tcx> Const<'tcx> {
-    pub fn identity_unevaluated(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::EarlyBinder<Const<'tcx>> {
+    pub fn identity_unevaluated(
+        tcx: TyCtxt<'tcx>,
+        def_id: DefId,
+    ) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
         ty::EarlyBinder::bind(Const::Unevaluated(
             UnevaluatedConst {
                 def: def_id,
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 791e87735f4..b0f8a047b82 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -266,19 +266,6 @@ impl AllocRange {
 
 // The constructors are all without extra; the extra gets added by a machine hook later.
 impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
-    /// Creates an allocation from an existing `Bytes` value - this is needed for miri FFI support
-    pub fn from_raw_bytes(bytes: Bytes, align: Align, mutability: Mutability) -> Self {
-        let size = Size::from_bytes(bytes.len());
-        Self {
-            bytes,
-            provenance: ProvenanceMap::new(),
-            init_mask: InitMask::new(size, true),
-            align,
-            mutability,
-            extra: (),
-        }
-    }
-
     /// Creates an allocation initialized by the given bytes
     pub fn from_bytes<'a>(
         slice: impl Into<Cow<'a, [u8]>>,
@@ -342,18 +329,30 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
             Err(x) => x,
         }
     }
+
+    /// Add the extra.
+    pub fn with_extra<Extra>(self, extra: Extra) -> Allocation<Prov, Extra, Bytes> {
+        Allocation {
+            bytes: self.bytes,
+            provenance: self.provenance,
+            init_mask: self.init_mask,
+            align: self.align,
+            mutability: self.mutability,
+            extra,
+        }
+    }
 }
 
 impl Allocation {
     /// Adjust allocation from the ones in `tcx` to a custom Machine instance
-    /// with a different `Provenance`, `Extra` and `Byte` type.
-    pub fn adjust_from_tcx<Prov: Provenance, Extra, Bytes: AllocBytes, Err>(
-        self,
+    /// with a different `Provenance` and `Byte` type.
+    pub fn adjust_from_tcx<Prov: Provenance, Bytes: AllocBytes, Err>(
+        &self,
         cx: &impl HasDataLayout,
-        extra: Extra,
         mut adjust_ptr: impl FnMut(Pointer<CtfeProvenance>) -> Result<Pointer<Prov>, Err>,
-    ) -> Result<Allocation<Prov, Extra, Bytes>, Err> {
-        let mut bytes = self.bytes;
+    ) -> Result<Allocation<Prov, (), Bytes>, Err> {
+        // Copy the data.
+        let mut bytes = Bytes::from_bytes(Cow::Borrowed(&*self.bytes), self.align);
         // Adjust provenance of pointers stored in this allocation.
         let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len());
         let ptr_size = cx.data_layout().pointer_size.bytes_usize();
@@ -369,12 +368,12 @@ impl Allocation {
         }
         // Create allocation.
         Ok(Allocation {
-            bytes: AllocBytes::from_bytes(Cow::Owned(Vec::from(bytes)), self.align),
+            bytes,
             provenance: ProvenanceMap::from_presorted_ptrs(new_provenance),
-            init_mask: self.init_mask,
+            init_mask: self.init_mask.clone(),
             align: self.align,
             mutability: self.mutability,
-            extra,
+            extra: self.extra,
         })
     }
 }
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index e974279f191..4e37295a571 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -3,12 +3,12 @@
 
 use std::cmp;
 
+use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance};
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_macros::HashStable;
-use rustc_target::abi::{HasDataLayout, Size};
-
-use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use rustc_target::abi::{HasDataLayout, Size};
+use tracing::trace;
 
 /// Stores the provenance information of pointers stored in memory.
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 6e152cbcb65..eabbcc2033f 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -1,19 +1,22 @@
-use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
+use std::borrow::Cow;
+use std::{any::Any, backtrace::Backtrace, fmt};
 
-use crate::error;
-use crate::mir::{ConstAlloc, ConstValue};
-use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree};
+use either::Either;
 
 use rustc_ast_ir::Mutability;
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_session::CtfeBacktrace;
+use rustc_span::Symbol;
 use rustc_span::{def_id::DefId, Span, DUMMY_SP};
 use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange};
 
-use std::borrow::Cow;
-use std::{any::Any, backtrace::Backtrace, fmt};
+use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
+
+use crate::error;
+use crate::mir::{ConstAlloc, ConstValue};
+use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 pub enum ErrorHandled {
@@ -63,6 +66,9 @@ impl ReportedErrorInfo {
     pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
         ReportedErrorInfo { is_tainted_by_errors: true, error }
     }
+    pub fn is_tainted_by_errors(&self) -> bool {
+        self.is_tainted_by_errors
+    }
 }
 
 impl From<ErrorGuaranteed> for ReportedErrorInfo {
@@ -310,6 +316,10 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     RemainderOverflow,
     /// Overflowing inbounds pointer arithmetic.
     PointerArithOverflow,
+    /// Overflow in arithmetic that may not overflow.
+    ArithOverflow { intrinsic: Symbol },
+    /// Shift by too much.
+    ShiftOverflow { intrinsic: Symbol, shift_amount: Either<u128, i128> },
     /// Invalid metadata in a wide pointer
     InvalidMeta(InvalidMetaKind),
     /// Reading a C string that does not end within its allocation.
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 739b1410e6d..16093cfca6a 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -15,6 +15,7 @@ use std::num::NonZero;
 use std::sync::atomic::{AtomicU32, Ordering};
 
 use smallvec::{smallvec, SmallVec};
+use tracing::{debug, trace};
 
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashMap;
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 04d6301116e..fe743fa4aac 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -9,6 +9,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
+use tracing::{debug, instrument};
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
@@ -112,8 +113,7 @@ impl<'tcx> TyCtxt<'tcx> {
                                 lint::builtin::CONST_EVALUATABLE_UNCHECKED,
                                 self.local_def_id_to_hir_id(local_def_id),
                                 self.def_span(ct.def),
-                                "cannot use constants which depend on generic parameters in types",
-                                |_| {},
+                                |lint| { lint.primary_message("cannot use constants which depend on generic parameters in types"); },
                             )
                         }
                     }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 25cc9ac47c8..02e5174a715 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -37,6 +37,7 @@ use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 
 use either::Either;
+use tracing::trace;
 
 use std::borrow::Cow;
 use std::cell::RefCell;
@@ -623,7 +624,7 @@ impl<'tcx> Body<'tcx> {
 
     /// Returns the return type; it always return first element from `local_decls` array.
     #[inline]
-    pub fn bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>> {
+    pub fn bound_return_ty(&self) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
         ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty)
     }
 
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index daab6c85581..a3d2140eb1b 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -18,6 +18,7 @@ use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use std::fmt;
 use std::hash::Hash;
+use tracing::debug;
 
 /// Describes how a monomorphization will be instantiated in object files.
 #[derive(PartialEq)]
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index 33412297017..18c48d99b81 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -1,4 +1,5 @@
 use rustc_middle::mir::*;
+use tracing::debug;
 
 /// This struct represents a patch to MIR, which can add
 /// new statements and basic blocks and patch over block
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 7e8598b49df..7bfb4ac867a 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -15,6 +15,7 @@ use rustc_middle::mir::interpret::{
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_target::abi::Size;
+use tracing::trace;
 
 const INDENT: &str = "    ";
 /// Alignment for lining up comments following MIR statements
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 2b28496faec..ebe77a1abfd 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1008,8 +1008,8 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
 /// element:
 ///
 ///  - [`Downcast`](ProjectionElem::Downcast): This projection sets the place's variant index to the
-///    given one, and makes no other changes. A `Downcast` projection on a place with its variant
-///    index already set is not well-formed.
+///    given one, and makes no other changes. A `Downcast` projection must always be followed
+///    immediately by a `Field` projection.
 ///  - [`Field`](ProjectionElem::Field): `Field` projections take their parent place and create a
 ///    place referring to one of the fields of the type. The resulting address is the parent
 ///    address, plus the offset of the field. The type becomes the type of the field. If the parent
@@ -1434,6 +1434,13 @@ pub enum UnOp {
     Not,
     /// The `-` operator for negation
     Neg,
+    /// Get the metadata `M` from a `*const/mut impl Pointee<Metadata = M>`.
+    ///
+    /// For example, this will give a `()` from `*const i32`, a `usize` from
+    /// `*mut [u8]`, or a pointer to a vtable from a `*const dyn Foo`.
+    ///
+    /// Allowed only in [`MirPhase::Runtime`]; earlier it's an intrinsic.
+    PtrMetadata,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index e1ae2e08666..126387db1d9 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -5,6 +5,7 @@
 
 use crate::mir::*;
 use rustc_hir as hir;
+use tracing::{debug, instrument};
 
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
 pub struct PlaceTy<'tcx> {
@@ -179,7 +180,10 @@ impl<'tcx> Rvalue<'tcx> {
                 let rhs_ty = rhs.ty(local_decls, tcx);
                 op.ty(tcx, lhs_ty, rhs_ty)
             }
-            Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
+            Rvalue::UnaryOp(op, ref operand) => {
+                let arg_ty = operand.ty(local_decls, tcx);
+                op.ty(tcx, arg_ty)
+            }
             Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
             Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
                 tcx.types.usize
@@ -281,6 +285,27 @@ impl<'tcx> BinOp {
     }
 }
 
+impl<'tcx> UnOp {
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> {
+        match self {
+            UnOp::Not | UnOp::Neg => arg_ty,
+            UnOp::PtrMetadata => {
+                let pointee_ty = arg_ty
+                    .builtin_deref(true)
+                    .unwrap_or_else(|| bug!("PtrMetadata of non-dereferenceable ty {arg_ty:?}"));
+                if pointee_ty.is_trivially_sized(tcx) {
+                    tcx.types.unit
+                } else {
+                    let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
+                        bug!("No metadata_type lang item while looking at {arg_ty:?}")
+                    };
+                    Ty::new_projection(tcx, metadata_def_id, [pointee_ty])
+                }
+            }
+        }
+    }
+}
+
 impl BorrowKind {
     pub fn to_mutbl_lossy(self) -> hir::Mutability {
         match self {
@@ -295,11 +320,13 @@ impl BorrowKind {
 }
 
 impl BinOp {
-    pub fn to_hir_binop(self) -> hir::BinOpKind {
+    pub(crate) fn to_hir_binop(self) -> hir::BinOpKind {
         match self {
-            BinOp::Add => hir::BinOpKind::Add,
-            BinOp::Sub => hir::BinOpKind::Sub,
-            BinOp::Mul => hir::BinOpKind::Mul,
+            // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending
+            // on whether overflow checks are enabled or not.
+            BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add,
+            BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub,
+            BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul,
             BinOp::Div => hir::BinOpKind::Div,
             BinOp::Rem => hir::BinOpKind::Rem,
             BinOp::BitXor => hir::BinOpKind::BitXor,
@@ -313,10 +340,8 @@ impl BinOp {
             BinOp::Gt => hir::BinOpKind::Gt,
             BinOp::Le => hir::BinOpKind::Le,
             BinOp::Ge => hir::BinOpKind::Ge,
+            // We don't have HIR syntax for these.
             BinOp::Cmp
-            | BinOp::AddWithOverflow
-            | BinOp::SubWithOverflow
-            | BinOp::MulWithOverflow
             | BinOp::AddUnchecked
             | BinOp::SubUnchecked
             | BinOp::MulUnchecked
@@ -338,6 +363,11 @@ impl BinOp {
         })
     }
 
+    /// Returns whether this is a `FooWithOverflow`
+    pub fn is_overflowing(self) -> bool {
+        self.overflowing_to_wrapping().is_some()
+    }
+
     /// If this is a `Foo`, return `Some(FooWithOverflow)`.
     pub fn wrapping_to_overflowing(self) -> Option<BinOp> {
         Some(match self {
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 320d49ea646..1e36f034cc2 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -114,9 +114,11 @@ impl EraseType for Result<CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed> {
     type Result = [u8; size_of::<Result<CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed>>()];
 }
 
-impl EraseType for Result<Option<ty::EarlyBinder<ty::Const<'_>>>, rustc_errors::ErrorGuaranteed> {
+impl EraseType
+    for Result<Option<ty::EarlyBinder<'_, ty::Const<'_>>>, rustc_errors::ErrorGuaranteed>
+{
     type Result = [u8; size_of::<
-        Result<Option<ty::EarlyBinder<ty::Const<'static>>>, rustc_errors::ErrorGuaranteed>,
+        Result<Option<ty::EarlyBinder<'static, ty::Const<'static>>>, rustc_errors::ErrorGuaranteed>,
     >()];
 }
 
@@ -165,8 +167,8 @@ impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
         [u8; size_of::<Result<&'static ty::List<Ty<'static>>, ty::util::AlwaysRequiresDrop>>()];
 }
 
-impl EraseType for Result<ty::EarlyBinder<Ty<'_>>, CyclePlaceholder> {
-    type Result = [u8; size_of::<Result<ty::EarlyBinder<Ty<'_>>, CyclePlaceholder>>()];
+impl EraseType for Result<ty::EarlyBinder<'_, Ty<'_>>, CyclePlaceholder> {
+    type Result = [u8; size_of::<Result<ty::EarlyBinder<'static, Ty<'_>>, CyclePlaceholder>>()];
 }
 
 impl<T> EraseType for Option<&'_ T> {
@@ -185,15 +187,15 @@ impl EraseType for Option<ty::ImplTraitHeader<'_>> {
     type Result = [u8; size_of::<Option<ty::ImplTraitHeader<'static>>>()];
 }
 
-impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> {
-    type Result = [u8; size_of::<Option<ty::EarlyBinder<Ty<'static>>>>()];
+impl EraseType for Option<ty::EarlyBinder<'_, Ty<'_>>> {
+    type Result = [u8; size_of::<Option<ty::EarlyBinder<'static, Ty<'static>>>>()];
 }
 
 impl EraseType for rustc_hir::MaybeOwner<'_> {
     type Result = [u8; size_of::<rustc_hir::MaybeOwner<'static>>()];
 }
 
-impl<T: EraseType> EraseType for ty::EarlyBinder<T> {
+impl<T: EraseType> EraseType for ty::EarlyBinder<'_, T> {
     type Result = T::Result;
 }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index c2f7a227f66..6ad4b7c40fb 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -209,7 +209,7 @@ rustc_queries! {
 
     /// Given the def_id of a const-generic parameter, computes the associated default const
     /// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`.
-    query const_param_default(param: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
+    query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> {
         desc { |tcx| "computing const default for a given parameter `{}`", tcx.def_path_str(param)  }
         cache_on_disk_if { param.is_local() }
         separate_provide_extern
@@ -219,7 +219,7 @@ rustc_queries! {
     /// to an alias, it will "skip" this alias to return the aliased type.
     ///
     /// [`DefId`]: rustc_hir::def_id::DefId
-    query type_of(key: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
+    query type_of(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
         desc { |tcx|
             "{action} `{path}`",
             action = {
@@ -240,7 +240,7 @@ rustc_queries! {
     /// Specialized instance of `type_of` that detects cycles that are due to
     /// revealing opaque because of an auto trait bound. Unless `CyclePlaceholder` needs
     /// to be handled separately, call `type_of` instead.
-    query type_of_opaque(key: DefId) -> Result<ty::EarlyBinder<Ty<'tcx>>, CyclePlaceholder> {
+    query type_of_opaque(key: DefId) -> Result<ty::EarlyBinder<'tcx, Ty<'tcx>>, CyclePlaceholder> {
         desc { |tcx|
             "computing type of opaque `{path}`",
             path = tcx.def_path_str(key),
@@ -257,7 +257,7 @@ rustc_queries! {
     }
 
     query collect_return_position_impl_trait_in_trait_tys(key: DefId)
-        -> Result<&'tcx DefIdMap<ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed>
+        -> Result<&'tcx DefIdMap<ty::EarlyBinder<'tcx, Ty<'tcx>>>, ErrorGuaranteed>
     {
         desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
         cache_on_disk_if { key.is_local() }
@@ -363,7 +363,7 @@ rustc_queries! {
     /// `key` is the `DefId` of the associated type or opaque type.
     ///
     /// Bounds from the parent (e.g. with nested impl trait) are not included.
-    query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
+    query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
         desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
@@ -373,7 +373,7 @@ rustc_queries! {
     /// share the `Self` type of the item. These are a subset of the bounds
     /// that may explicitly be used for things like closure signature
     /// deduction.
-    query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
+    query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
         desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
@@ -399,15 +399,15 @@ rustc_queries! {
     /// ```
     ///
     /// Bounds from the parent (e.g. with nested impl trait) are not included.
-    query item_bounds(key: DefId) -> ty::EarlyBinder<ty::Clauses<'tcx>> {
+    query item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> {
         desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
     }
 
-    query item_super_predicates(key: DefId) -> ty::EarlyBinder<ty::Clauses<'tcx>> {
+    query item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> {
         desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) }
     }
 
-    query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder<ty::Clauses<'tcx>> {
+    query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> {
         desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) }
     }
 
@@ -504,7 +504,7 @@ rustc_queries! {
     /// Try to build an abstract representation of the given constant.
     query thir_abstract_const(
         key: DefId
-    ) -> Result<Option<ty::EarlyBinder<ty::Const<'tcx>>>, ErrorGuaranteed> {
+    ) -> Result<Option<ty::EarlyBinder<'tcx, ty::Const<'tcx>>>, ErrorGuaranteed> {
         desc {
             |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key),
         }
@@ -704,7 +704,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query adt_sized_constraint(key: DefId) -> Option<ty::EarlyBinder<Ty<'tcx>>> {
+    query adt_sized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
         desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) }
     }
 
@@ -780,7 +780,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Maps from a trait item to the trait item "descriptor".
+    /// Maps from a trait/impl item to the trait/impl item "descriptor".
     query associated_item(key: DefId) -> ty::AssocItem {
         desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
@@ -849,7 +849,7 @@ rustc_queries! {
 
     query self_ty_of_trait_impl_enabling_order_dep_trait_object_hack(
         key: DefId
-    ) -> Option<ty::EarlyBinder<ty::Ty<'tcx>>> {
+    ) -> Option<ty::EarlyBinder<'tcx, ty::Ty<'tcx>>> {
         desc { |tcx| "computing self type wrt issue #33140 `{}`", tcx.def_path_str(key) }
     }
 
@@ -888,7 +888,7 @@ rustc_queries! {
     }
 
     /// Computes the signature of the function.
-    query fn_sig(key: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
+    query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> {
         desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
@@ -1860,13 +1860,22 @@ rustc_queries! {
         eval_always
         desc { "calculating the stability index for the local crate" }
     }
-    query crates(_: ()) -> &'tcx [CrateNum] {
+    /// All loaded crates, including those loaded purely for doc links or diagnostics.
+    /// (Diagnostics include lints, so speculatively loaded crates may occur in successful
+    /// compilation even without doc links.)
+    /// Should be used when encoding crate metadata (and therefore when generating crate hash,
+    /// depinfo and similar things), to avoid dangling crate references in other encoded data,
+    /// like source maps.
+    /// May also be used for diagnostics - if we are loading a crate anyway we can suggest some
+    /// items from it as well.
+    /// But otherwise, `used_crates` should generally be used.
+    query crates_including_speculative(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "fetching all foreign CrateNum instances" }
     }
-    // Crates that are loaded non-speculatively (not for diagnostics or doc links).
-    // FIXME: This is currently only used for collecting lang items, but should be used instead of
-    // `crates` in most other cases too.
+    /// Crates that are loaded non-speculatively (not for diagnostics or doc links).
+    /// Should be used to maintain observable language behavior, for example when collecting lang
+    /// items or impls from all crates, or collecting libraries to link.
     query used_crates(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "fetching `CrateNum`s for all crates loaded non-speculatively" }
@@ -2209,15 +2218,6 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being
-    /// equal to eachother. This might return `Ok` even if the types are not equal, but will never return `Err` if
-    /// the types might be equal.
-    query check_tys_might_be_eq(
-        arg: Canonical<'tcx, ty::ParamEnvAnd<'tcx, (Ty<'tcx>, Ty<'tcx>)>>
-    ) -> Result<(), NoSolution> {
-        desc { "check whether two const param are definitely not equal to eachother"}
-    }
-
     /// Get all item paths that were stripped by a `#[cfg]` in a particular crate.
     /// Should not be called for the local crate before the resolver outputs are created, as it
     /// is only fed there.
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 2dcb58729ff..ccd0c7cb10c 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -154,24 +154,25 @@ impl EncodedSourceFileId {
 
 impl<'sess> OnDiskCache<'sess> {
     /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
-    pub fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Self {
-        debug_assert!(sess.opts.incremental.is_some());
-
-        // Wrap in a scope so we can borrow `data`.
-        let footer: Footer = {
-            let mut decoder = MemDecoder::new(&data, start_pos);
-
-            // Decode the *position* of the footer, which can be found in the
-            // last 8 bytes of the file.
-            let footer_pos = decoder
-                .with_position(decoder.len() - IntEncodedWithFixedSize::ENCODED_SIZE, |decoder| {
-                    IntEncodedWithFixedSize::decode(decoder).0 as usize
-                });
-            // Decode the file footer, which contains all the lookup tables, etc.
-            decoder.with_position(footer_pos, |decoder| decode_tagged(decoder, TAG_FILE_FOOTER))
-        };
+    ///
+    /// The serialized cache has some basic integrity checks, if those checks indicate that the
+    /// on-disk data is corrupt, an error is returned.
+    pub fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Result<Self, ()> {
+        assert!(sess.opts.incremental.is_some());
+
+        let mut decoder = MemDecoder::new(&data, start_pos)?;
+
+        // Decode the *position* of the footer, which can be found in the
+        // last 8 bytes of the file.
+        let footer_pos = decoder
+            .with_position(decoder.len() - IntEncodedWithFixedSize::ENCODED_SIZE, |decoder| {
+                IntEncodedWithFixedSize::decode(decoder).0 as usize
+            });
+        // Decode the file footer, which contains all the lookup tables, etc.
+        let footer: Footer =
+            decoder.with_position(footer_pos, |decoder| decode_tagged(decoder, TAG_FILE_FOOTER));
 
-        Self {
+        Ok(Self {
             serialized_data: RwLock::new(Some(data)),
             file_index_to_stable_id: footer.file_index_to_stable_id,
             file_index_to_file: Default::default(),
@@ -184,7 +185,7 @@ impl<'sess> OnDiskCache<'sess> {
             expn_data: footer.expn_data,
             foreign_expn_data: footer.foreign_expn_data,
             hygiene_context: Default::default(),
-        }
+        })
     }
 
     pub fn new_empty(source_map: &'sess SourceMap) -> Self {
@@ -437,7 +438,8 @@ impl<'sess> OnDiskCache<'sess> {
         let serialized_data = self.serialized_data.read();
         let mut decoder = CacheDecoder {
             tcx,
-            opaque: MemDecoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()),
+            opaque: MemDecoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize())
+                .unwrap(),
             source_map: self.source_map,
             file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
@@ -558,7 +560,7 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> {
     {
         debug_assert!(pos < self.opaque.len());
 
-        let new_opaque = MemDecoder::new(self.opaque.data(), pos);
+        let new_opaque = self.opaque.split_at(pos);
         let old_opaque = mem::replace(&mut self.opaque, new_opaque);
         let r = f(self);
         self.opaque = old_opaque;
@@ -750,7 +752,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx UnordSet<LocalDefId>
 }
 
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
-    for &'tcx UnordMap<DefId, ty::EarlyBinder<Ty<'tcx>>>
+    for &'tcx UnordMap<DefId, ty::EarlyBinder<'tcx, Ty<'tcx>>>
 {
     #[inline]
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index c68b7a6c9eb..454897aa672 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -32,6 +32,7 @@ use rustc_target::asm::InlineAsmRegOrRegClass;
 use std::cmp::Ordering;
 use std::fmt;
 use std::ops::Index;
+use tracing::instrument;
 
 pub mod visit;
 
diff --git a/compiler/rustc_middle/src/traits/solve/cache.rs b/compiler/rustc_middle/src/traits/solve/cache.rs
index 2ff4ade21d0..dc31114b2c4 100644
--- a/compiler/rustc_middle/src/traits/solve/cache.rs
+++ b/compiler/rustc_middle/src/traits/solve/cache.rs
@@ -17,7 +17,7 @@ pub struct EvaluationCache<'tcx> {
 #[derive(Debug, PartialEq, Eq)]
 pub struct CacheData<'tcx> {
     pub result: QueryResult<'tcx>,
-    pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>,
+    pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>>,
     pub additional_depth: usize,
     pub encountered_overflow: bool,
 }
@@ -28,7 +28,7 @@ impl<'tcx> EvaluationCache<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         key: CanonicalInput<'tcx>,
-        proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>,
+        proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>>,
         additional_depth: usize,
         encountered_overflow: bool,
         cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
@@ -107,7 +107,7 @@ struct Success<'tcx> {
 #[derive(Clone, Copy)]
 pub struct QueryData<'tcx> {
     pub result: QueryResult<'tcx>,
-    pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>,
+    pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>>,
 }
 
 /// The cache entry for a goal `CanonicalInput`.
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index e28e4d66faf..f30270abd5c 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -1,6 +1,7 @@
 use crate::ty::error::TypeError;
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use crate::ty::{self, InferConst, Ty, TyCtxt};
+use tracing::{debug, instrument};
 
 /// A type "A" *matches* "B" if the fresh types in B could be
 /// instantiated with values so as to make it equal to A. Matching is
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index dc46b470b6f..7fb5e9aadae 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -30,7 +30,8 @@ impl From<ErrorGuaranteed> for NotConstEvaluatable {
 
 TrivialTypeTraversalImpls! { NotConstEvaluatable }
 
-pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>, ErrorGuaranteed>;
+pub type BoundAbstractConst<'tcx> =
+    Result<Option<EarlyBinder<'tcx, ty::Const<'tcx>>>, ErrorGuaranteed>;
 
 impl<'tcx> TyCtxt<'tcx> {
     pub fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, ac: T) -> T {
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 77da3fbe1d7..8e946bc8b31 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -17,6 +17,7 @@ use rustc_query_system::ich::StableHashingContext;
 use rustc_session::DataTypeKind;
 use rustc_span::symbol::sym;
 use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT};
+use tracing::{debug, info, trace};
 
 use std::cell::RefCell;
 use std::hash::{Hash, Hasher};
@@ -578,7 +579,7 @@ impl<'tcx> AdtDef<'tcx> {
 
     /// Returns a type such that `Self: Sized` if and only if that type is `Sized`,
     /// or `None` if the type is always sized.
-    pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<Ty<'tcx>>> {
+    pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
         if self.is_struct() { tcx.adt_sized_constraint(self.did()) } else { None }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index c0effe9804c..07652b47929 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -115,18 +115,11 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Ty<'tcx> {
     }
 }
 
-impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E>
-    for ty::Binder<'tcx, ty::PredicateKind<'tcx>>
-{
-    fn encode(&self, e: &mut E) {
-        self.bound_vars().encode(e);
-        encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands);
-    }
-}
-
 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> {
     fn encode(&self, e: &mut E) {
-        self.kind().encode(e);
+        let kind = self.kind();
+        kind.bound_vars().encode(e);
+        encode_with_shorthand(e, &kind.skip_binder(), TyEncoder::predicate_shorthands);
     }
 }
 
@@ -233,13 +226,11 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Ty<'tcx> {
     }
 }
 
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D>
-    for ty::Binder<'tcx, ty::PredicateKind<'tcx>>
-{
-    fn decode(decoder: &mut D) -> ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx> {
+    fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
         let bound_vars = Decodable::decode(decoder);
         // Handle shorthands first, if we have a usize > 0x80.
-        ty::Binder::bind_with_vars(
+        let predicate_kind = ty::Binder::bind_with_vars(
             if decoder.positioned_at_shorthand() {
                 let pos = decoder.read_usize();
                 assert!(pos >= SHORTHAND_OFFSET);
@@ -250,13 +241,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D>
                 <ty::PredicateKind<'tcx> as Decodable<D>>::decode(decoder)
             },
             bound_vars,
-        )
-    }
-}
-
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx> {
-    fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
-        let predicate_kind = Decodable::decode(decoder);
+        );
         decoder.interner().mk_predicate(predicate_kind)
     }
 }
@@ -599,32 +584,3 @@ macro_rules! implement_ty_decoder {
         }
     }
 }
-
-macro_rules! impl_binder_encode_decode {
-    ($($t:ty),+ $(,)?) => {
-        $(
-            impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Binder<'tcx, $t> {
-                fn encode(&self, e: &mut E) {
-                    self.bound_vars().encode(e);
-                    self.as_ref().skip_binder().encode(e);
-                }
-            }
-            impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Binder<'tcx, $t> {
-                fn decode(decoder: &mut D) -> Self {
-                    let bound_vars = Decodable::decode(decoder);
-                    ty::Binder::bind_with_vars(Decodable::decode(decoder), bound_vars)
-                }
-            }
-        )*
-    }
-}
-
-impl_binder_encode_decode! {
-    &'tcx ty::List<Ty<'tcx>>,
-    ty::FnSig<'tcx>,
-    ty::Predicate<'tcx>,
-    ty::TraitPredicate<'tcx>,
-    ty::ExistentialPredicate<'tcx>,
-    ty::TraitRef<'tcx>,
-    ty::ExistentialTraitRef<'tcx>,
-}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index f7cc055be11..6416bbbe889 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -8,6 +8,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
+use tracing::{debug, instrument};
 
 mod int;
 mod kind;
@@ -183,6 +184,15 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
         Const::new_var(tcx, vid, ty)
     }
 
+    fn new_bound(
+        interner: TyCtxt<'tcx>,
+        debruijn: ty::DebruijnIndex,
+        var: ty::BoundVar,
+        ty: Ty<'tcx>,
+    ) -> Self {
+        Const::new_bound(interner, debruijn, var, ty)
+    }
+
     fn new_anon_bound(
         tcx: TyCtxt<'tcx>,
         debruijn: ty::DebruijnIndex,
@@ -485,7 +495,10 @@ impl<'tcx> Const<'tcx> {
     }
 }
 
-pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Const<'_>> {
+pub fn const_param_default<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
     let default_def_id = match tcx.hir_node_by_def_id(def_id) {
         hir::Node::GenericParam(hir::GenericParam {
             kind: hir::GenericParamKind::Const { default: Some(ac), .. },
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8185c99c2fd..c2219fba023 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -31,8 +31,7 @@ use crate::ty::{
     self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
     GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
     PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity,
-    Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, TypeVisitable,
-    Visibility,
+    Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
 };
 use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use rustc_ast::{self as ast, attr};
@@ -48,9 +47,7 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, RwLock, Work
 #[cfg(parallel_compiler)]
 use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{
-    Applicability, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, LintDiagnostic, MultiSpan,
-};
+use rustc_errors::{Applicability, Diag, DiagCtxt, ErrorGuaranteed, LintDiagnostic, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
@@ -75,6 +72,7 @@ use rustc_target::spec::abi;
 use rustc_type_ir::TyKind::*;
 use rustc_type_ir::WithCachedTypeInfo;
 use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
+use tracing::{debug, instrument};
 
 use std::assert_matches::assert_matches;
 use std::borrow::Borrow;
@@ -96,15 +94,15 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type GenericArg = ty::GenericArg<'tcx>;
     type Term = ty::Term<'tcx>;
 
-    type Binder<T: TypeVisitable<TyCtxt<'tcx>>> = Binder<'tcx, T>;
-    type BoundVars = &'tcx List<ty::BoundVariableKind>;
-    type BoundVar = ty::BoundVariableKind;
+    type BoundVarKinds = &'tcx List<ty::BoundVariableKind>;
+    type BoundVarKind = ty::BoundVariableKind;
 
     type CanonicalVars = CanonicalVarInfos<'tcx>;
     type PredefinedOpaques = solve::PredefinedOpaques<'tcx>;
     type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
     type ExternalConstraints = ExternalConstraints<'tcx>;
-    type GoalEvaluationSteps = &'tcx [solve::inspect::GoalEvaluationStep<TyCtxt<'tcx>>];
+    type CanonicalGoalEvaluationStepRef =
+        &'tcx solve::inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>;
 
     type Ty = Ty<'tcx>;
     type Tys = &'tcx List<Ty<'tcx>>;
@@ -123,7 +121,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type Abi = abi::Abi;
 
     type Const = ty::Const<'tcx>;
-    type AliasConst = ty::UnevaluatedConst<'tcx>;
     type PlaceholderConst = ty::PlaceholderConst;
     type ParamConst = ty::ParamConst;
     type BoundConst = ty::BoundVar;
@@ -138,15 +135,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
 
     type ParamEnv = ty::ParamEnv<'tcx>;
     type Predicate = Predicate<'tcx>;
-    type TraitPredicate = ty::TraitPredicate<'tcx>;
-    type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
-    type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
-    type ProjectionPredicate = ty::ProjectionPredicate<'tcx>;
-    type NormalizesTo = ty::NormalizesTo<'tcx>;
-    type SubtypePredicate = ty::SubtypePredicate<'tcx>;
-
-    type CoercePredicate = ty::CoercePredicate<'tcx>;
-    type ClosureKind = ty::ClosureKind;
+    type Clause = Clause<'tcx>;
 
     type Clauses = ty::Clauses<'tcx>;
 
@@ -160,8 +149,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.generics_of(def_id)
     }
 
-    fn type_of_instantiated(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Ty<'tcx> {
-        self.type_of(def_id).instantiate(self, args)
+    fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
+        self.type_of(def_id)
     }
 
     fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind {
@@ -229,6 +218,13 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.check_and_mk_args(def_id, args)
     }
 
+    fn intern_canonical_goal_evaluation_step(
+        self,
+        step: solve::inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>>,
+    ) -> &'tcx solve::inspect::CanonicalGoalEvaluationStep<TyCtxt<'tcx>> {
+        self.arena.alloc(step)
+    }
+
     fn parent(self, def_id: Self::DefId) -> Self::DefId {
         self.parent(def_id)
     }
@@ -245,6 +241,10 @@ impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
 }
 
 impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
+    fn is_safe(self) -> bool {
+        matches!(self, hir::Safety::Safe)
+    }
+
     fn prefix_str(self) -> &'static str {
         self.prefix_str()
     }
@@ -686,7 +686,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// In order to break cycles involving `AnonConst`, we need to set the expected type by side
     /// effect. However, we do not want this as a general capability, so this interface restricts
     /// to the only allowed case.
-    pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<Ty<'tcx>>) {
+    pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<'tcx, Ty<'tcx>>) {
         debug_assert_eq!(self.def_kind(key), DefKind::AnonConst);
         TyCtxtFeed { tcx: self, key }.type_of(value)
     }
@@ -744,6 +744,7 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
                 1,
             ),
             bodies,
+            has_inline_consts: false,
         })));
         self.feed_owner_id().hir_attrs(attrs);
     }
@@ -1494,13 +1495,14 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     /// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
-    pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionInfo> {
+    pub fn is_suitable_region(
+        self,
+        generic_param_scope: LocalDefId,
+        mut region: Region<'tcx>,
+    ) -> Option<FreeRegionInfo> {
         let (suitable_region_binding_scope, bound_region) = loop {
-            let def_id = match region.kind() {
-                ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?,
-                ty::ReEarlyParam(ebr) => ebr.def_id.as_local()?,
-                _ => return None, // not a free region
-            };
+            let def_id =
+                region.opt_param_def_id(self, generic_param_scope.to_def_id())?.as_local()?;
             let scope = self.local_parent(def_id);
             if self.def_kind(scope) == DefKind::OpaqueTy {
                 // Lifetime params of opaque types are synthetic and thus irrelevant to
@@ -1618,7 +1620,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
         iter::once(LOCAL_CRATE)
-            .chain(self.crates(()).iter().copied())
+            .chain(self.used_crates(()).iter().copied())
             .flat_map(move |cnum| self.traits(cnum).iter().copied())
     }
 
@@ -2475,10 +2477,9 @@ impl<'tcx> TyCtxt<'tcx> {
         span: impl Into<MultiSpan>,
         decorator: impl for<'a> LintDiagnostic<'a, ()>,
     ) {
-        let msg = decorator.msg();
         let (level, src) = self.lint_level_at_node(lint, hir_id);
-        lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
-            decorator.decorate_lint(diag);
+        lint_level(self.sess, lint, level, src, Some(span.into()), |lint| {
+            decorator.decorate_lint(lint);
         })
     }
 
@@ -2492,11 +2493,10 @@ impl<'tcx> TyCtxt<'tcx> {
         lint: &'static Lint,
         hir_id: HirId,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         let (level, src) = self.lint_level_at_node(lint, hir_id);
-        lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
+        lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
     }
 
     /// Find the crate root and the appropriate span where `use` and outer attributes can be
@@ -2547,8 +2547,8 @@ impl<'tcx> TyCtxt<'tcx> {
         id: HirId,
         decorator: impl for<'a> LintDiagnostic<'a, ()>,
     ) {
-        self.node_lint(lint, id, decorator.msg(), |diag| {
-            decorator.decorate_lint(diag);
+        self.node_lint(lint, id, |lint| {
+            decorator.decorate_lint(lint);
         })
     }
 
@@ -2561,11 +2561,10 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         lint: &'static Lint,
         id: HirId,
-        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         let (level, src) = self.lint_level_at_node(lint, id);
-        lint_level(self.sess, lint, level, src, None, msg, decorate);
+        lint_level(self.sess, lint, level, src, None, decorate);
     }
 
     pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
@@ -2639,7 +2638,6 @@ impl<'tcx> TyCtxt<'tcx> {
                     return ty::Region::new_early_param(
                         self,
                         ty::EarlyParamRegion {
-                            def_id: ebv,
                             index: generics
                                 .param_def_id_to_index(self, ebv)
                                 .expect("early-bound var should be present in fn generics"),
@@ -2751,7 +2749,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn impl_trait_ref(
         self,
         def_id: impl IntoQueryParam<DefId>,
-    ) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
+    ) -> Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>> {
         Some(self.impl_trait_header(def_id)?.trait_ref)
     }
 
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index cfd36fd8c7c..cd6e7df31f7 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,6 +1,7 @@
 use crate::query::Providers;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
+use tracing::debug;
 
 pub(super) fn provide(providers: &mut Providers) {
     *providers = Providers { erase_regions_ty, ..*providers };
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index fd3bee16e26..b5b36cbd1ba 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -1,8 +1,11 @@
 use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::def_id::DefId;
+use tracing::{debug, instrument};
 
-pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
+pub use rustc_type_ir::fold::{
+    shift_region, shift_vars, FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable,
+};
 
 ///////////////////////////////////////////////////////////////////////////
 // Some sample folders
@@ -411,103 +414,3 @@ impl<'tcx> TyCtxt<'tcx> {
         Binder::bind_with_vars(inner, bound_vars)
     }
 }
-
-///////////////////////////////////////////////////////////////////////////
-// Shifter
-//
-// Shifts the De Bruijn indices on all escaping bound vars by a
-// fixed amount. Useful in instantiation or when otherwise introducing
-// a binding level that is not intended to capture the existing bound
-// vars. See comment on `shift_vars_through_binders` method in
-// `rustc_middle/src/ty/generic_args.rs` for more details.
-
-struct Shifter<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    current_index: ty::DebruijnIndex,
-    amount: u32,
-}
-
-impl<'tcx> Shifter<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, amount: u32) -> Self {
-        Shifter { tcx, current_index: ty::INNERMOST, amount }
-    }
-}
-
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
-        self.current_index.shift_in(1);
-        let t = t.super_fold_with(self);
-        self.current_index.shift_out(1);
-        t
-    }
-
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
-            ty::ReBound(debruijn, br) if debruijn >= self.current_index => {
-                let debruijn = debruijn.shifted_in(self.amount);
-                ty::Region::new_bound(self.tcx, debruijn, br)
-            }
-            _ => r,
-        }
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        match *ty.kind() {
-            ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
-                let debruijn = debruijn.shifted_in(self.amount);
-                Ty::new_bound(self.tcx, debruijn, bound_ty)
-            }
-
-            _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
-            _ => ty,
-        }
-    }
-
-    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind()
-            && debruijn >= self.current_index
-        {
-            let debruijn = debruijn.shifted_in(self.amount);
-            ty::Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty())
-        } else {
-            ct.super_fold_with(self)
-        }
-    }
-
-    fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
-        if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
-    }
-}
-
-pub fn shift_region<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    region: ty::Region<'tcx>,
-    amount: u32,
-) -> ty::Region<'tcx> {
-    match *region {
-        ty::ReBound(debruijn, br) if amount > 0 => {
-            ty::Region::new_bound(tcx, debruijn.shifted_in(amount), br)
-        }
-        _ => region,
-    }
-}
-
-pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T
-where
-    T: TypeFoldable<TyCtxt<'tcx>>,
-{
-    debug!("shift_vars(value={:?}, amount={})", value, amount);
-
-    if amount == 0 || !value.has_escaping_bound_vars() {
-        return value;
-    }
-
-    value.fold_with(&mut Shifter::new(tcx, amount))
-}
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 3d263e62de6..7a516b9f2c8 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -1,10 +1,10 @@
 // Generic arguments.
 
 use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs};
-use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
-use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
+use crate::ty::visit::{TypeVisitable, TypeVisitor};
+use crate::ty::{self, Lift, List, Ty, TyCtxt};
 
 use rustc_ast_ir::visit::VisitorResult;
 use rustc_ast_ir::walk_visitable_list;
@@ -12,9 +12,7 @@ use rustc_data_structures::intern::Interned;
 use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::DefId;
 use rustc_macros::extension;
-use rustc_macros::{
-    Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
-};
+use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 use rustc_serialize::{Decodable, Encodable};
 use rustc_type_ir::WithCachedTypeInfo;
 use smallvec::SmallVec;
@@ -23,7 +21,6 @@ use core::intrinsics;
 use std::marker::PhantomData;
 use std::mem;
 use std::num::NonZero;
-use std::ops::Deref;
 use std::ptr::NonNull;
 
 pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind<TyCtxt<'tcx>>;
@@ -51,6 +48,14 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg
     fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
         GenericArgs::identity_for_item(tcx, def_id)
     }
+
+    fn extend_with_error(
+        tcx: TyCtxt<'tcx>,
+        def_id: DefId,
+        original_args: &[ty::GenericArg<'tcx>],
+    ) -> ty::GenericArgsRef<'tcx> {
+        ty::GenericArgs::extend_with_error(tcx, def_id, original_args)
+    }
 }
 
 impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> {
@@ -567,490 +572,6 @@ impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx
     }
 }
 
-/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
-/// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call
-/// `instantiate`.
-///
-/// If you don't have anything to `instantiate`, you may be looking for
-/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(Encodable, Decodable, HashStable)]
-pub struct EarlyBinder<T> {
-    value: T,
-}
-
-/// For early binders, you should first call `instantiate` before using any visitors.
-impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
-impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
-
-impl<T> EarlyBinder<T> {
-    pub fn bind(value: T) -> EarlyBinder<T> {
-        EarlyBinder { value }
-    }
-
-    pub fn as_ref(&self) -> EarlyBinder<&T> {
-        EarlyBinder { value: &self.value }
-    }
-
-    pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
-    where
-        F: FnOnce(&T) -> U,
-    {
-        self.as_ref().map_bound(f)
-    }
-
-    pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U>
-    where
-        F: FnOnce(T) -> U,
-    {
-        let value = f(self.value);
-        EarlyBinder { value }
-    }
-
-    pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
-    where
-        F: FnOnce(T) -> Result<U, E>,
-    {
-        let value = f(self.value)?;
-        Ok(EarlyBinder { value })
-    }
-
-    pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
-        EarlyBinder { value }
-    }
-
-    /// Skips the binder and returns the "bound" value.
-    /// This can be used to extract data that does not depend on generic parameters
-    /// (e.g., getting the `DefId` of the inner value or getting the number of
-    /// arguments of an `FnSig`). Otherwise, consider using
-    /// [`instantiate_identity`](EarlyBinder::instantiate_identity).
-    ///
-    /// To skip the binder on `x: &EarlyBinder<T>` to obtain `&T`, leverage
-    /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`.
-    ///
-    /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
-    /// the analogous operation on [`super::Binder`].
-    pub fn skip_binder(self) -> T {
-        self.value
-    }
-}
-
-impl<T> EarlyBinder<Option<T>> {
-    pub fn transpose(self) -> Option<EarlyBinder<T>> {
-        self.value.map(|value| EarlyBinder { value })
-    }
-}
-
-impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
-where
-    I::Item: TypeFoldable<TyCtxt<'tcx>>,
-{
-    pub fn iter_instantiated(
-        self,
-        tcx: TyCtxt<'tcx>,
-        args: &'s [GenericArg<'tcx>],
-    ) -> IterInstantiated<'s, 'tcx, I> {
-        IterInstantiated { it: self.value.into_iter(), tcx, args }
-    }
-
-    /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
-    /// but on an iterator of `TypeFoldable` values.
-    pub fn instantiate_identity_iter(self) -> I::IntoIter {
-        self.value.into_iter()
-    }
-}
-
-pub struct IterInstantiated<'s, 'tcx, I: IntoIterator> {
-    it: I::IntoIter,
-    tcx: TyCtxt<'tcx>,
-    args: &'s [GenericArg<'tcx>],
-}
-
-impl<'tcx, I: IntoIterator> Iterator for IterInstantiated<'_, 'tcx, I>
-where
-    I::Item: TypeFoldable<TyCtxt<'tcx>>,
-{
-    type Item = I::Item;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        Some(EarlyBinder { value: self.it.next()? }.instantiate(self.tcx, self.args))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.it.size_hint()
-    }
-}
-
-impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiated<'_, 'tcx, I>
-where
-    I::IntoIter: DoubleEndedIterator,
-    I::Item: TypeFoldable<TyCtxt<'tcx>>,
-{
-    fn next_back(&mut self) -> Option<Self::Item> {
-        Some(EarlyBinder { value: self.it.next_back()? }.instantiate(self.tcx, self.args))
-    }
-}
-
-impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiated<'_, 'tcx, I>
-where
-    I::IntoIter: ExactSizeIterator,
-    I::Item: TypeFoldable<TyCtxt<'tcx>>,
-{
-}
-
-impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
-where
-    I::Item: Deref,
-    <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
-{
-    pub fn iter_instantiated_copied(
-        self,
-        tcx: TyCtxt<'tcx>,
-        args: &'s [GenericArg<'tcx>],
-    ) -> IterInstantiatedCopied<'s, 'tcx, I> {
-        IterInstantiatedCopied { it: self.value.into_iter(), tcx, args }
-    }
-
-    /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity),
-    /// but on an iterator of values that deref to a `TypeFoldable`.
-    pub fn instantiate_identity_iter_copied(
-        self,
-    ) -> impl Iterator<Item = <I::Item as Deref>::Target> {
-        self.value.into_iter().map(|v| *v)
-    }
-}
-
-pub struct IterInstantiatedCopied<'a, 'tcx, I: IntoIterator> {
-    it: I::IntoIter,
-    tcx: TyCtxt<'tcx>,
-    args: &'a [GenericArg<'tcx>],
-}
-
-impl<'tcx, I: IntoIterator> Iterator for IterInstantiatedCopied<'_, 'tcx, I>
-where
-    I::Item: Deref,
-    <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
-{
-    type Item = <I::Item as Deref>::Target;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.it.next().map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.it.size_hint()
-    }
-}
-
-impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiatedCopied<'_, 'tcx, I>
-where
-    I::IntoIter: DoubleEndedIterator,
-    I::Item: Deref,
-    <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
-{
-    fn next_back(&mut self) -> Option<Self::Item> {
-        self.it
-            .next_back()
-            .map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args))
-    }
-}
-
-impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiatedCopied<'_, 'tcx, I>
-where
-    I::IntoIter: ExactSizeIterator,
-    I::Item: Deref,
-    <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
-{
-}
-
-pub struct EarlyBinderIter<T> {
-    t: T,
-}
-
-impl<T: IntoIterator> EarlyBinder<T> {
-    pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
-        EarlyBinderIter { t: self.value.into_iter() }
-    }
-}
-
-impl<T: Iterator> Iterator for EarlyBinderIter<T> {
-    type Item = EarlyBinder<T::Item>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.t.next().map(|value| EarlyBinder { value })
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.t.size_hint()
-    }
-}
-
-impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
-    pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: &[GenericArg<'tcx>]) -> T {
-        let mut folder = ArgFolder { tcx, args, binders_passed: 0 };
-        self.value.fold_with(&mut folder)
-    }
-
-    /// Makes the identity replacement `T0 => T0, ..., TN => TN`.
-    /// Conceptually, this converts universally bound variables into placeholders
-    /// when inside of a given item.
-    ///
-    /// For example, consider `for<T> fn foo<T>(){ .. }`:
-    /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`).
-    /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling
-    /// `instantiate_identity` to discharge the `EarlyBinder`.
-    pub fn instantiate_identity(self) -> T {
-        self.value
-    }
-
-    /// Returns the inner value, but only if it contains no bound vars.
-    pub fn no_bound_vars(self) -> Option<T> {
-        if !self.value.has_param() { Some(self.value) } else { None }
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// The actual instantiation engine itself is a type folder.
-
-struct ArgFolder<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    args: &'a [GenericArg<'tcx>],
-
-    /// Number of region binders we have passed through while doing the instantiation
-    binders_passed: u32,
-}
-
-impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
-    #[inline]
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: ty::Binder<'tcx, T>,
-    ) -> ty::Binder<'tcx, T> {
-        self.binders_passed += 1;
-        let t = t.super_fold_with(self);
-        self.binders_passed -= 1;
-        t
-    }
-
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        #[cold]
-        #[inline(never)]
-        fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! {
-            bug!(
-                "Region parameter out of range when instantiating in region {} (index={}, args = {:?})",
-                data.name,
-                data.index,
-                args,
-            )
-        }
-
-        #[cold]
-        #[inline(never)]
-        fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! {
-            bug!(
-                "Unexpected parameter {:?} when instantiating in region {} (index={})",
-                other,
-                data.name,
-                data.index
-            )
-        }
-
-        // Note: This routine only handles regions that are bound on
-        // type declarations and other outer declarations, not those
-        // bound in *fn types*. Region instantiation of the bound
-        // regions that appear in a function signature is done using
-        // the specialized routine `ty::replace_late_regions()`.
-        match *r {
-            ty::ReEarlyParam(data) => {
-                let rk = self.args.get(data.index as usize).map(|k| k.unpack());
-                match rk {
-                    Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
-                    Some(other) => region_param_invalid(data, other),
-                    None => region_param_out_of_range(data, self.args),
-                }
-            }
-            ty::ReBound(..)
-            | ty::ReLateParam(_)
-            | ty::ReStatic
-            | ty::RePlaceholder(_)
-            | ty::ReErased
-            | ty::ReError(_) => r,
-            ty::ReVar(_) => bug!("unexpected region: {r:?}"),
-        }
-    }
-
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.has_param() {
-            return t;
-        }
-
-        match *t.kind() {
-            ty::Param(p) => self.ty_for_param(p, t),
-            _ => t.super_fold_with(self),
-        }
-    }
-
-    fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if let ty::ConstKind::Param(p) = c.kind() {
-            self.const_for_param(p, c)
-        } else {
-            c.super_fold_with(self)
-        }
-    }
-}
-
-impl<'a, 'tcx> ArgFolder<'a, 'tcx> {
-    fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
-        // Look up the type in the args. It really should be in there.
-        let opt_ty = self.args.get(p.index as usize).map(|k| k.unpack());
-        let ty = match opt_ty {
-            Some(GenericArgKind::Type(ty)) => ty,
-            Some(kind) => self.type_param_expected(p, source_ty, kind),
-            None => self.type_param_out_of_range(p, source_ty),
-        };
-
-        self.shift_vars_through_binders(ty)
-    }
-
-    #[cold]
-    #[inline(never)]
-    fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! {
-        bug!(
-            "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}",
-            p,
-            ty,
-            p.index,
-            kind,
-            self.args,
-        )
-    }
-
-    #[cold]
-    #[inline(never)]
-    fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! {
-        bug!(
-            "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}",
-            p,
-            ty,
-            p.index,
-            self.args,
-        )
-    }
-
-    fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        // Look up the const in the args. It really should be in there.
-        let opt_ct = self.args.get(p.index as usize).map(|k| k.unpack());
-        let ct = match opt_ct {
-            Some(GenericArgKind::Const(ct)) => ct,
-            Some(kind) => self.const_param_expected(p, source_ct, kind),
-            None => self.const_param_out_of_range(p, source_ct),
-        };
-
-        self.shift_vars_through_binders(ct)
-    }
-
-    #[cold]
-    #[inline(never)]
-    fn const_param_expected(
-        &self,
-        p: ty::ParamConst,
-        ct: ty::Const<'tcx>,
-        kind: GenericArgKind<'tcx>,
-    ) -> ! {
-        bug!(
-            "expected const for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}",
-            p,
-            ct,
-            p.index,
-            kind,
-            self.args,
-        )
-    }
-
-    #[cold]
-    #[inline(never)]
-    fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! {
-        bug!(
-            "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}",
-            p,
-            ct,
-            p.index,
-            self.args,
-        )
-    }
-
-    /// It is sometimes necessary to adjust the De Bruijn indices during instantiation. This occurs
-    /// when we are instantating a type with escaping bound vars into a context where we have
-    /// passed through binders. That's quite a mouthful. Let's see an example:
-    ///
-    /// ```
-    /// type Func<A> = fn(A);
-    /// type MetaFunc = for<'a> fn(Func<&'a i32>);
-    /// ```
-    ///
-    /// The type `MetaFunc`, when fully expanded, will be
-    /// ```ignore (illustrative)
-    /// for<'a> fn(fn(&'a i32))
-    /// //      ^~ ^~ ^~~
-    /// //      |  |  |
-    /// //      |  |  DebruijnIndex of 2
-    /// //      Binders
-    /// ```
-    /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the
-    /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
-    /// over the inner binder (remember that we count De Bruijn indices from 1). However, in the
-    /// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a
-    /// De Bruijn index of 1. It's only during the instantiation that we can see we must increase the
-    /// depth by 1 to account for the binder that we passed through.
-    ///
-    /// As a second example, consider this twist:
-    ///
-    /// ```
-    /// type FuncTuple<A> = (A,fn(A));
-    /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>);
-    /// ```
-    ///
-    /// Here the final type will be:
-    /// ```ignore (illustrative)
-    /// for<'a> fn((&'a i32, fn(&'a i32)))
-    /// //          ^~~         ^~~
-    /// //          |           |
-    /// //   DebruijnIndex of 1 |
-    /// //               DebruijnIndex of 2
-    /// ```
-    /// As indicated in the diagram, here the same type `&'a i32` is instantiated once, but in the
-    /// first case we do not increase the De Bruijn index and in the second case we do. The reason
-    /// is that only in the second case have we passed through a fn binder.
-    fn shift_vars_through_binders<T: TypeFoldable<TyCtxt<'tcx>>>(&self, val: T) -> T {
-        debug!(
-            "shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})",
-            val,
-            self.binders_passed,
-            val.has_escaping_bound_vars()
-        );
-
-        if self.binders_passed == 0 || !val.has_escaping_bound_vars() {
-            return val;
-        }
-
-        let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed);
-        debug!("shift_vars: shifted result = {:?}", result);
-
-        result
-    }
-
-    fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        if self.binders_passed == 0 || !region.has_escaping_bound_vars() {
-            return region;
-        }
-        ty::fold::shift_region(self.tcx, region, self.binders_passed)
-    }
-}
-
 /// Stores the user-given args to reach some fully qualified path
 /// (e.g., `<T>::Item` or `<T as Trait>::Item`).
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index cfaca05c2f0..89ba8cd2ad4 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -6,6 +6,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::Span;
+use tracing::instrument;
 
 use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
 
@@ -65,7 +66,7 @@ pub struct GenericParamDef {
 impl GenericParamDef {
     pub fn to_early_bound_region_data(&self) -> ty::EarlyParamRegion {
         if let GenericParamDefKind::Lifetime = self.kind {
-            ty::EarlyParamRegion { def_id: self.def_id, index: self.index, name: self.name }
+            ty::EarlyParamRegion { index: self.index, name: self.name }
         } else {
             bug!("cannot convert a non-lifetime parameter def to an early bound region")
         }
@@ -87,7 +88,7 @@ impl GenericParamDef {
     pub fn default_value<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
-    ) -> Option<EarlyBinder<ty::GenericArg<'tcx>>> {
+    ) -> Option<EarlyBinder<'tcx, ty::GenericArg<'tcx>>> {
         match self.kind {
             GenericParamDefKind::Type { has_default, .. } if has_default => {
                 Some(tcx.type_of(self.def_id).map_bound(|t| t.into()))
@@ -244,20 +245,6 @@ impl<'tcx> Generics {
         }
     }
 
-    /// Returns the `GenericParamDef` with the given index if available.
-    pub fn opt_param_at(
-        &'tcx self,
-        param_index: usize,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<&'tcx GenericParamDef> {
-        if let Some(index) = param_index.checked_sub(self.parent_count) {
-            self.own_params.get(index)
-        } else {
-            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
-                .opt_param_at(param_index, tcx)
-        }
-    }
-
     pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
         if let Some(index) = param_index.checked_sub(self.parent_count) {
             &self.own_params[..index]
@@ -289,20 +276,6 @@ impl<'tcx> Generics {
         }
     }
 
-    /// Returns the `GenericParamDef` associated with this `ParamTy` if it belongs to this
-    /// `Generics`.
-    pub fn opt_type_param(
-        &'tcx self,
-        param: ParamTy,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<&'tcx GenericParamDef> {
-        let param = self.opt_param_at(param.index as usize, tcx)?;
-        match param.kind {
-            GenericParamDefKind::Type { .. } => Some(param),
-            _ => None,
-        }
-    }
-
     /// Returns the `GenericParamDef` associated with this `ParamConst`.
     pub fn const_param(&'tcx self, param: ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
         let param = self.param_at(param.index as usize, tcx);
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index ef7a7a99ff7..efcf428c213 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -12,6 +12,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
 use rustc_query_system::ich::StableHashingContext;
 use std::cell::RefCell;
 use std::ptr;
+use tracing::trace;
 
 impl<'a, 'tcx, H, T> HashStable<StableHashingContext<'a>> for &'tcx ty::list::RawList<H, T>
 where
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index e3eea83ba49..54b8507babf 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -1,5 +1,6 @@
 use rustc_macros::HashStable;
 use smallvec::SmallVec;
+use tracing::instrument;
 
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty};
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index da5d57db5be..afdf2cbc726 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -48,6 +48,7 @@ use crate::ty::context::TyCtxt;
 use crate::ty::{self, DefId, Ty, TypeVisitableExt, VariantDef, Visibility};
 
 use rustc_type_ir::TyKind::*;
+use tracing::instrument;
 
 pub mod inhabited_predicate;
 
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index a08fde976bc..a887047f62f 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -14,6 +14,7 @@ use rustc_macros::{
 use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Symbol;
+use tracing::{debug, instrument};
 
 use std::assert_matches::assert_matches;
 use std::fmt;
@@ -763,7 +764,7 @@ impl<'tcx> Instance<'tcx> {
         self.def.has_polymorphic_mir_body().then_some(self.args)
     }
 
-    pub fn instantiate_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T
+    pub fn instantiate_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, &T>) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>> + Copy,
     {
@@ -781,7 +782,7 @@ impl<'tcx> Instance<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        v: EarlyBinder<T>,
+        v: EarlyBinder<'tcx, T>,
     ) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
@@ -799,7 +800,7 @@ impl<'tcx> Instance<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        v: EarlyBinder<T>,
+        v: EarlyBinder<'tcx, T>,
     ) -> Result<T, NormalizationError<'tcx>>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index cf701f837d8..60ce8744032 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -19,6 +19,7 @@ use rustc_target::abi::*;
 use rustc_target::spec::{
     abi::Abi as SpecAbi, HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi,
 };
+use tracing::debug;
 
 use std::borrow::Cow;
 use std::cmp;
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 8bb19bc85ac..f24074cb472 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -61,6 +61,7 @@ use rustc_span::{ExpnId, ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
 pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
+use tracing::{debug, instrument};
 pub use vtable::*;
 
 use std::assert_matches::assert_matches;
@@ -113,9 +114,9 @@ pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::{
     AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
     ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs,
-    CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs,
-    InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs,
-    VarianceDiagInfo,
+    CoroutineClosureArgsParts, CoroutineClosureSignature, EarlyBinder, FnSig, GenSig,
+    InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut,
+    UpvarArgs, VarianceDiagInfo,
 };
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
@@ -265,7 +266,7 @@ pub struct ImplHeader<'tcx> {
 
 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct ImplTraitHeader<'tcx> {
-    pub trait_ref: ty::EarlyBinder<ty::TraitRef<'tcx>>,
+    pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
     pub polarity: ImplPolarity,
     pub safety: hir::Safety,
 }
@@ -1814,6 +1815,11 @@ impl<'tcx> TyCtxt<'tcx> {
         self.get_attrs(did, attr).next().is_some()
     }
 
+    /// Determines whether an item is annotated with a multi-segement attribute
+    pub fn has_attrs_with_path(self, did: impl Into<DefId>, attrs: &[Symbol]) -> bool {
+        self.get_attrs_by_path(did.into(), attrs).next().is_some()
+    }
+
     /// Returns `true` if this is an `auto trait`.
     pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
         self.trait_def(trait_def_id).has_auto_impl
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 115cf3eeb22..fb16cf5bd36 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -11,6 +11,7 @@ use crate::traits::query::NoSolution;
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
 use crate::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use tracing::{debug, instrument};
 
 #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
 pub enum NormalizationError<'tcx> {
@@ -124,7 +125,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         param_args: GenericArgsRef<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        value: EarlyBinder<T>,
+        value: EarlyBinder<'tcx, T>,
     ) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
@@ -142,7 +143,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         param_args: GenericArgsRef<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        value: EarlyBinder<T>,
+        value: EarlyBinder<'tcx, T>,
     ) -> Result<T, NormalizationError<'tcx>>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index fa5265c58e4..bbcbcdce1b2 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -5,6 +5,7 @@ use crate::ty::{GenericArg, GenericArgKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
+use tracing::{debug, instrument, trace};
 
 /// Converts generic params of a TypeFoldable from one
 /// item's generics to another. Usually from a function's generics
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 571c6e918dc..f394b3c990c 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -33,8 +33,8 @@ impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::Binder<'static, T> {
     type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>;
 }
 
-impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::EarlyBinder<T> {
-    type Value<'tcx> = ty::EarlyBinder<T::Value<'tcx>>;
+impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::EarlyBinder<'static, T> {
+    type Value<'tcx> = ty::EarlyBinder<'tcx, T::Value<'tcx>>;
 }
 
 #[macro_export]
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index be91249a25f..c730f5117c5 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -1,15 +1,14 @@
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
 use rustc_hir::def_id::DefId;
-use rustc_macros::{
-    extension, HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
-};
+use rustc_macros::{extension, HashStable};
 use rustc_type_ir as ir;
 use std::cmp::Ordering;
+use tracing::instrument;
 
 use crate::ty::{
-    self, Binder, DebruijnIndex, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags,
-    Upcast, UpcastFrom, WithCachedTypeInfo,
+    self, DebruijnIndex, EarlyBinder, PredicatePolarity, Ty, TyCtxt, TypeFlags, Upcast, UpcastFrom,
+    WithCachedTypeInfo,
 };
 
 pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
@@ -24,6 +23,15 @@ pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>;
 pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>;
 pub type CoercePredicate<'tcx> = ir::CoercePredicate<TyCtxt<'tcx>>;
 pub type SubtypePredicate<'tcx> = ir::SubtypePredicate<TyCtxt<'tcx>>;
+pub type OutlivesPredicate<'tcx, T> = ir::OutlivesPredicate<TyCtxt<'tcx>, T>;
+pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, ty::Region<'tcx>>;
+pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, Ty<'tcx>>;
+pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
+pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
+pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
+pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
+pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
+pub type PolyProjectionPredicate<'tcx> = ty::Binder<'tcx, ProjectionPredicate<'tcx>>;
 
 /// A statement that can be proven by a trait solver. This includes things that may
 /// show up in where clauses, such as trait predicates and projection predicates,
@@ -113,17 +121,14 @@ impl<'tcx> Predicate<'tcx> {
     #[inline]
     pub fn allow_normalization(self) -> bool {
         match self.kind().skip_binder() {
-            PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
-            // `NormalizesTo` is only used in the new solver, so this shouldn't
-            // matter. Normalizing `term` would be 'wrong' however, as it changes whether
-            // `normalizes-to(<T as Trait>::Assoc, <T as Trait>::Assoc)` holds.
-            PredicateKind::NormalizesTo(..) => false,
+            PredicateKind::Clause(ClauseKind::WellFormed(_))
+            | PredicateKind::AliasRelate(..)
+            | PredicateKind::NormalizesTo(..) => false,
             PredicateKind::Clause(ClauseKind::Trait(_))
             | PredicateKind::Clause(ClauseKind::RegionOutlives(_))
             | PredicateKind::Clause(ClauseKind::TypeOutlives(_))
             | PredicateKind::Clause(ClauseKind::Projection(_))
             | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
-            | PredicateKind::AliasRelate(..)
             | PredicateKind::ObjectSafe(_)
             | PredicateKind::Subtype(_)
             | PredicateKind::Coerce(_)
@@ -155,6 +160,8 @@ pub struct Clause<'tcx>(
     pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
 );
 
+impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {}
+
 impl<'tcx> Clause<'tcx> {
     pub fn as_predicate(self) -> Predicate<'tcx> {
         Predicate(self.0)
@@ -231,34 +238,6 @@ impl<'tcx> ExistentialPredicate<'tcx> {
 
 pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>;
 
-impl<'tcx> PolyExistentialPredicate<'tcx> {
-    /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
-    /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
-    /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example).
-    pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> {
-        match self.skip_binder() {
-            ExistentialPredicate::Trait(tr) => {
-                self.rebind(tr).with_self_ty(tcx, self_ty).upcast(tcx)
-            }
-            ExistentialPredicate::Projection(p) => {
-                self.rebind(p.with_self_ty(tcx, self_ty)).upcast(tcx)
-            }
-            ExistentialPredicate::AutoTrait(did) => {
-                let generics = tcx.generics_of(did);
-                let trait_ref = if generics.own_params.len() == 1 {
-                    ty::TraitRef::new(tcx, did, [self_ty])
-                } else {
-                    // If this is an ill-formed auto trait, then synthesize
-                    // new error args for the missing generics.
-                    let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]);
-                    ty::TraitRef::new(tcx, did, err_args)
-                };
-                self.rebind(trait_ref).upcast(tcx)
-            }
-        }
-    }
-}
-
 impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
     /// Returns the "principal `DefId`" of this set of existential predicates.
     ///
@@ -322,49 +301,9 @@ impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
 }
 
 pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
-
-impl<'tcx> PolyTraitRef<'tcx> {
-    pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
-        self.map_bound_ref(|tr| tr.self_ty())
-    }
-
-    pub fn def_id(&self) -> DefId {
-        self.skip_binder().def_id
-    }
-}
-
 pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
-
-impl<'tcx> PolyExistentialTraitRef<'tcx> {
-    pub fn def_id(&self) -> DefId {
-        self.skip_binder().def_id
-    }
-
-    /// Object types don't have a self type specified. Therefore, when
-    /// we convert the principal trait-ref into a normal trait-ref,
-    /// you must give *some* self type. A common choice is `mk_err()`
-    /// or some placeholder type.
-    pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTraitRef<'tcx> {
-        self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty))
-    }
-}
-
 pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
 
-impl<'tcx> PolyExistentialProjection<'tcx> {
-    pub fn with_self_ty(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        self_ty: Ty<'tcx>,
-    ) -> ty::PolyProjectionPredicate<'tcx> {
-        self.map_bound(|p| p.with_self_ty(tcx, self_ty))
-    }
-
-    pub fn item_def_id(&self) -> DefId {
-        self.skip_binder().def_id
-    }
-}
-
 impl<'tcx> Clause<'tcx> {
     /// Performs a instantiation suitable for going from a
     /// poly-trait-ref to supertraits that must hold if that
@@ -471,73 +410,6 @@ impl<'tcx> Clause<'tcx> {
     }
 }
 
-pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
-
-impl<'tcx> PolyTraitPredicate<'tcx> {
-    pub fn def_id(self) -> DefId {
-        // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().def_id()
-    }
-
-    pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
-        self.map_bound(|trait_ref| trait_ref.self_ty())
-    }
-
-    #[inline]
-    pub fn polarity(self) -> PredicatePolarity {
-        self.skip_binder().polarity
-    }
-}
-
-/// `A: B`
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct OutlivesPredicate<A, B>(pub A, pub B);
-pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
-pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
-pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
-pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
-
-pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
-
-pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
-
-pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
-
-impl<'tcx> PolyProjectionPredicate<'tcx> {
-    /// Returns the `DefId` of the trait of the associated item being projected.
-    #[inline]
-    pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        self.skip_binder().projection_term.trait_def_id(tcx)
-    }
-
-    /// Get the [PolyTraitRef] required for this projection to be well formed.
-    /// Note that for generic associated types the predicates of the associated
-    /// type also need to be checked.
-    #[inline]
-    pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
-        // Note: unlike with `TraitRef::to_poly_trait_ref()`,
-        // `self.0.trait_ref` is permitted to have escaping regions.
-        // This is because here `self` has a `Binder` and so does our
-        // return value, so we are preserving the number of binding
-        // levels.
-        self.map_bound(|predicate| predicate.projection_term.trait_ref(tcx))
-    }
-
-    pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
-        self.map_bound(|predicate| predicate.term)
-    }
-
-    /// The `DefId` of the `TraitItem` for the associated type.
-    ///
-    /// Note that this is not the `DefId` of the `TraitRef` containing this
-    /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
-    pub fn projection_def_id(&self) -> DefId {
-        // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().projection_term.def_id
-    }
-}
-
 pub trait ToPolyTraitRef<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
 }
@@ -554,8 +426,8 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
     }
 }
 
-impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
-    fn upcast_from(from: Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
+    fn upcast_from(from: ty::Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
         tcx.mk_predicate(from)
     }
 }
@@ -566,8 +438,8 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> {
     }
 }
 
-impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
-    fn upcast_from(from: Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
+    fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
         tcx.mk_predicate(from.map_bound(PredicateKind::Clause))
     }
 }
@@ -580,12 +452,12 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> {
 
 impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> {
     fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
-        tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(from))).expect_clause()
+        tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))).expect_clause()
     }
 }
 
-impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
-    fn upcast_from(from: Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
+    fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
         tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause()
     }
 }
@@ -609,22 +481,22 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> {
     }
 }
 
-impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
-    fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
+    fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
         let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
         pred.upcast(tcx)
     }
 }
 
-impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
-    fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
+    fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
         let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
         pred.upcast(tcx)
     }
 }
 
-impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for PolyTraitPredicate<'tcx> {
-    fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, _tcx: TyCtxt<'tcx>) -> Self {
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for PolyTraitPredicate<'tcx> {
+    fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, _tcx: TyCtxt<'tcx>) -> Self {
         from.map_bound(|trait_ref| TraitPredicate {
             trait_ref,
             polarity: PredicatePolarity::Positive,
@@ -664,10 +536,8 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyRegionOutlivesPredicate<'tcx>> for Predi
     }
 }
 
-impl<'tcx> UpcastFrom<TyCtxt<'tcx>, OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>
-    for Predicate<'tcx>
-{
-    fn upcast_from(from: OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
+impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TypeOutlivesPredicate<'tcx>> for Predicate<'tcx> {
+    fn upcast_from(from: TypeOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
         ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(from))).upcast(tcx)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index dc77f59f3d0..3c27df9529a 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use tracing::{debug, instrument, trace};
 
 // `pretty` is a separate module only for organization.
 mod pretty;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 0dbb17e9db4..83790db9926 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1579,8 +1579,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 let formatted_op = match op {
                     UnOp::Not => "!",
                     UnOp::Neg => "-",
+                    UnOp::PtrMetadata => "PtrMetadata",
                 };
                 let parenthesized = match ct.kind() {
+                    _ if op == UnOp::PtrMetadata => true,
                     ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op,
                     ty::ConstKind::Expr(_) => true,
                     _ => false,
@@ -2860,10 +2862,9 @@ where
     }
 }
 
-impl<'tcx, T, U, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate<T, U>
+impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate<'tcx, T>
 where
     T: Print<'tcx, P>,
-    U: Print<'tcx, P>,
 {
     fn print(&self, cx: &mut P) -> Result<(), PrintError> {
         define_scoped_cx!(cx);
@@ -2934,12 +2935,13 @@ impl<'tcx> ty::TraitRef<'tcx> {
     }
 }
 
+#[extension(pub trait PrintPolyTraitRefExt<'tcx>)]
 impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
-    pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> {
+    fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> {
         self.map_bound(|tr| tr.print_only_trait_path())
     }
 
-    pub fn print_trait_sugared(self) -> ty::Binder<'tcx, TraitRefPrintSugared<'tcx>> {
+    fn print_trait_sugared(self) -> ty::Binder<'tcx, TraitRefPrintSugared<'tcx>> {
         self.map_bound(|tr| tr.print_trait_sugared())
     }
 }
@@ -2960,8 +2962,9 @@ impl<'tcx> ty::TraitPredicate<'tcx> {
     }
 }
 
+#[extension(pub trait PrintPolyTraitPredicateExt<'tcx>)]
 impl<'tcx> ty::PolyTraitPredicate<'tcx> {
-    pub fn print_modifiers_and_trait_path(
+    fn print_modifiers_and_trait_path(
         self,
     ) -> ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>> {
         self.map_bound(TraitPredPrintModifiersAndPath)
@@ -3014,21 +3017,7 @@ forward_display_to_print! {
     ty::Region<'tcx>,
     Ty<'tcx>,
     &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ty::Const<'tcx>,
-
-    // HACK(eddyb) these are exhaustive instead of generic,
-    // because `for<'tcx>` isn't possible yet.
-    ty::PolyExistentialProjection<'tcx>,
-    ty::PolyExistentialTraitRef<'tcx>,
-    ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-    ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
-    ty::Binder<'tcx, TraitRefPrintSugared<'tcx>>,
-    ty::Binder<'tcx, ty::FnSig<'tcx>>,
-    ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
-    ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>,
-    ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
-    ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
-    ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
+    ty::Const<'tcx>
 }
 
 define_print! {
@@ -3271,7 +3260,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
     let queue = &mut Vec::new();
     let mut seen_defs: DefIdSet = Default::default();
 
-    for &cnum in tcx.crates(()).iter() {
+    for &cnum in tcx.crates_including_speculative(()).iter() {
         let def_id = cnum.as_def_id();
 
         // Ignore crates that are not direct dependencies.
@@ -3327,7 +3316,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
 ///
 /// The implementation uses similar import discovery logic to that of 'use' suggestions.
 ///
-/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
+/// See also [`with_no_trimmed_paths!`].
 // this is pub to be able to intra-doc-link it
 pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
     // Trimming paths is expensive and not optimized, since we expect it to only be used for error
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index 551e2ea2295..4e85af90170 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -8,6 +8,7 @@ use rustc_span::{ErrorGuaranteed, DUMMY_SP};
 use rustc_type_ir::RegionKind as IrRegionKind;
 pub use rustc_type_ir::RegionVid;
 use std::ops::Deref;
+use tracing::debug;
 
 use crate::ty::{self, BoundVar, TyCtxt, TypeFlags};
 
@@ -137,6 +138,14 @@ impl<'tcx> Region<'tcx> {
 }
 
 impl<'tcx> rustc_type_ir::inherent::Region<TyCtxt<'tcx>> for Region<'tcx> {
+    fn new_bound(
+        interner: TyCtxt<'tcx>,
+        debruijn: ty::DebruijnIndex,
+        var: ty::BoundRegion,
+    ) -> Self {
+        Region::new_bound(interner, debruijn, var)
+    }
+
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
         Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon })
     }
@@ -264,33 +273,6 @@ impl<'tcx> Region<'tcx> {
         flags
     }
 
-    /// Given an early-bound or free region, returns the `DefId` where it was bound.
-    /// For example, consider the regions in this snippet of code:
-    ///
-    /// ```ignore (illustrative)
-    /// impl<'a> Foo {
-    /// //   ^^ -- early bound, declared on an impl
-    ///
-    ///     fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c
-    /// //         ^^  ^^     ^ anonymous, late-bound
-    /// //         |   early-bound, appears in where-clauses
-    /// //         late-bound, appears only in fn args
-    ///     {..}
-    /// }
-    /// ```
-    ///
-    /// Here, `free_region_binding_scope('a)` would return the `DefId`
-    /// of the impl, and for all the other highlighted regions, it
-    /// would return the `DefId` of the function. In other cases (not shown), this
-    /// function might return the `DefId` of a closure.
-    pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId {
-        match *self {
-            ty::ReEarlyParam(br) => tcx.parent(br.def_id),
-            ty::ReLateParam(fr) => fr.scope,
-            _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self),
-        }
-    }
-
     /// True for free regions other than `'static`.
     pub fn is_param(self) -> bool {
         matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_))
@@ -320,6 +302,21 @@ impl<'tcx> Region<'tcx> {
             _ => bug!("expected region {:?} to be of kind ReVar", self),
         }
     }
+
+    /// Given some item `binding_item`, check if this region is a generic parameter introduced by it
+    /// or one of the parent generics. Returns the `DefId` of the parameter definition if so.
+    pub fn opt_param_def_id(self, tcx: TyCtxt<'tcx>, binding_item: DefId) -> Option<DefId> {
+        match self.kind() {
+            ty::ReEarlyParam(ebr) => {
+                Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id)
+            }
+            ty::ReLateParam(ty::LateParamRegion {
+                bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
+                ..
+            }) => Some(def_id),
+            _ => None,
+        }
+    }
 }
 
 impl<'tcx> Deref for Region<'tcx> {
@@ -334,16 +331,19 @@ impl<'tcx> Deref for Region<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct EarlyParamRegion {
-    pub def_id: DefId,
     pub index: u32,
     pub name: Symbol,
 }
 
+impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion {
+    fn index(self) -> u32 {
+        self.index
+    }
+}
+
 impl std::fmt::Debug for EarlyParamRegion {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        // FIXME(BoxyUwU): self.def_id goes first because of `erased-regions-in-hidden-ty.rs` being impossible to write
-        // error annotations for otherwise. :). Ideally this would be `self.name, self.index, self.def_id`.
-        write!(f, "{:?}_{}/#{}", self.def_id, self.name, self.index)
+        write!(f, "{}/#{}", self.name, self.index)
     }
 }
 
@@ -351,6 +351,12 @@ impl std::fmt::Debug for EarlyParamRegion {
 #[derive(HashStable)]
 /// The parameter representation of late-bound function parameters, "some region
 /// at least as big as the scope `fr.scope`".
+///
+/// Similar to a placeholder region as we create `LateParam` regions when entering a binder
+/// except they are always in the root universe and instead of using a boundvar to distinguish
+/// between others we use the `DefId` of the parameter. For this reason the `bound_region` field
+/// should basically always be `BoundRegionKind::BrNamed` as otherwise there is no way of telling
+/// different parameters apart.
 pub struct LateParamRegion {
     pub scope: DefId,
     pub bound_region: BoundRegionKind,
@@ -384,6 +390,10 @@ impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundRegion {
     fn var(self) -> BoundVar {
         self.var
     }
+
+    fn assert_eq(self, var: ty::BoundVariableKind) {
+        assert_eq!(self.kind, var.expect_region())
+    }
 }
 
 impl core::fmt::Debug for BoundRegion {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 947de3f3aaa..f02b4849f83 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -14,6 +14,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::TypeVisitable;
 use rustc_target::spec::abi;
 use std::iter;
+use tracing::{debug, instrument};
 
 use super::Pattern;
 
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index cb2f7284eaa..8ec7946e718 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -2,6 +2,7 @@ use crate::middle::region::{Scope, ScopeData, ScopeTree};
 use rustc_hir as hir;
 use rustc_hir::ItemLocalMap;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use tracing::debug;
 
 /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by
 /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`.
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 81d92a2a448..af3aa3b56f7 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -387,38 +387,6 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
     }
 }
 
-impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
-    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
-        self,
-        folder: &mut F,
-    ) -> Result<Self, F::Error> {
-        folder.try_fold_binder(self)
-    }
-}
-
-impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
-        visitor.visit_binder(self)
-    }
-}
-
-impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
-    fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
-        self,
-        folder: &mut F,
-    ) -> Result<Self, F::Error> {
-        self.try_map_bound(|ty| ty.try_fold_with(folder))
-    }
-}
-
-impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeSuperVisitable<TyCtxt<'tcx>>
-    for ty::Binder<'tcx, T>
-{
-    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
-        self.as_ref().skip_binder().visit_with(visitor)
-    }
-}
-
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
     fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
         self,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 2d9d178449e..5cf96d29837 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -3,17 +3,16 @@
 #![allow(rustc::usage_of_ty_tykind)]
 
 use crate::infer::canonical::Canonical;
-use crate::ty::visit::ValidateBoundVars;
 use crate::ty::InferTy::*;
 use crate::ty::{
     self, AdtDef, BoundRegionKind, Discr, Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor,
+    TypeVisitable, TypeVisitor,
 };
 use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use crate::ty::{List, ParamEnv};
 use hir::def::{CtorKind, DefKind};
 use rustc_data_structures::captures::Captures;
-use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagArg, MultiSpan};
+use rustc_errors::{ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
@@ -21,11 +20,11 @@ use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
-use rustc_target::spec::abi::{self, Abi};
+use rustc_target::spec::abi;
 use std::assert_matches::debug_assert_matches;
 use std::borrow::Cow;
 use std::iter;
-use std::ops::{ControlFlow, Deref, Range};
+use std::ops::{ControlFlow, Range};
 use ty::util::IntTypeExt;
 
 use rustc_type_ir::TyKind::*;
@@ -40,6 +39,8 @@ pub type TyKind<'tcx> = ir::TyKind<TyCtxt<'tcx>>;
 pub type TypeAndMut<'tcx> = ir::TypeAndMut<TyCtxt<'tcx>>;
 pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>;
 pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>;
+pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
+pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
 
 pub trait Article {
     fn article(&self) -> &'static str;
@@ -373,7 +374,7 @@ impl<'tcx> CoroutineClosureArgs<'tcx> {
         self.split().signature_parts_ty
     }
 
-    pub fn coroutine_closure_sig(self) -> ty::Binder<'tcx, CoroutineClosureSignature<'tcx>> {
+    pub fn coroutine_closure_sig(self) -> Binder<'tcx, CoroutineClosureSignature<'tcx>> {
         let interior = self.coroutine_witness_ty();
         let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { bug!() };
         sig.map_bound(|sig| {
@@ -401,6 +402,45 @@ impl<'tcx> CoroutineClosureArgs<'tcx> {
     pub fn coroutine_witness_ty(self) -> Ty<'tcx> {
         self.split().coroutine_witness_ty
     }
+
+    pub fn has_self_borrows(&self) -> bool {
+        match self.coroutine_captures_by_ref_ty().kind() {
+            ty::FnPtr(sig) => sig
+                .skip_binder()
+                .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
+                .is_break(),
+            ty::Error(_) => true,
+            _ => bug!(),
+        }
+    }
+}
+/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will
+/// detect only regions bound *at* the debruijn index.
+struct HasRegionsBoundAt {
+    binder: ty::DebruijnIndex,
+}
+// FIXME: Could be optimized to not walk into components with no escaping bound vars.
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRegionsBoundAt {
+    type Result = ControlFlow<()>;
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
+        &mut self,
+        t: &ty::Binder<'tcx, T>,
+    ) -> Self::Result {
+        self.binder.shift_in(1);
+        t.super_visit_with(self)?;
+        self.binder.shift_out(1);
+        ControlFlow::Continue(())
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
+        if let ty::ReBound(binder, _) = *r
+            && self.binder == binder
+        {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::Continue(())
+        }
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
@@ -898,203 +938,6 @@ impl BoundVariableKind {
     }
 }
 
-/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
-/// compiler's representation for things like `for<'a> Fn(&'a isize)`
-/// (which would be represented by the type `PolyTraitRef ==
-/// Binder<'tcx, TraitRef>`). Note that when we instantiate,
-/// erase, or otherwise "discharge" these bound vars, we change the
-/// type from `Binder<'tcx, T>` to just `T` (see
-/// e.g., `liberate_late_bound_regions`).
-///
-/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-#[derive(HashStable, Lift)]
-pub struct Binder<'tcx, T> {
-    value: T,
-    bound_vars: &'tcx List<BoundVariableKind>,
-}
-
-impl<'tcx, T> Binder<'tcx, T>
-where
-    T: TypeVisitable<TyCtxt<'tcx>>,
-{
-    /// Wraps `value` in a binder, asserting that `value` does not
-    /// contain any bound vars that would be bound by the
-    /// binder. This is commonly used to 'inject' a value T into a
-    /// different binding level.
-    #[track_caller]
-    pub fn dummy(value: T) -> Binder<'tcx, T> {
-        assert!(
-            !value.has_escaping_bound_vars(),
-            "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
-        );
-        Binder { value, bound_vars: ty::List::empty() }
-    }
-
-    pub fn bind_with_vars(value: T, bound_vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
-        if cfg!(debug_assertions) {
-            let mut validator = ValidateBoundVars::new(bound_vars);
-            value.visit_with(&mut validator);
-        }
-        Binder { value, bound_vars }
-    }
-}
-
-impl<'tcx, T> rustc_type_ir::inherent::BoundVars<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
-    fn bound_vars(&self) -> &'tcx List<ty::BoundVariableKind> {
-        self.bound_vars
-    }
-
-    fn has_no_bound_vars(&self) -> bool {
-        self.bound_vars.is_empty()
-    }
-}
-
-impl<'tcx, T> Binder<'tcx, T> {
-    /// Skips the binder and returns the "bound" value. This is a
-    /// risky thing to do because it's easy to get confused about
-    /// De Bruijn indices and the like. It is usually better to
-    /// discharge the binder using `no_bound_vars` or
-    /// `instantiate_bound_regions` or something like
-    /// that. `skip_binder` is only valid when you are either
-    /// extracting data that has nothing to do with bound vars, you
-    /// are doing some sort of test that does not involve bound
-    /// regions, or you are being very careful about your depth
-    /// accounting.
-    ///
-    /// Some examples where `skip_binder` is reasonable:
-    ///
-    /// - extracting the `DefId` from a PolyTraitRef;
-    /// - comparing the self type of a PolyTraitRef to see if it is equal to
-    ///   a type parameter `X`, since the type `X` does not reference any regions
-    pub fn skip_binder(self) -> T {
-        self.value
-    }
-
-    pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> {
-        self.bound_vars
-    }
-
-    pub fn as_ref(&self) -> Binder<'tcx, &T> {
-        Binder { value: &self.value, bound_vars: self.bound_vars }
-    }
-
-    pub fn as_deref(&self) -> Binder<'tcx, &T::Target>
-    where
-        T: Deref,
-    {
-        Binder { value: &self.value, bound_vars: self.bound_vars }
-    }
-
-    pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U>
-    where
-        F: FnOnce(&T) -> U,
-    {
-        self.as_ref().map_bound(f)
-    }
-
-    pub fn map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>>(self, f: F) -> Binder<'tcx, U>
-    where
-        F: FnOnce(T) -> U,
-    {
-        let Binder { value, bound_vars } = self;
-        let value = f(value);
-        if cfg!(debug_assertions) {
-            let mut validator = ValidateBoundVars::new(bound_vars);
-            value.visit_with(&mut validator);
-        }
-        Binder { value, bound_vars }
-    }
-
-    pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>(
-        self,
-        f: F,
-    ) -> Result<Binder<'tcx, U>, E>
-    where
-        F: FnOnce(T) -> Result<U, E>,
-    {
-        let Binder { value, bound_vars } = self;
-        let value = f(value)?;
-        if cfg!(debug_assertions) {
-            let mut validator = ValidateBoundVars::new(bound_vars);
-            value.visit_with(&mut validator);
-        }
-        Ok(Binder { value, bound_vars })
-    }
-
-    /// Wraps a `value` in a binder, using the same bound variables as the
-    /// current `Binder`. This should not be used if the new value *changes*
-    /// the bound variables. Note: the (old or new) value itself does not
-    /// necessarily need to *name* all the bound variables.
-    ///
-    /// This currently doesn't do anything different than `bind`, because we
-    /// don't actually track bound vars. However, semantically, it is different
-    /// because bound vars aren't allowed to change here, whereas they are
-    /// in `bind`. This may be (debug) asserted in the future.
-    pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
-    where
-        U: TypeVisitable<TyCtxt<'tcx>>,
-    {
-        Binder::bind_with_vars(value, self.bound_vars)
-    }
-
-    /// Unwraps and returns the value within, but only if it contains
-    /// no bound vars at all. (In other words, if this binder --
-    /// and indeed any enclosing binder -- doesn't bind anything at
-    /// all.) Otherwise, returns `None`.
-    ///
-    /// (One could imagine having a method that just unwraps a single
-    /// binder, but permits late-bound vars bound by enclosing
-    /// binders, but that would require adjusting the debruijn
-    /// indices, and given the shallow binding structure we often use,
-    /// would not be that useful.)
-    pub fn no_bound_vars(self) -> Option<T>
-    where
-        T: TypeVisitable<TyCtxt<'tcx>>,
-    {
-        // `self.value` is equivalent to `self.skip_binder()`
-        if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
-    }
-
-    /// Splits the contents into two things that share the same binder
-    /// level as the original, returning two distinct binders.
-    ///
-    /// `f` should consider bound regions at depth 1 to be free, and
-    /// anything it produces with bound regions at depth 1 will be
-    /// bound in the resulting return values.
-    pub fn split<U, V, F>(self, f: F) -> (Binder<'tcx, U>, Binder<'tcx, V>)
-    where
-        F: FnOnce(T) -> (U, V),
-    {
-        let Binder { value, bound_vars } = self;
-        let (u, v) = f(value);
-        (Binder { value: u, bound_vars }, Binder { value: v, bound_vars })
-    }
-}
-
-impl<'tcx, T> Binder<'tcx, Option<T>> {
-    pub fn transpose(self) -> Option<Binder<'tcx, T>> {
-        let Binder { value, bound_vars } = self;
-        value.map(|value| Binder { value, bound_vars })
-    }
-}
-
-impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
-    pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
-        let Binder { value, bound_vars } = self;
-        value.into_iter().map(|value| Binder { value, bound_vars })
-    }
-}
-
-impl<'tcx, T> IntoDiagArg for Binder<'tcx, T>
-where
-    T: IntoDiagArg,
-{
-    fn into_diag_arg(self) -> DiagArgValue {
-        self.value.into_diag_arg()
-    }
-}
-
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
 pub struct GenSig<'tcx> {
     pub resume_ty: Ty<'tcx>,
@@ -1103,48 +946,6 @@ pub struct GenSig<'tcx> {
 }
 
 pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
-
-impl<'tcx> PolyFnSig<'tcx> {
-    #[inline]
-    pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> {
-        self.map_bound_ref(|fn_sig| fn_sig.inputs())
-    }
-
-    #[inline]
-    #[track_caller]
-    pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> {
-        self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
-    }
-
-    pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List<Ty<'tcx>>> {
-        self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output)
-    }
-
-    #[inline]
-    pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
-        self.map_bound_ref(|fn_sig| fn_sig.output())
-    }
-
-    pub fn c_variadic(&self) -> bool {
-        self.skip_binder().c_variadic
-    }
-
-    pub fn safety(&self) -> hir::Safety {
-        self.skip_binder().safety
-    }
-
-    pub fn abi(&self) -> abi::Abi {
-        self.skip_binder().abi
-    }
-
-    pub fn is_fn_trait_compatible(&self) -> bool {
-        matches!(
-            self.skip_binder(),
-            ty::FnSig { safety: rustc_hir::Safety::Safe, abi: Abi::Rust, c_variadic: false, .. }
-        )
-    }
-}
-
 pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>;
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
@@ -1154,6 +955,12 @@ pub struct ParamTy {
     pub name: Symbol,
 }
 
+impl rustc_type_ir::inherent::ParamLike for ParamTy {
+    fn index(self) -> u32 {
+        self.index
+    }
+}
+
 impl<'tcx> ParamTy {
     pub fn new(index: u32, name: Symbol) -> ParamTy {
         ParamTy { index, name }
@@ -1182,6 +989,12 @@ pub struct ParamConst {
     pub name: Symbol,
 }
 
+impl rustc_type_ir::inherent::ParamLike for ParamConst {
+    fn index(self) -> u32 {
+        self.index
+    }
+}
+
 impl ParamConst {
     pub fn new(index: u32, name: Symbol) -> ParamConst {
         ParamConst { index, name }
@@ -1203,6 +1016,10 @@ impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundTy {
     fn var(self) -> BoundVar {
         self.var
     }
+
+    fn assert_eq(self, var: ty::BoundVariableKind) {
+        assert_eq!(self.kind, var.expect_ty())
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
@@ -1619,6 +1436,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
         Ty::new_var(tcx, vid)
     }
 
+    fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self {
+        Ty::new_bound(interner, debruijn, var)
+    }
+
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
         Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
     }
@@ -2001,7 +1822,7 @@ impl<'tcx> Ty<'tcx> {
             FnPtr(f) => *f,
             Error(_) => {
                 // ignore errors (#54954)
-                ty::Binder::dummy(ty::FnSig {
+                Binder::dummy(ty::FnSig {
                     inputs_and_output: ty::List::empty(),
                     c_variadic: false,
                     safety: hir::Safety::Safe,
@@ -2251,7 +2072,7 @@ impl<'tcx> Ty<'tcx> {
     fn async_destructor_combinator(
         tcx: TyCtxt<'tcx>,
         lang_item: LangItem,
-    ) -> ty::EarlyBinder<Ty<'tcx>> {
+    ) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
         tcx.fn_sig(tcx.require_lang_item(lang_item, None))
             .map_bound(|fn_sig| fn_sig.output().no_bound_vars().unwrap())
     }
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index c5b3de17bcb..37a34f28338 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -5,6 +5,7 @@ use hir::def_id::LOCAL_CRATE;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use std::iter;
+use tracing::debug;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::ErrorGuaranteed;
@@ -39,11 +40,16 @@ pub struct TraitDef {
     /// also have already switched to the new trait solver.
     pub is_coinductive: bool,
 
-    /// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]`
+    /// If `true`, then this trait has the `#[rustc_skip_during_method_dispatch(array)]`
     /// attribute, indicating that editions before 2021 should not consider this trait
     /// during method dispatch if the receiver is an array.
     pub skip_array_during_method_dispatch: bool,
 
+    /// If `true`, then this trait has the `#[rustc_skip_during_method_dispatch(boxed_slice)]`
+    /// attribute, indicating that editions before 2024 should not consider this trait
+    /// during method dispatch if the receiver is a boxed slice.
+    pub skip_boxed_slice_during_method_dispatch: bool,
+
     /// Used to determine whether the standard library is allowed to specialize
     /// on this trait.
     pub specialization_kind: TraitSpecializationKind,
@@ -200,7 +206,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
     // Traits defined in the current crate can't have impls in upstream
     // crates, so we don't bother querying the cstore.
     if !trait_id.is_local() {
-        for &cnum in tcx.crates(()).iter() {
+        for &cnum in tcx.used_crates(()).iter() {
             for &(impl_def_id, simplified_self_ty) in
                 tcx.implementations_of_trait((cnum, trait_id)).iter()
             {
@@ -242,7 +248,7 @@ pub(super) fn incoherent_impls_provider(
     let mut impls = Vec::new();
 
     let mut res = Ok(());
-    for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
+    for cnum in iter::once(LOCAL_CRATE).chain(tcx.used_crates(()).iter().copied()) {
         let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) {
             Ok(impls) => impls,
             Err(e) => {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 24e3e623ff2..69ea9c9843a 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -217,6 +217,10 @@ pub struct TypeckResults<'tcx> {
 
     /// Container types and field indices of `offset_of!` expressions
     offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
+
+    /// Maps from `HirId`s of const blocks (the `ExprKind::ConstBlock`, not the inner expression's)
+    /// to the `DefId` of the corresponding inline const.
+    pub inline_consts: FxIndexMap<ItemLocalId, LocalDefId>,
 }
 
 impl<'tcx> TypeckResults<'tcx> {
@@ -249,6 +253,7 @@ impl<'tcx> TypeckResults<'tcx> {
             treat_byte_string_as_slice: Default::default(),
             closure_size_eval: Default::default(),
             offset_of_data: Default::default(),
+            inline_consts: Default::default(),
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 8c14f1e080a..cacaa859d52 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -24,6 +24,7 @@ use rustc_target::abi::{Float, Integer, IntegerType, Size};
 use rustc_target::spec::abi::Abi;
 use smallvec::{smallvec, SmallVec};
 use std::{fmt, iter};
+use tracing::{debug, instrument, trace};
 
 #[derive(Copy, Clone, Debug)]
 pub struct Discr<'tcx> {
@@ -693,7 +694,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn coroutine_hidden_types(
         self,
         def_id: DefId,
-    ) -> impl Iterator<Item = ty::EarlyBinder<Ty<'tcx>>> {
+    ) -> impl Iterator<Item = ty::EarlyBinder<'tcx, Ty<'tcx>>> {
         let coroutine_layout = self.mir_coroutine_witnesses(def_id);
         coroutine_layout
             .as_ref()
@@ -708,7 +709,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn bound_coroutine_hidden_types(
         self,
         def_id: DefId,
-    ) -> impl Iterator<Item = ty::EarlyBinder<ty::Binder<'tcx, Ty<'tcx>>>> {
+    ) -> impl Iterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'tcx, Ty<'tcx>>>> {
         let coroutine_layout = self.mir_coroutine_witnesses(def_id);
         coroutine_layout
             .as_ref()
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 218567bbd59..b1bbfd420e1 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -1,7 +1,6 @@
 use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::sso::SsoHashSet;
 use rustc_type_ir::fold::TypeFoldable;
 use std::ops::ControlFlow;
 
@@ -145,103 +144,6 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
-pub struct ValidateBoundVars<'tcx> {
-    bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
-    binder_index: ty::DebruijnIndex,
-    // We may encounter the same variable at different levels of binding, so
-    // this can't just be `Ty`
-    visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
-}
-
-impl<'tcx> ValidateBoundVars<'tcx> {
-    pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
-        ValidateBoundVars {
-            bound_vars,
-            binder_index: ty::INNERMOST,
-            visited: SsoHashSet::default(),
-        }
-    }
-}
-
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
-    type Result = ControlFlow<()>;
-
-    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: &Binder<'tcx, T>,
-    ) -> Self::Result {
-        self.binder_index.shift_in(1);
-        let result = t.super_visit_with(self);
-        self.binder_index.shift_out(1);
-        result
-    }
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
-        if t.outer_exclusive_binder() < self.binder_index
-            || !self.visited.insert((self.binder_index, t))
-        {
-            return ControlFlow::Break(());
-        }
-        match *t.kind() {
-            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
-                if self.bound_vars.len() <= bound_ty.var.as_usize() {
-                    bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
-                }
-                let list_var = self.bound_vars[bound_ty.var.as_usize()];
-                match list_var {
-                    ty::BoundVariableKind::Ty(kind) => {
-                        if kind != bound_ty.kind {
-                            bug!(
-                                "Mismatched type kinds: {:?} doesn't var in list {:?}",
-                                bound_ty.kind,
-                                list_var
-                            );
-                        }
-                    }
-                    _ => {
-                        bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var)
-                    }
-                }
-            }
-
-            _ => (),
-        };
-
-        t.super_visit_with(self)
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
-        match *r {
-            ty::ReBound(index, br) if index == self.binder_index => {
-                if self.bound_vars.len() <= br.var.as_usize() {
-                    bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars);
-                }
-                let list_var = self.bound_vars[br.var.as_usize()];
-                match list_var {
-                    ty::BoundVariableKind::Region(kind) => {
-                        if kind != br.kind {
-                            bug!(
-                                "Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})",
-                                br.kind,
-                                list_var,
-                                self.bound_vars
-                            );
-                        }
-                    }
-                    _ => bug!(
-                        "Mismatched bound variable kinds! Expected region, found {:?}",
-                        list_var
-                    ),
-                }
-            }
-
-            _ => (),
-        };
-
-        ControlFlow::Continue(())
-    }
-}
-
 /// Collects all the late-bound regions at the innermost binding level
 /// into a hash set.
 struct LateBoundRegionsCollector {
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 2ad19431310..b8371cc2bca 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -84,10 +84,14 @@ pub(super) fn vtable_allocation_provider<'tcx>(
         let idx: u64 = u64::try_from(idx).unwrap();
         let scalar = match entry {
             VtblEntry::MetadataDropInPlace => {
-                let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
-                let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance);
-                let fn_ptr = Pointer::from(fn_alloc_id);
-                Scalar::from_pointer(fn_ptr, &tcx)
+                if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) {
+                    let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
+                    let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance);
+                    let fn_ptr = Pointer::from(fn_alloc_id);
+                    Scalar::from_pointer(fn_ptr, &tcx)
+                } else {
+                    Scalar::from_maybe_pointer(Pointer::null(), &tcx)
+                }
             }
             VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size),
             VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size),
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 089e61749c3..a9421aacff8 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -5,6 +5,7 @@ use crate::ty::{self, Ty};
 use crate::ty::{GenericArg, GenericArgKind};
 use rustc_data_structures::sso::SsoHashSet;
 use smallvec::{smallvec, SmallVec};
+use tracing::debug;
 
 // The TypeWalker's stack is hot enough that it's worth going to some effort to
 // avoid heap allocations.
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index 4e2a2c6ae0a..a4cbfe86711 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -8,6 +8,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{lang_items, LangItem};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, DesugaringKind, Span};
+use tracing::debug;
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub enum CallDesugaringKind {
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index 0ca4fce5da9..027e2703e98 100644
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -3,6 +3,7 @@ use crate::ty::GenericArgsRef;
 use crate::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::source_map::Spanned;
+use tracing::debug;
 
 /// Checks if the specified `local` is used as the `self` parameter of a method call
 /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 79f36cfe569..4ae475d35d1 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -23,7 +23,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for Result<ty::EarlyBinder<Ty<'_>>, CyclePlaceholder> {
+impl<'tcx> Value<TyCtxt<'tcx>> for Result<ty::EarlyBinder<'_, Ty<'_>>, CyclePlaceholder> {
     fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self {
         Err(CyclePlaceholder(guar))
     }
@@ -111,7 +111,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<Ty<'_>> {
+impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<'_, Ty<'_>> {
     fn from_cycle_error(
         tcx: TyCtxt<'tcx>,
         cycle_error: &CycleError,
@@ -121,7 +121,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<Ty<'_>> {
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>> {
+impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig<'_>>> {
     fn from_cycle_error(
         tcx: TyCtxt<'tcx>,
         cycle_error: &CycleError,