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/dep_graph/dep_node.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs66
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs6
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs14
-rw-r--r--compiler/rustc_middle/src/lint.rs13
-rw-r--r--compiler/rustc_middle/src/macros.rs18
-rw-r--r--compiler/rustc_middle/src/middle/region.rs5
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs4
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs42
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs44
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/mir/query.rs7
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs19
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs58
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs22
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs2
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs8
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_middle/src/thir.rs5
-rw-r--r--compiler/rustc_middle/src/traits/chalk.rs65
-rw-r--r--compiler/rustc_middle/src/traits/query.rs13
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs9
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs5
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs2
-rw-r--r--compiler/rustc_middle/src/ty/error.rs2
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs18
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs8
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs67
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs41
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs8
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs6
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs19
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs10
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs10
-rw-r--r--compiler/rustc_middle/src/ty/util.rs13
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs26
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs2
-rw-r--r--compiler/rustc_middle/src/util/bug.rs3
-rw-r--r--compiler/rustc_middle/src/values.rs23
43 files changed, 368 insertions, 335 deletions
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 6b556826918..865bb70afb5 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -175,7 +175,7 @@ impl DepNodeExt for DepNode {
     /// DepNode. Condition (2) might not be fulfilled if a DepNode
     /// refers to something from the previous compilation session that
     /// has been removed.
-    fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
+    fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
         if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
             Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || {
                 panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash)
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 0450abed51b..883554f959c 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -18,7 +18,7 @@ use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 #[inline]
-pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
+pub fn associated_body(node: Node<'_>) -> Option<BodyId> {
     match node {
         Node::Item(Item {
             kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
@@ -41,7 +41,7 @@ pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
     }
 }
 
-fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool {
+fn is_body_owner(node: Node<'_>, hir_id: HirId) -> bool {
     match associated_body(node) {
         Some(b) => b.hir_id == hir_id,
         None => false,
@@ -69,7 +69,7 @@ impl<'hir> Iterator for ParentHirIterator<'hir> {
         }
         loop {
             // There are nodes that do not have entries, so we need to skip them.
-            let parent_id = self.map.get_parent_node(self.current_id);
+            let parent_id = self.map.parent_id(self.current_id);
 
             if parent_id == self.current_id {
                 self.current_id = CRATE_HIR_ID;
@@ -170,6 +170,7 @@ impl<'hir> Map<'hir> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn local_def_id(self, hir_id: HirId) -> LocalDefId {
         self.opt_local_def_id(hir_id).unwrap_or_else(|| {
             bug!(
@@ -245,7 +246,7 @@ impl<'hir> Map<'hir> {
             },
             Node::Variant(_) => DefKind::Variant,
             Node::Ctor(variant_data) => {
-                let ctor_of = match self.find(self.get_parent_node(hir_id)) {
+                let ctor_of = match self.find_parent(hir_id) {
                     Some(Node::Item(..)) => def::CtorOf::Struct,
                     Some(Node::Variant(..)) => def::CtorOf::Variant,
                     _ => unreachable!(),
@@ -256,7 +257,7 @@ impl<'hir> Map<'hir> {
                 }
             }
             Node::AnonConst(_) => {
-                let inline = match self.find(self.get_parent_node(hir_id)) {
+                let inline = match self.find_parent(hir_id) {
                     Some(Node::Expr(&Expr {
                         kind: ExprKind::ConstBlock(ref anon_const), ..
                     })) if anon_const.hir_id == hir_id => true,
@@ -297,7 +298,7 @@ impl<'hir> Map<'hir> {
     /// Finds the id of the parent node to this one.
     ///
     /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
-    pub fn find_parent_node(self, id: HirId) -> Option<HirId> {
+    pub fn opt_parent_id(self, id: HirId) -> Option<HirId> {
         if id.local_id == ItemLocalId::from_u32(0) {
             Some(self.tcx.hir_owner_parent(id.owner))
         } else {
@@ -310,11 +311,20 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    pub fn get_parent_node(self, hir_id: HirId) -> HirId {
-        self.find_parent_node(hir_id)
+    #[track_caller]
+    pub fn parent_id(self, hir_id: HirId) -> HirId {
+        self.opt_parent_id(hir_id)
             .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
     }
 
+    pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
+        self.get(self.parent_id(hir_id))
+    }
+
+    pub fn find_parent(self, hir_id: HirId) -> Option<Node<'hir>> {
+        self.find(self.opt_parent_id(hir_id)?)
+    }
+
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
     pub fn find(self, id: HirId) -> Option<Node<'hir>> {
         if id.local_id == ItemLocalId::from_u32(0) {
@@ -334,12 +344,14 @@ impl<'hir> Map<'hir> {
     }
 
     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
+    #[track_caller]
     pub fn get(self, id: HirId) -> Node<'hir> {
         self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id))
     }
 
     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
     #[inline]
+    #[track_caller]
     pub fn get_by_def_id(self, id: LocalDefId) -> Node<'hir> {
         self.find_by_def_id(id).unwrap_or_else(|| bug!("couldn't find {:?} in the HIR map", id))
     }
@@ -377,6 +389,7 @@ impl<'hir> Map<'hir> {
         self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id]
     }
 
+    #[track_caller]
     pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
         if let Some(node) = self.find(hir_id) {
             node.fn_decl()
@@ -385,6 +398,7 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    #[track_caller]
     pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
         if let Some(node) = self.find(hir_id) {
             node.fn_sig()
@@ -393,6 +407,7 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    #[track_caller]
     pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
         for (_, node) in self.parent_iter(hir_id) {
             if let Some(body) = associated_body(node) {
@@ -407,8 +422,8 @@ impl<'hir> Map<'hir> {
     /// which this is the body of, i.e., a `fn`, `const` or `static`
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
-        let parent = self.get_parent_node(hir_id);
-        assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)));
+        let parent = self.parent_id(hir_id);
+        assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)), "{hir_id:?}");
         parent
     }
 
@@ -419,10 +434,11 @@ impl<'hir> Map<'hir> {
     /// Given a `LocalDefId`, returns the `BodyId` associated with it,
     /// if the node is a body owner, otherwise returns `None`.
     pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<BodyId> {
-        self.get_if_local(id.to_def_id()).map(associated_body).flatten()
+        self.find_by_def_id(id).and_then(associated_body)
     }
 
     /// Given a body owner's id, returns the `BodyId` associated with it.
+    #[track_caller]
     pub fn body_owned_by(self, id: LocalDefId) -> BodyId {
         self.maybe_body_owned_by(id).unwrap_or_else(|| {
             let hir_id = self.local_def_id_to_hir_id(id);
@@ -634,21 +650,21 @@ impl<'hir> Map<'hir> {
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
-    /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
     #[inline]
     pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator<Item = HirId> + 'hir {
         ParentHirIterator { current_id, map: self }
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
-    /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
     #[inline]
     pub fn parent_iter(self, current_id: HirId) -> impl Iterator<Item = (HirId, Node<'hir>)> {
         self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.find(id)?)))
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
-    /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
     #[inline]
     pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
         ParentOwnerIterator { current_id, map: self }
@@ -656,7 +672,7 @@ impl<'hir> Map<'hir> {
 
     /// Checks if the node is left-hand side of an assignment.
     pub fn is_lhs(self, id: HirId) -> bool {
-        match self.find(self.get_parent_node(id)) {
+        match self.find_parent(id) {
             Some(Node::Expr(expr)) => match expr.kind {
                 ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id,
                 _ => false,
@@ -696,12 +712,10 @@ impl<'hir> Map<'hir> {
     pub fn get_return_block(self, id: HirId) -> Option<HirId> {
         let mut iter = self.parent_iter(id).peekable();
         let mut ignore_tail = false;
-        if let Some(node) = self.find(id) {
-            if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = node {
-                // When dealing with `return` statements, we don't care about climbing only tail
-                // expressions.
-                ignore_tail = true;
-            }
+        if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.find(id) {
+            // When dealing with `return` statements, we don't care about climbing only tail
+            // expressions.
+            ignore_tail = true;
         }
         while let Some((hir_id, node)) = iter.next() {
             if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
@@ -886,7 +900,7 @@ impl<'hir> Map<'hir> {
             Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
             // A `Ctor` doesn't have an identifier itself, but its parent
             // struct/variant does. Compare with `hir::Map::opt_span`.
-            Node::Ctor(..) => match self.find(self.get_parent_node(id))? {
+            Node::Ctor(..) => match self.find_parent(id)? {
                 Node::Item(item) => Some(item.ident),
                 Node::Variant(variant) => Some(variant.ident),
                 _ => unreachable!(),
@@ -1015,7 +1029,7 @@ impl<'hir> Map<'hir> {
                 ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()),
                 _ => named_span(item.span, item.ident, None),
             },
-            Node::Ctor(_) => return self.opt_span(self.get_parent_node(hir_id)),
+            Node::Ctor(_) => return self.opt_span(self.parent_id(hir_id)),
             Node::Expr(Expr {
                 kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
                 span,
@@ -1057,7 +1071,7 @@ impl<'hir> Map<'hir> {
             Node::PatField(field) => field.span,
             Node::Arm(arm) => arm.span,
             Node::Block(block) => block.span,
-            Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
+            Node::Ctor(..) => self.span_with_body(self.parent_id(hir_id)),
             Node::Lifetime(lifetime) => lifetime.ident.span,
             Node::GenericParam(param) => param.span,
             Node::Infer(i) => i.span,
@@ -1087,7 +1101,7 @@ impl<'hir> Map<'hir> {
     /// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
     /// called with the HirId for the `{ ... }` anon const
     pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
-        match self.get(self.get_parent_node(anon_const)) {
+        match self.get_parent(anon_const) {
             Node::GenericParam(GenericParam {
                 def_id: param_id,
                 kind: GenericParamKind::Const { .. },
@@ -1154,7 +1168,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
         hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
         upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
         source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
-        if tcx.sess.opts.unstable_opts.incremental_relative_spans {
+        if tcx.sess.opts.incremental_relative_spans() {
             let definitions = tcx.definitions_untracked();
             let mut owner_spans: Vec<_> = krate
                 .owners
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 3f6e29ad611..a633201e3d9 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -160,9 +160,13 @@ pub fn provide(providers: &mut Providers) {
         } else if let Node::TraitItem(&TraitItem {
             kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
             ..
+        })
+        | Node::ForeignItem(&ForeignItem {
+            kind: ForeignItemKind::Fn(_, idents, _),
+            ..
         }) = hir.get(hir_id)
         {
-            tcx.arena.alloc_slice(idents)
+            idents
         } else {
             span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
         }
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 0331d764b38..614cf1a0051 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -213,9 +213,7 @@ impl QueryRegionConstraints<'_> {
     }
 }
 
-pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>;
-
-pub type CanonicalizedQueryResponse<'tcx, T> = &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;
+pub type CanonicalQueryResponse<'tcx, T> = &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;
 
 /// Indicates whether or not we were able to prove the query to be
 /// true.
@@ -300,6 +298,16 @@ impl<'tcx, V> Canonical<'tcx, V> {
         let Canonical { max_universe, variables, value } = self;
         Canonical { max_universe, variables, value: map_op(value) }
     }
+
+    /// Allows you to map the `value` of a canonical while keeping the same set of
+    /// bound variables.
+    ///
+    /// **WARNING:** This function is very easy to mis-use, hence the name! See
+    /// the comment of [Canonical::unchecked_map] for more details.
+    pub fn unchecked_rebind<W>(self, value: W) -> Canonical<'tcx, W> {
+        let Canonical { max_universe, variables, value: _ } = self;
+        Canonical { max_universe, variables, value }
+    }
 }
 
 pub type QueryOutlivesConstraint<'tcx> = (
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 51df42f6d14..c61de97d532 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -182,7 +182,7 @@ impl TyCtxt<'_> {
             if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
                 return id;
             }
-            let next = hir.get_parent_node(id);
+            let next = hir.parent_id(id);
             if next == id {
                 bug!("lint traversal reached the root of the crate");
             }
@@ -234,16 +234,7 @@ pub fn explain_lint_level_source(
             err.note_once(&format!("`#[{}({})]` on by default", level.as_str(), name));
         }
         LintLevelSource::CommandLine(lint_flag_val, orig_level) => {
-            let flag = match orig_level {
-                Level::Warn => "-W",
-                Level::Deny => "-D",
-                Level::Forbid => "-F",
-                Level::Allow => "-A",
-                Level::ForceWarn(_) => "--force-warn",
-                Level::Expect(_) => {
-                    unreachable!("the expect level does not have a commandline flag")
-                }
-            };
+            let flag = orig_level.to_cmd_flag();
             let hyphen_case_lint_name = name.replace('_', "-");
             if lint_flag_val.as_str() == name {
                 err.note_once(&format!(
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 01fe72de612..5ca4d260179 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -1,3 +1,13 @@
+/// A macro for triggering an ICE.
+/// Calling `bug` instead of panicking will result in a nicer error message and should
+/// therefore be prefered over `panic`/`unreachable` or others.
+///
+/// If you have a span available, you should use [`span_bug`] instead.
+///
+/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful.
+///
+/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
+/// [`span_bug`]: crate::span_bug
 #[macro_export]
 macro_rules! bug {
     () => ( $crate::bug!("impossible case reached") );
@@ -8,6 +18,14 @@ macro_rules! bug {
     });
 }
 
+/// A macro for triggering an ICE with a span.
+/// Calling `span_bug!` instead of panicking will result in a nicer error message and point
+/// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger
+/// ICEs.
+///
+/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful.
+///
+/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
 #[macro_export]
 macro_rules! span_bug {
     ($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) });
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index c886175c6ea..94ca38c0e75 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -147,9 +147,8 @@ rustc_index::newtype_index! {
     ///
     /// * The subscope with `first_statement_index == 1` is scope of `c`,
     ///   and thus does not include EXPR_2, but covers the `...`.
-    pub struct FirstStatementIndex {
-        derive [HashStable]
-    }
+    #[derive(HashStable)]
+    pub struct FirstStatementIndex {}
 }
 
 // compilation error if size of `ScopeData` is not the same as a `u32`
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 61bc089e431..0836f236e24 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -223,8 +223,8 @@ pub fn deprecation_message_and_lint(
     )
 }
 
-pub fn early_report_deprecation<'a>(
-    lint_buffer: &'a mut LintBuffer,
+pub fn early_report_deprecation(
+    lint_buffer: &mut LintBuffer,
     message: &str,
     suggestion: Option<Symbol>,
     lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 0b55757eb03..e7bb3ab0bc3 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -10,10 +10,10 @@ rustc_index::newtype_index! {
     /// CounterValueReference.as_u32() (which ascend from 1) or an ExpressionOperandId.as_u32()
     /// (which _*descend*_ from u32::MAX). Id value `0` (zero) represents a virtual counter with a
     /// constant value of `0`.
+    #[derive(HashStable)]
+    #[max = 0xFFFF_FFFF]
+    #[debug_format = "ExpressionOperandId({})"]
     pub struct ExpressionOperandId {
-        derive [HashStable]
-        DEBUG_FORMAT = "ExpressionOperandId({})",
-        MAX = 0xFFFF_FFFF,
     }
 }
 
@@ -32,11 +32,10 @@ impl ExpressionOperandId {
 }
 
 rustc_index::newtype_index! {
-    pub struct CounterValueReference {
-        derive [HashStable]
-        DEBUG_FORMAT = "CounterValueReference({})",
-        MAX = 0xFFFF_FFFF,
-    }
+    #[derive(HashStable)]
+    #[max = 0xFFFF_FFFF]
+    #[debug_format = "CounterValueReference({})"]
+    pub struct CounterValueReference {}
 }
 
 impl CounterValueReference {
@@ -56,33 +55,30 @@ rustc_index::newtype_index! {
     /// InjectedExpressionId.as_u32() converts to ExpressionOperandId.as_u32()
     ///
     /// Values descend from u32::MAX.
-    pub struct InjectedExpressionId {
-        derive [HashStable]
-        DEBUG_FORMAT = "InjectedExpressionId({})",
-        MAX = 0xFFFF_FFFF,
-    }
+    #[derive(HashStable)]
+    #[max = 0xFFFF_FFFF]
+    #[debug_format = "InjectedExpressionId({})"]
+    pub struct InjectedExpressionId {}
 }
 
 rustc_index::newtype_index! {
     /// InjectedExpressionIndex.as_u32() translates to u32::MAX - ExpressionOperandId.as_u32()
     ///
     /// Values ascend from 0.
-    pub struct InjectedExpressionIndex {
-        derive [HashStable]
-        DEBUG_FORMAT = "InjectedExpressionIndex({})",
-        MAX = 0xFFFF_FFFF,
-    }
+    #[derive(HashStable)]
+    #[max = 0xFFFF_FFFF]
+    #[debug_format = "InjectedExpressionIndex({})"]
+    pub struct InjectedExpressionIndex {}
 }
 
 rustc_index::newtype_index! {
     /// MappedExpressionIndex values ascend from zero, and are recalculated indexes based on their
     /// array position in the LLVM coverage map "Expressions" array, which is assembled during the
     /// "mapgen" process. They cannot be computed algorithmically, from the other `newtype_index`s.
-    pub struct MappedExpressionIndex {
-        derive [HashStable]
-        DEBUG_FORMAT = "MappedExpressionIndex({})",
-        MAX = 0xFFFF_FFFF,
-    }
+    #[derive(HashStable)]
+    #[max = 0xFFFF_FFFF]
+    #[debug_format = "MappedExpressionIndex({})"]
+    pub struct MappedExpressionIndex {}
 }
 
 impl From<CounterValueReference> for ExpressionOperandId {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index e909b2f74aa..14bdff4568f 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -654,10 +654,10 @@ impl SourceInfo {
 // Variables and temps
 
 rustc_index::newtype_index! {
+    #[derive(HashStable)]
+    #[debug_format = "_{}"]
     pub struct Local {
-        derive [HashStable]
-        DEBUG_FORMAT = "_{}",
-        const RETURN_PLACE = 0,
+        const RETURN_PLACE = 0;
     }
 }
 
@@ -1146,10 +1146,10 @@ rustc_index::newtype_index! {
     ///     https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
     /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
     /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
+    #[derive(HashStable)]
+    #[debug_format = "bb{}"]
     pub struct BasicBlock {
-        derive [HashStable]
-        DEBUG_FORMAT = "bb{}",
-        const START_BLOCK = 0,
+        const START_BLOCK = 0;
     }
 }
 
@@ -1488,7 +1488,7 @@ impl<'tcx> StatementKind<'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 // Places
 
-impl<V, T, U> ProjectionElem<V, T, U> {
+impl<V, T> ProjectionElem<V, T> {
     /// Returns `true` if the target of this projection may refer to a different region of memory
     /// than the base.
     fn is_indirect(&self) -> bool {
@@ -1517,7 +1517,7 @@ impl<V, T, U> ProjectionElem<V, T, U> {
 
 /// Alias for projections as they appear in `UserTypeProjection`, where we
 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
-pub type ProjectionKind = ProjectionElem<(), (), ()>;
+pub type ProjectionKind = ProjectionElem<(), ()>;
 
 rustc_index::newtype_index! {
     /// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG]
@@ -1530,10 +1530,9 @@ rustc_index::newtype_index! {
     /// [wrapper]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#newtype
     /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
     /// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types
-    pub struct Field {
-        derive [HashStable]
-        DEBUG_FORMAT = "field[{}]"
-    }
+    #[derive(HashStable)]
+    #[debug_format = "field[{}]"]
+    pub struct Field {}
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -1757,10 +1756,10 @@ impl Debug for Place<'_> {
 // Scopes
 
 rustc_index::newtype_index! {
+    #[derive(HashStable)]
+    #[debug_format = "scope[{}]"]
     pub struct SourceScope {
-        derive [HashStable]
-        DEBUG_FORMAT = "scope[{}]",
-        const OUTERMOST_SOURCE_SCOPE = 0,
+        const OUTERMOST_SOURCE_SCOPE = 0;
     }
 }
 
@@ -1768,9 +1767,9 @@ impl SourceScope {
     /// Finds the original HirId this MIR item came from.
     /// This is necessary after MIR optimizations, as otherwise we get a HirId
     /// from the function that was inlined instead of the function call site.
-    pub fn lint_root<'tcx>(
+    pub fn lint_root(
         self,
-        source_scopes: &IndexVec<SourceScope, SourceScopeData<'tcx>>,
+        source_scopes: &IndexVec<SourceScope, SourceScopeData<'_>>,
     ) -> Option<HirId> {
         let mut data = &source_scopes[self];
         // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it
@@ -2507,7 +2506,7 @@ impl<'tcx> ConstantKind<'tcx> {
         }
 
         let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
-        let parent_substs = if let Some(parent_hir_id) = tcx.hir().find_parent_node(hir_id) {
+        let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) {
             if let Some(parent_did) = tcx.hir().opt_local_def_id(parent_hir_id) {
                 InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
             } else {
@@ -2755,10 +2754,9 @@ impl<'tcx> TypeVisitable<'tcx> for UserTypeProjection {
 }
 
 rustc_index::newtype_index! {
-    pub struct Promoted {
-        derive [HashStable]
-        DEBUG_FORMAT = "promoted[{}]"
-    }
+    #[derive(HashStable)]
+    #[debug_format = "promoted[{}]"]
+    pub struct Promoted {}
 }
 
 impl<'tcx> Debug for Constant<'tcx> {
@@ -2896,7 +2894,7 @@ fn pretty_print_const_value<'tcx>(
                 if let Some(contents) = tcx.try_destructure_mir_constant(
                     ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)),
                 ) {
-                    let fields = contents.fields.iter().copied().collect::<Vec<_>>();
+                    let fields = contents.fields.to_vec();
                     match *ty.kind() {
                         ty::Array(..) => {
                             fmt.write_str("[")?;
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 1ebfdbbd6ef..40289af257f 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -88,7 +88,7 @@ pub fn dump_mir<'tcx, F>(
     dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, body, extra_data);
 }
 
-pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> bool {
+pub fn dump_enabled(tcx: TyCtxt<'_>, pass_name: &str, def_id: DefId) -> bool {
     let Some(ref filters) = tcx.sess.opts.unstable_opts.dump_mir else {
         return false;
     };
@@ -421,7 +421,7 @@ impl<'tcx> ExtraComments<'tcx> {
     }
 }
 
-fn use_verbose<'tcx>(ty: Ty<'tcx>, fn_def: bool) -> bool {
+fn use_verbose(ty: Ty<'_>, fn_def: bool) -> bool {
     match *ty.kind() {
         ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false,
         // Unit type
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index efd7357afc4..a8a4532223c 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -130,10 +130,9 @@ pub struct UnsafetyCheckResult {
 }
 
 rustc_index::newtype_index! {
-    pub struct GeneratorSavedLocal {
-        derive [HashStable]
-        DEBUG_FORMAT = "_{}",
-    }
+    #[derive(HashStable)]
+    #[debug_format = "_{}"]
+    pub struct GeneratorSavedLocal {}
 }
 
 /// The layout of generator state.
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 4e06d91012c..887ee571575 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -230,7 +230,7 @@ where
 }
 
 /// Format a string showing the start line and column, and end line and column within a file.
-pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> String {
+pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String {
     let source_map = tcx.sess.source_map();
     let start = source_map.lookup_char_pos(span.lo());
     let end = source_map.lookup_char_pos(span.hi());
@@ -322,7 +322,7 @@ fn block_span_viewable<'tcx>(
     Some(SpanViewable { bb, span, id, tooltip })
 }
 
-fn compute_block_span<'tcx>(data: &BasicBlockData<'tcx>, body_span: Span) -> Span {
+fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span {
     let mut span = data.terminator().source_info.span;
     for statement_span in data.statements.iter().map(|statement| statement.source_info.span) {
         // Only combine Spans from the root context, and within the function's body_span.
@@ -522,12 +522,7 @@ where
 }
 
 #[inline(always)]
-fn write_coverage_gap<'tcx, W>(
-    tcx: TyCtxt<'tcx>,
-    lo: BytePos,
-    hi: BytePos,
-    w: &mut W,
-) -> io::Result<()>
+fn write_coverage_gap<W>(tcx: TyCtxt<'_>, lo: BytePos, hi: BytePos, w: &mut W) -> io::Result<()>
 where
     W: Write,
 {
@@ -582,8 +577,8 @@ where
     Ok(())
 }
 
-fn make_html_snippet<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn make_html_snippet(
+    tcx: TyCtxt<'_>,
     span: Span,
     some_viewable: Option<&SpanViewable>,
 ) -> Option<String> {
@@ -664,7 +659,7 @@ fn trim_span_hi(span: Span, to_pos: BytePos) -> Span {
     if to_pos >= span.hi() { span } else { span.with_hi(cmp::max(span.lo(), to_pos)) }
 }
 
-fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span {
+fn fn_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
     let fn_decl_span = tcx.def_span(def_id);
     if let Some(body_span) = hir_body(tcx, def_id).map(|hir_body| hir_body.value.span) {
         if fn_decl_span.eq_ctxt(body_span) { fn_decl_span.to(body_span) } else { body_span }
@@ -673,7 +668,7 @@ fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span {
     }
 }
 
-fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<&'tcx rustc_hir::Body<'tcx>> {
+fn hir_body(tcx: TyCtxt<'_>, def_id: DefId) -> Option<&rustc_hir::Body<'_>> {
     let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
     hir::map::associated_body(hir_node).map(|fn_body_id| tcx.hir().body(fn_body_id))
 }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index a6ca04f5e62..6b4489026d3 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -320,8 +320,10 @@ pub enum StatementKind<'tcx> {
     /// <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/> for
     /// more details.
     ///
-    /// For code that is not specific to stacked borrows, you should consider retags to read
-    /// and modify the place in an opaque way.
+    /// For code that is not specific to stacked borrows, you should consider retags to read and
+    /// modify the place in an opaque way.
+    ///
+    /// Only `RetagKind::Default` and `RetagKind::FnEntry` are permitted.
     Retag(RetagKind, Box<Place<'tcx>>),
 
     /// Encodes a user's type ascription. These need to be preserved
@@ -562,14 +564,13 @@ pub enum TerminatorKind<'tcx> {
     Unreachable,
 
     /// The behavior of this statement differs significantly before and after drop elaboration.
-    /// After drop elaboration, `Drop` executes the drop glue for the specified place, after which
-    /// it continues execution/unwinds at the given basic blocks. It is possible that executing drop
-    /// glue is special - this would be part of Rust's memory model. (**FIXME**: due we have an
-    /// issue tracking if drop glue has any interesting semantics in addition to those of a function
-    /// call?)
     ///
-    /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically, the
-    /// `Drop` will be executed if...
+    /// After drop elaboration: `Drop` terminators are a complete nop for types that have no drop
+    /// glue. For other types, `Drop` terminators behave exactly like a call to
+    /// `core::mem::drop_in_place` with a pointer to the given place.
+    ///
+    /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically,
+    /// the `Drop` will be executed if...
     ///
     /// **Needs clarification**: End of that sentence. This in effect should document the exact
     /// behavior of drop elaboration. The following sounds vaguely right, but I'm not quite sure:
@@ -890,18 +891,11 @@ pub struct Place<'tcx> {
     pub projection: &'tcx List<PlaceElem<'tcx>>,
 }
 
-/// The different kinds of projections that can be used in the projection of a `Place`.
-///
-/// `T1` is the generic type for a field projection. For an actual projection on a `Place`
-/// this parameter will always be `Ty`, but the field type can be unavailable when
-/// building (by using `PlaceBuilder`) places that correspond to upvars.
-/// `T2` is the generic type for an `OpaqueCast` (is generic since it's abstracted over
-/// in dataflow analysis, see `AbstractElem`).
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
-pub enum ProjectionElem<V, T1, T2> {
+pub enum ProjectionElem<V, T> {
     Deref,
-    Field(Field, T1),
+    Field(Field, T),
     /// Index into a slice/array.
     ///
     /// Note that this does not also dereference, and so it does not exactly correspond to slice
@@ -957,36 +951,12 @@ pub enum ProjectionElem<V, T1, T2> {
 
     /// Like an explicit cast from an opaque type to a concrete type, but without
     /// requiring an intermediate variable.
-    OpaqueCast(T2),
+    OpaqueCast(T),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
 /// and the index is a local.
-pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>, Ty<'tcx>>;
-
-/// Alias for projections that appear in `PlaceBuilder::Upvar`, for which
-/// we cannot provide any field types.
-pub type UpvarProjectionElem<'tcx> = ProjectionElem<Local, (), Ty<'tcx>>;
-
-impl<'tcx> From<PlaceElem<'tcx>> for UpvarProjectionElem<'tcx> {
-    fn from(elem: PlaceElem<'tcx>) -> Self {
-        match elem {
-            ProjectionElem::Deref => ProjectionElem::Deref,
-            ProjectionElem::Field(field, _) => ProjectionElem::Field(field, ()),
-            ProjectionElem::Index(v) => ProjectionElem::Index(v),
-            ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
-                ProjectionElem::ConstantIndex { offset, min_length, from_end }
-            }
-            ProjectionElem::Subslice { from, to, from_end } => {
-                ProjectionElem::Subslice { from, to, from_end }
-            }
-            ProjectionElem::Downcast(opt_sym, variant_idx) => {
-                ProjectionElem::Downcast(opt_sym, variant_idx)
-            }
-            ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
-        }
-    }
-}
+pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 
 ///////////////////////////////////////////////////////////////////////////
 // Operands
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 1e289fc4abe..599f0b9d3fa 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -28,12 +28,13 @@ impl<'tcx> PlaceTy<'tcx> {
     /// `place_ty.field_ty(tcx, f)` computes the type at a given field
     /// of a record or enum-variant. (Most clients of `PlaceTy` can
     /// instead just extract the relevant type directly from their
-    /// `PlaceElem`, but some instances of `ProjectionElem<V, T1, T2>` do
-    /// not carry a `Ty` for `T1` or `T2`.)
+    /// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do
+    /// not carry a `Ty` for `T`.)
     ///
     /// Note that the resulting type has not been normalized.
+    #[instrument(level = "debug", skip(tcx), ret)]
     pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
-        let answer = match self.ty.kind() {
+        match self.ty.kind() {
             ty::Adt(adt_def, substs) => {
                 let variant_def = match self.variant_index {
                     None => adt_def.non_enum_variant(),
@@ -47,9 +48,7 @@ impl<'tcx> PlaceTy<'tcx> {
             }
             ty::Tuple(tys) => tys[f.index()],
             _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
-        };
-        debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
-        answer
+        }
     }
 
     /// Convenience wrapper around `projection_ty_core` for
@@ -64,18 +63,17 @@ impl<'tcx> PlaceTy<'tcx> {
     /// `Ty` or downcast variant corresponding to that projection.
     /// The `handle_field` callback must map a `Field` to its `Ty`,
     /// (which should be trivial when `T` = `Ty`).
-    pub fn projection_ty_core<V, T1, T2>(
+    pub fn projection_ty_core<V, T>(
         self,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        elem: &ProjectionElem<V, T1, T2>,
-        mut handle_field: impl FnMut(&Self, Field, T1) -> Ty<'tcx>,
-        mut handle_opaque_cast: impl FnMut(&Self, T2) -> Ty<'tcx>,
+        elem: &ProjectionElem<V, T>,
+        mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
+        mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
     ) -> PlaceTy<'tcx>
     where
         V: ::std::fmt::Debug,
-        T1: ::std::fmt::Debug + Copy,
-        T2: ::std::fmt::Debug + Copy,
+        T: ::std::fmt::Debug + Copy,
     {
         if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
             bug!("cannot use non field projection on downcasted place")
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 013a1bccd3b..438f36373ca 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,4 +1,4 @@
-use smallvec::{smallvec, SmallVec};
+use smallvec::SmallVec;
 
 use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
 use rustc_ast::InlineAsmTemplatePiece;
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 55b2c592795..0b461d1ce41 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -302,7 +302,7 @@ pub fn reachable<'a, 'tcx>(
 }
 
 /// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`.
-pub fn reachable_as_bitset<'tcx>(body: &Body<'tcx>) -> BitSet<BasicBlock> {
+pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet<BasicBlock> {
     let mut iter = preorder(body);
     (&mut iter).for_each(drop);
     iter.visited
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 2ee3f551529..1a264d2d5af 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -3,15 +3,15 @@
 //! ## Overview
 //!
 //! There are two visitors, one for immutable and one for mutable references,
-//! but both are generated by the following macro. The code is written according
-//! to the following conventions:
+//! but both are generated by the `make_mir_visitor` macro.
+//! The code is written according to the following conventions:
 //!
 //! - introduce a `visit_foo` and a `super_foo` method for every MIR type
 //! - `visit_foo`, by default, calls `super_foo`
 //! - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
 //!
-//! This allows you as a user to override `visit_foo` for types are
-//! interested in, and invoke (within that method) call
+//! This allows you to override `visit_foo` for types you are
+//! interested in, and invoke (within that method call)
 //! `self.super_foo` to get the default behavior. Just as in an OO
 //! language, you should never call `super` methods ordinarily except
 //! in that circumstance.
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index ab512804330..37db2274f67 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -169,7 +169,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query collect_trait_impl_trait_tys(key: DefId)
+    query collect_return_position_impl_trait_in_trait_tys(key: DefId)
         -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>
     {
         desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
@@ -2117,7 +2117,7 @@ rustc_queries! {
         desc { "checking to see if `{}` permits being left zeroed", key.ty }
     }
 
-    query compare_assoc_const_impl_item_with_trait_item(
+    query compare_impl_const(
         key: (LocalDefId, DefId)
     ) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 8bef9dfe099..ac903010c8d 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -35,9 +35,8 @@ macro_rules! thir_with_elements {
         $(
             newtype_index! {
                 #[derive(HashStable)]
-                pub struct $id {
-                    DEBUG_FORMAT = $format
-                }
+                #[debug_format = $format]
+                pub struct $id {}
             }
         )*
 
diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs
index 6d4af8bea62..dd75b0d9ebc 100644
--- a/compiler/rustc_middle/src/traits/chalk.rs
+++ b/compiler/rustc_middle/src/traits/chalk.rs
@@ -210,7 +210,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(chalk_ir::TyData { kind: ty, flags: flags })
     }
 
-    fn ty_data<'a>(self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
+    fn ty_data(self, ty: &Self::InternedType) -> &chalk_ir::TyData<Self> {
         ty
     }
 
@@ -218,10 +218,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(lifetime)
     }
 
-    fn lifetime_data<'a>(
-        self,
-        lifetime: &'a Self::InternedLifetime,
-    ) -> &'a chalk_ir::LifetimeData<Self> {
+    fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &chalk_ir::LifetimeData<Self> {
         &lifetime
     }
 
@@ -229,7 +226,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(constant)
     }
 
-    fn const_data<'a>(self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
+    fn const_data(self, constant: &Self::InternedConst) -> &chalk_ir::ConstData<Self> {
         &constant
     }
 
@@ -246,10 +243,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(data)
     }
 
-    fn generic_arg_data<'a>(
-        self,
-        data: &'a Self::InternedGenericArg,
-    ) -> &'a chalk_ir::GenericArgData<Self> {
+    fn generic_arg_data(self, data: &Self::InternedGenericArg) -> &chalk_ir::GenericArgData<Self> {
         &data
     }
 
@@ -257,7 +251,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(goal)
     }
 
-    fn goal_data<'a>(self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData<Self> {
+    fn goal_data(self, goal: &Self::InternedGoal) -> &chalk_ir::GoalData<Self> {
         &goal
     }
 
@@ -268,7 +262,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn goals_data<'a>(self, goals: &'a Self::InternedGoals) -> &'a [chalk_ir::Goal<Self>] {
+    fn goals_data(self, goals: &Self::InternedGoals) -> &[chalk_ir::Goal<Self>] {
         goals
     }
 
@@ -279,10 +273,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn substitution_data<'a>(
+    fn substitution_data(
         self,
-        substitution: &'a Self::InternedSubstitution,
-    ) -> &'a [chalk_ir::GenericArg<Self>] {
+        substitution: &Self::InternedSubstitution,
+    ) -> &[chalk_ir::GenericArg<Self>] {
         substitution
     }
 
@@ -293,10 +287,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(data)
     }
 
-    fn program_clause_data<'a>(
+    fn program_clause_data(
         self,
-        clause: &'a Self::InternedProgramClause,
-    ) -> &'a chalk_ir::ProgramClauseData<Self> {
+        clause: &Self::InternedProgramClause,
+    ) -> &chalk_ir::ProgramClauseData<Self> {
         &clause
     }
 
@@ -307,10 +301,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn program_clauses_data<'a>(
+    fn program_clauses_data(
         self,
-        clauses: &'a Self::InternedProgramClauses,
-    ) -> &'a [chalk_ir::ProgramClause<Self>] {
+        clauses: &Self::InternedProgramClauses,
+    ) -> &[chalk_ir::ProgramClause<Self>] {
         clauses
     }
 
@@ -321,10 +315,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn quantified_where_clauses_data<'a>(
+    fn quantified_where_clauses_data(
         self,
-        clauses: &'a Self::InternedQuantifiedWhereClauses,
-    ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] {
+        clauses: &Self::InternedQuantifiedWhereClauses,
+    ) -> &[chalk_ir::QuantifiedWhereClause<Self>] {
         clauses
     }
 
@@ -335,10 +329,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn variable_kinds_data<'a>(
+    fn variable_kinds_data(
         self,
-        parameter_kinds: &'a Self::InternedVariableKinds,
-    ) -> &'a [chalk_ir::VariableKind<Self>] {
+        parameter_kinds: &Self::InternedVariableKinds,
+    ) -> &[chalk_ir::VariableKind<Self>] {
         parameter_kinds
     }
 
@@ -349,10 +343,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn canonical_var_kinds_data<'a>(
+    fn canonical_var_kinds_data(
         self,
-        canonical_var_kinds: &'a Self::InternedCanonicalVarKinds,
-    ) -> &'a [chalk_ir::CanonicalVarKind<Self>] {
+        canonical_var_kinds: &Self::InternedCanonicalVarKinds,
+    ) -> &[chalk_ir::CanonicalVarKind<Self>] {
         canonical_var_kinds
     }
 
@@ -363,10 +357,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn constraints_data<'a>(
+    fn constraints_data(
         self,
-        constraints: &'a Self::InternedConstraints,
-    ) -> &'a [chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
+        constraints: &Self::InternedConstraints,
+    ) -> &[chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
         constraints
     }
 
@@ -377,10 +371,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn variances_data<'a>(
-        self,
-        variances: &'a Self::InternedVariances,
-    ) -> &'a [chalk_ir::Variance] {
+    fn variances_data(self, variances: &Self::InternedVariances) -> &[chalk_ir::Variance] {
         variances
     }
 }
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 7380c62a669..543f5b87e00 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -15,22 +15,19 @@ use rustc_span::source_map::Span;
 
 pub mod type_op {
     use crate::ty::fold::TypeFoldable;
-    use crate::ty::subst::UserSubsts;
-    use crate::ty::{Predicate, Ty};
-    use rustc_hir::def_id::DefId;
+    use crate::ty::{Predicate, Ty, UserType};
     use std::fmt;
 
     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
     #[derive(TypeFoldable, TypeVisitable)]
     pub struct AscribeUserType<'tcx> {
         pub mir_ty: Ty<'tcx>,
-        pub def_id: DefId,
-        pub user_substs: UserSubsts<'tcx>,
+        pub user_ty: UserType<'tcx>,
     }
 
     impl<'tcx> AscribeUserType<'tcx> {
-        pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self {
-            Self { mir_ty, def_id, user_substs }
+        pub fn new(mir_ty: Ty<'tcx>, user_ty: UserType<'tcx>) -> Self {
+            Self { mir_ty, user_ty }
         }
     }
 
@@ -96,7 +93,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
 pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
     Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
 
-#[derive(Copy, Clone, Debug, HashStable)]
+#[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)]
 pub struct NoSolution;
 
 pub type Fallible<T> = Result<T, NoSolution>;
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index cccedc9ec6e..aad5b2fbe07 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -60,7 +60,7 @@ pub enum OverlapMode {
 }
 
 impl OverlapMode {
-    pub fn get<'tcx>(tcx: TyCtxt<'tcx>, trait_id: DefId) -> OverlapMode {
+    pub fn get(tcx: TyCtxt<'_>, trait_id: DefId) -> OverlapMode {
         let with_negative_coherence = tcx.features().with_negative_coherence;
         let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence);
 
@@ -180,6 +180,7 @@ impl Iterator for Ancestors<'_> {
 }
 
 /// Information about the most specialized definition of an associated item.
+#[derive(Debug)]
 pub struct LeafDef {
     /// The associated item described by this `LeafDef`.
     pub item: ty::AssocItem,
@@ -253,11 +254,11 @@ impl<'tcx> Ancestors<'tcx> {
 ///
 /// Returns `Err` if an error was reported while building the specialization
 /// graph.
-pub fn ancestors<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn ancestors(
+    tcx: TyCtxt<'_>,
     trait_def_id: DefId,
     start_from_impl: DefId,
-) -> Result<Ancestors<'tcx>, ErrorGuaranteed> {
+) -> Result<Ancestors<'_>, ErrorGuaranteed> {
     let specialization_graph = tcx.specialization_graph_of(trait_def_id);
 
     if let Some(reported) = specialization_graph.has_errored {
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index d00553cbad1..6ade8935fc8 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -238,10 +238,7 @@ impl<'tcx> CapturedPlace<'tcx> {
     }
 }
 
-fn symbols_for_closure_captures<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: (LocalDefId, LocalDefId),
-) -> Vec<Symbol> {
+fn symbols_for_closure_captures(tcx: TyCtxt<'_>, def_id: (LocalDefId, LocalDefId)) -> Vec<Symbol> {
     let typeck_results = tcx.typeck(def_id.0);
     let captures = typeck_results.closure_min_captures_flattened(def_id.1);
     captures.into_iter().map(|captured_place| captured_place.to_symbol(tcx)).collect()
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index e5abc38046c..152a7e9d43f 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -239,7 +239,7 @@ impl<'tcx> Const<'tcx> {
     }
 }
 
-pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {
+pub fn const_param_default(tcx: TyCtxt<'_>, def_id: DefId) -> Const<'_> {
     let default_def_id = match tcx.hir().get_by_def_id(def_id.expect_local()) {
         hir::Node::GenericParam(hir::GenericParam {
             kind: hir::GenericParamKind::Const { default: Some(ac), .. },
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 2a8a4d59888..48958e0d9e9 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -232,7 +232,7 @@ impl ScalarInt {
     }
 
     #[inline]
-    pub fn try_to_machine_usize<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Result<u64, Size> {
+    pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
         Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
     }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8f4d56c65b9..5de414077a2 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1518,7 +1518,7 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
 
 #[allow(rustc::usage_of_ty_tykind)]
 impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
-    fn borrow<'a>(&'a self) -> &'a T {
+    fn borrow(&self) -> &T {
         &self.0.internee
     }
 }
@@ -1541,7 +1541,7 @@ impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
 }
 
 impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
-    fn borrow<'a>(&'a self) -> &'a [T] {
+    fn borrow(&self) -> &[T] {
         &self.0[..]
     }
 }
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index ffdac93bcd0..9e4f90caab0 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -21,7 +21,7 @@ impl<'tcx> TyCtxt<'tcx> {
         T: TypeFoldable<'tcx>,
     {
         // If there's nothing to erase avoid performing the query at all
-        if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
+        if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
             return value;
         }
         debug!("erase_regions({:?})", value);
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 14d07608a78..50554cf9a82 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -457,7 +457,7 @@ impl<'tcx> TyCtxt<'tcx> {
                             .def_id
                             .as_local()
                             .map(|id| hir.local_def_id_to_hir_id(id))
-                            .and_then(|id| self.hir().find(self.hir().get_parent_node(id)))
+                            .and_then(|id| self.hir().find_parent(id))
                             .as_ref()
                             .and_then(|node| node.generics())
                         {
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 042b89bc4b0..b7eafc4b437 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -22,7 +22,7 @@ impl FlagComputation {
         result
     }
 
-    pub fn for_predicate<'tcx>(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation {
+    pub fn for_predicate(binder: ty::Binder<'_, ty::PredicateKind<'_>>) -> FlagComputation {
         let mut result = FlagComputation::new();
         result.add_predicate(binder);
         result
@@ -59,8 +59,18 @@ impl FlagComputation {
     {
         let mut computation = FlagComputation::new();
 
-        if !value.bound_vars().is_empty() {
-            computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND;
+        for bv in value.bound_vars() {
+            match bv {
+                ty::BoundVariableKind::Ty(_) => {
+                    computation.flags |= TypeFlags::HAS_TY_LATE_BOUND;
+                }
+                ty::BoundVariableKind::Region(_) => {
+                    computation.flags |= TypeFlags::HAS_RE_LATE_BOUND;
+                }
+                ty::BoundVariableKind::Const => {
+                    computation.flags |= TypeFlags::HAS_CT_LATE_BOUND;
+                }
+            }
         }
 
         f(&mut computation, value.skip_binder());
@@ -131,6 +141,7 @@ impl FlagComputation {
 
             &ty::Bound(debruijn, _) => {
                 self.add_bound_var(debruijn);
+                self.add_flags(TypeFlags::HAS_TY_LATE_BOUND);
             }
 
             &ty::Placeholder(..) => {
@@ -303,6 +314,7 @@ impl FlagComputation {
             }
             ty::ConstKind::Bound(debruijn, _) => {
                 self.add_bound_var(debruijn);
+                self.add_flags(TypeFlags::HAS_CT_LATE_BOUND);
             }
             ty::ConstKind::Param(_) => {
                 self.add_flags(TypeFlags::HAS_CT_PARAM);
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 2e70ac256a7..705adecd3b9 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -70,14 +70,6 @@ impl GenericParamDef {
         }
     }
 
-    pub fn has_default(&self) -> bool {
-        match self.kind {
-            GenericParamDefKind::Type { has_default, .. }
-            | GenericParamDefKind::Const { has_default } => has_default,
-            GenericParamDefKind::Lifetime => false,
-        }
-    }
-
     pub fn is_anonymous_lifetime(&self) -> bool {
         match self.kind {
             GenericParamDefKind::Lifetime => {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 7f66b993646..00f53afd663 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -670,29 +670,50 @@ where
                         });
                     }
 
-                    match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
-                        ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize),
-                        ty::Dynamic(_, _, ty::Dyn) => {
-                            TyMaybeWithLayout::Ty(tcx.mk_imm_ref(
-                                tcx.lifetimes.re_static,
-                                tcx.mk_array(tcx.types.usize, 3),
-                            ))
-                            /* FIXME: use actual fn pointers
-                            Warning: naively computing the number of entries in the
-                            vtable by counting the methods on the trait + methods on
-                            all parent traits does not work, because some methods can
-                            be not object safe and thus excluded from the vtable.
-                            Increase this counter if you tried to implement this but
-                            failed to do it without duplicating a lot of code from
-                            other places in the compiler: 2
-                            tcx.mk_tup(&[
-                                tcx.mk_array(tcx.types.usize, 3),
-                                tcx.mk_array(Option<fn()>),
-                            ])
-                            */
+                    let mk_dyn_vtable = || {
+                        tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3))
+                        /* FIXME: use actual fn pointers
+                        Warning: naively computing the number of entries in the
+                        vtable by counting the methods on the trait + methods on
+                        all parent traits does not work, because some methods can
+                        be not object safe and thus excluded from the vtable.
+                        Increase this counter if you tried to implement this but
+                        failed to do it without duplicating a lot of code from
+                        other places in the compiler: 2
+                        tcx.mk_tup(&[
+                            tcx.mk_array(tcx.types.usize, 3),
+                            tcx.mk_array(Option<fn()>),
+                        ])
+                        */
+                    };
+
+                    let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
+                        let metadata = tcx.normalize_erasing_regions(
+                            cx.param_env(),
+                            tcx.mk_projection(metadata_def_id, [pointee]),
+                        );
+
+                        // Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it
+                        // offers better information than `std::ptr::metadata::VTable`,
+                        // and we rely on this layout information to trigger a panic in
+                        // `std::mem::uninitialized::<&dyn Trait>()`, for example.
+                        if let ty::Adt(def, substs) = metadata.kind()
+                            && Some(def.did()) == tcx.lang_items().dyn_metadata()
+                            && substs.type_at(0).is_trait()
+                        {
+                            mk_dyn_vtable()
+                        } else {
+                            metadata
                         }
-                        _ => bug!("TyAndLayout::field({:?}): not applicable", this),
-                    }
+                    } else {
+                        match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
+                            ty::Slice(_) | ty::Str => tcx.types.usize,
+                            ty::Dynamic(_, _, ty::Dyn) => mk_dyn_vtable(),
+                            _ => bug!("TyAndLayout::field({:?}): not applicable", this),
+                        }
+                    };
+
+                    TyMaybeWithLayout::Ty(metadata)
                 }
 
                 // Arrays and slices.
@@ -993,7 +1014,7 @@ where
 /// might (from a foreign exception or similar).
 #[inline]
 #[tracing::instrument(level = "debug", skip(tcx))]
-pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
+pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
     if let Some(did) = fn_def_id {
         // Special attribute for functions which can't unwind.
         if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a8e1253e670..f01d74539a1 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -535,6 +535,17 @@ impl<'tcx> Predicate<'tcx> {
         self
     }
 
+    #[instrument(level = "debug", skip(tcx), ret)]
+    pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
+        match self.kind().skip_binder() {
+            ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+                tcx.trait_is_coinductive(data.def_id())
+            }
+            ty::PredicateKind::WellFormed(_) => true,
+            _ => false,
+        }
+    }
+
     /// Whether this projection can be soundly normalized.
     ///
     /// Wf predicates must not be normalized, as normalization
@@ -1018,6 +1029,24 @@ pub struct ProjectionPredicate<'tcx> {
     pub term: Term<'tcx>,
 }
 
+impl<'tcx> ProjectionPredicate<'tcx> {
+    pub fn self_ty(self) -> Ty<'tcx> {
+        self.projection_ty.self_ty()
+    }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
+        Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
+    }
+
+    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+        self.projection_ty.trait_def_id(tcx)
+    }
+
+    pub fn def_id(self) -> DefId {
+        self.projection_ty.def_id
+    }
+}
+
 pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
 
 impl<'tcx> PolyProjectionPredicate<'tcx> {
@@ -1054,18 +1083,6 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
     }
 }
 
-impl<'tcx> ProjectionPredicate<'tcx> {
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        Self {
-            projection_ty: tcx.mk_alias_ty(
-                self.projection_ty.def_id,
-                [self_ty.into()].into_iter().chain(self.projection_ty.substs.iter().skip(1)),
-            ),
-            ..self
-        }
-    }
-}
-
 pub trait ToPolyTraitRef<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a1d53506707..c49e75d68ad 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2883,13 +2883,19 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
 /// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere.
 ///
 /// The implementation uses similar import discovery logic to that of 'use' suggestions.
+///
+/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths`].
 fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
     let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default();
 
     if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
+        // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting.
+        //
         // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
         // wrapper can be used to suppress this query, in exchange for full paths being formatted.
-        tcx.sess.delay_good_path_bug("trimmed_def_paths constructed");
+        tcx.sess.delay_good_path_bug(
+            "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
+        );
     }
 
     let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 3c6800cf293..30073b541ec 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -99,12 +99,6 @@ impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
     }
 }
 
-impl fmt::Debug for ty::RegionVid {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "'_#{}r", self.index())
-    }
-}
-
 impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         with_no_trimmed_paths!(fmt::Display::fmt(self, f))
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 66aeebab88b..f7e4c821569 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1169,7 +1169,7 @@ pub struct AliasTy<'tcx> {
 }
 
 impl<'tcx> AliasTy<'tcx> {
-    pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
+    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
             DefKind::ImplTraitPlaceholder => {
@@ -1183,7 +1183,7 @@ impl<'tcx> AliasTy<'tcx> {
     /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
     /// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs
     pub fn trait_ref_and_own_substs(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
         debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
@@ -1202,14 +1202,18 @@ impl<'tcx> AliasTy<'tcx> {
     /// WARNING: This will drop the substs for generic associated types
     /// consider calling [Self::trait_ref_and_own_substs] to get those
     /// as well.
-    pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
+    pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
         let def_id = self.trait_def_id(tcx);
         tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
     }
 
-    pub fn self_ty(&self) -> Ty<'tcx> {
+    pub fn self_ty(self) -> Ty<'tcx> {
         self.substs.type_at(0)
     }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)))
+    }
 }
 
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
@@ -1378,9 +1382,8 @@ pub struct ConstVid<'tcx> {
 rustc_index::newtype_index! {
     /// A **region** (lifetime) **v**ariable **ID**.
     #[derive(HashStable)]
-    pub struct RegionVid {
-        DEBUG_FORMAT = custom,
-    }
+    #[debug_format = "'_#{}r"]
+    pub struct RegionVid {}
 }
 
 impl Atom for RegionVid {
@@ -1391,7 +1394,7 @@ impl Atom for RegionVid {
 
 rustc_index::newtype_index! {
     #[derive(HashStable)]
-    pub struct BoundVar { .. }
+    pub struct BoundVar {}
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a04b15f8cf1..0c33e5bda1a 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -348,7 +348,7 @@ impl<'tcx> InternalSubsts<'tcx> {
         substs.reserve(defs.params.len());
         for param in &defs.params {
             let kind = mk_kind(param, substs);
-            assert_eq!(param.index as usize, substs.len());
+            assert_eq!(param.index as usize, substs.len(), "{substs:#?}, {defs:#?}");
             substs.push(kind);
         }
     }
@@ -400,6 +400,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn type_at(&self, i: usize) -> Ty<'tcx> {
         if let GenericArgKind::Type(ty) = self[i].unpack() {
             ty
@@ -409,6 +410,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
         if let GenericArgKind::Lifetime(lt) = self[i].unpack() {
             lt
@@ -418,6 +420,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
         if let GenericArgKind::Const(ct) = self[i].unpack() {
             ct
@@ -427,6 +430,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn type_for_def(&self, def: &ty::GenericParamDef) -> GenericArg<'tcx> {
         self.type_at(def.index as usize).into()
     }
@@ -573,6 +577,10 @@ impl<T> EarlyBinder<T> {
     pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
         EarlyBinder(value)
     }
+
+    pub fn skip_binder(self) -> T {
+        self.0
+    }
 }
 
 impl<T> EarlyBinder<Option<T>> {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 4fe85d4366f..028a03c0b2b 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -608,10 +608,10 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
 }
 
 rustc_index::newtype_index! {
+    #[derive(HashStable)]
+    #[debug_format = "UserType({})"]
     pub struct UserTypeAnnotationIndex {
-        derive [HashStable]
-        DEBUG_FORMAT = "UserType({})",
-        const START_INDEX = 0,
+        const START_INDEX = 0;
     }
 }
 
@@ -626,7 +626,7 @@ pub struct CanonicalUserTypeAnnotation<'tcx> {
     pub inferred_ty: Ty<'tcx>,
 }
 
-/// Canonicalized user type annotation.
+/// Canonical user type annotation.
 pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
 
 impl<'tcx> CanonicalUserType<'tcx> {
@@ -679,7 +679,7 @@ impl<'tcx> CanonicalUserType<'tcx> {
 /// from constants that are named via paths, like `Foo::<A>::new` and
 /// so forth.
 #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub enum UserType<'tcx> {
     Ty(Ty<'tcx>),
 
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 857f52c8a24..cc53659f827 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -3,6 +3,7 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir;
 use crate::ty::layout::IntegerExt;
+use crate::ty::query::TyCtxtAt;
 use crate::ty::{
     self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
     TypeVisitable,
@@ -640,11 +641,11 @@ impl<'tcx> TyCtxt<'tcx> {
         ty::EarlyBinder(self.type_of(def_id))
     }
 
-    pub fn bound_trait_impl_trait_tys(
+    pub fn bound_return_position_impl_trait_in_trait_tys(
         self,
         def_id: DefId,
     ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> {
-        ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id))
+        ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id))
     }
 
     pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
@@ -769,6 +770,12 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
+impl<'tcx> TyCtxtAt<'tcx> {
+    pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
+        ty::EarlyBinder(self.type_of(def_id))
+    }
+}
+
 struct OpaqueTypeExpander<'tcx> {
     // Contains the DefIds of the opaque types that are currently being
     // expanded. When we expand an opaque type we insert the DefId of
@@ -1241,7 +1248,7 @@ pub fn needs_drop_components<'tcx>(
     }
 }
 
-pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
+pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
     match *ty.kind() {
         ty::Bool
         | ty::Char
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index b302572f3ca..ca445558131 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -88,9 +88,11 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
         self.has_vars_bound_at_or_above(ty::INNERMOST)
     }
 
-    #[instrument(level = "trace", ret)]
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
+        let res =
+            self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
+        trace!(?self, ?flags, ?res, "has_type_flags");
+        res
     }
     fn has_projections(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_PROJECTION)
@@ -163,6 +165,14 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
     fn has_late_bound_regions(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
     }
+    /// True if there are any late-bound non-region variables
+    fn has_non_region_late_bound(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND)
+    }
+    /// True if there are any late-bound variables
+    fn has_late_bound_vars(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_LATE_BOUND)
+    }
 
     /// Indicates whether this value still has parameters/placeholders/inference variables
     /// which could be replaced later, in a way that would change the results of `impl`
@@ -560,10 +570,8 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     type BreakTy = FoundFlags;
 
     #[inline]
-    #[instrument(skip(self), level = "trace", ret)]
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = t.flags();
-        trace!(t.flags=?t.flags());
         if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
@@ -572,10 +580,8 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    #[instrument(skip(self), level = "trace", ret)]
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = r.type_flags();
-        trace!(r.flags=?flags);
         if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
@@ -584,7 +590,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    #[instrument(level = "trace", ret)]
     fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = FlagComputation::for_const(c);
         trace!(r.flags=?flags);
@@ -596,14 +601,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    #[instrument(level = "trace", ret)]
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
-        debug!(
-            "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
-            predicate,
-            predicate.flags(),
-            self.flags
-        );
         if predicate.flags().intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 34dbb6e9f68..708a5e4d059 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -4,7 +4,7 @@
 use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::{self, Ty};
 use rustc_data_structures::sso::SsoHashSet;
-use smallvec::{self, SmallVec};
+use smallvec::SmallVec;
 
 // 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/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index fd7045d6a03..b73ae593905 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -35,8 +35,7 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
             (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg),
             (None, _) => panic_any(msg),
         }
-    });
-    unreachable!();
+    })
 }
 
 /// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 70b98e59a8b..c242be57031 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -1,3 +1,4 @@
+use crate::dep_graph::DepKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
 use rustc_hir as hir;
@@ -11,16 +12,16 @@ use rustc_span::Span;
 
 use std::fmt::Write;
 
-impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Ty<'_> {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self {
         // SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
         // FIXME: Represent the above fact in the trait system somehow.
         unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error()) }
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::SymbolName<'_> {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self {
         // SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`.
         // FIXME: Represent the above fact in the trait system somehow.
         unsafe {
@@ -31,12 +32,12 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::Binder<'_, ty::FnSig<'_>> {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo<DepKind>]) -> Self {
         let err = tcx.ty_error();
 
         let arity = if let Some(frame) = stack.get(0)
-            && frame.query.name == "fn_sig"
+            && frame.query.dep_kind == DepKind::fn_sig
             && let Some(def_id) = frame.query.def_id
             && let Some(node) = tcx.hir().get_if_local(def_id)
             && let Some(sig) = node.fn_sig()
@@ -61,12 +62,12 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Representability {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
         let mut item_and_field_ids = Vec::new();
         let mut representable_ids = FxHashSet::default();
         for info in cycle {
-            if info.query.name == "representability"
+            if info.query.dep_kind == DepKind::representability
                 && let Some(field_id) = info.query.def_id
                 && let Some(field_id) = field_id.as_local()
                 && let Some(DefKind::Field) = info.query.def_kind
@@ -80,7 +81,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
             }
         }
         for info in cycle {
-            if info.query.name == "representability_adt_ty"
+            if info.query.dep_kind == DepKind::representability_adt_ty
                 && let Some(def_id) = info.query.ty_adt_id
                 && let Some(def_id) = def_id.as_local()
                 && !item_and_field_ids.iter().any(|&(id, _)| id == def_id)