about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast.rs27
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs26
-rw-r--r--compiler/rustc_ast/src/visit.rs26
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs20
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs74
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs7
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs2
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs6
-rw-r--r--compiler/rustc_expand/messages.ftl3
-rw-r--r--compiler/rustc_expand/src/errors.rs7
-rw-r--r--compiler/rustc_expand/src/expand.rs117
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs10
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs42
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs8
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs4
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs6
-rw-r--r--compiler/rustc_middle/src/mir/query.rs4
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs8
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs2
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs3
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs14
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs30
-rw-r--r--compiler/rustc_middle/src/ty/context.rs76
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs16
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs54
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs36
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs384
-rw-r--r--compiler/rustc_middle/src/ty/util.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs12
-rw-r--r--compiler/rustc_parse/src/parser/item.rs31
-rw-r--r--compiler/rustc_parse/src/parser/path.rs7
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs5
-rw-r--r--compiler/rustc_passes/src/lang_items.rs8
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs6
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs2
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs15
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs4
-rw-r--r--compiler/rustc_resolve/src/macros.rs20
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs19
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs34
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs41
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs27
-rw-r--r--compiler/rustc_type_ir/src/interner.rs25
-rw-r--r--compiler/rustc_type_ir/src/ir_print.rs6
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs234
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs158
-rw-r--r--library/core/src/ascii.rs14
-rw-r--r--library/core/src/char/methods.rs8
-rw-r--r--library/core/src/char/mod.rs44
-rw-r--r--library/core/src/escape.rs139
-rw-r--r--library/core/src/num/uint_macros.rs6
-rw-r--r--library/std/src/sys/pal/unix/alloc.rs19
-rw-r--r--src/bootstrap/defaults/config.compiler.toml2
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs6
-rw-r--r--src/bootstrap/src/core/download.rs6
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/helpers.rs15
-rw-r--r--src/bootstrap/src/utils/tarball.rs4
-rw-r--r--src/doc/style-guide/src/editions.md2
-rw-r--r--src/doc/style-guide/src/expressions.md31
-rw-r--r--src/librustdoc/html/render/mod.rs8
-rw-r--r--src/tools/compiletest/src/runtest.rs22
-rw-r--r--src/tools/opt-dist/src/main.rs6
-rw-r--r--src/tools/run-make-support/src/lib.rs57
-rw-r--r--src/tools/run-make-support/src/rustc.rs9
-rw-r--r--src/tools/rustfmt/src/items.rs4
-rw-r--r--src/tools/rustfmt/src/visitor.rs2
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt7
-rw-r--r--tests/run-make/c-link-to-rust-staticlib/Makefile16
-rw-r--r--tests/run-make/c-link-to-rust-staticlib/rmake.rs15
-rw-r--r--tests/run-make/doctests-keep-binaries/rmake.rs9
-rw-r--r--tests/run-make/doctests-runtool/rmake.rs3
-rw-r--r--tests/run-make/issue-11908/Makefile22
-rw-r--r--tests/run-make/issue-14500/Makefile15
-rw-r--r--tests/run-make/no-cdylib-as-rdylib/Makefile16
-rw-r--r--tests/run-make/no-cdylib-as-rdylib/rmake.rs16
-rw-r--r--tests/run-make/panic-impl-transitive/Makefile7
-rw-r--r--tests/run-make/panic-impl-transitive/rmake.rs19
-rw-r--r--tests/run-make/reachable-extern-fn-available-lto/bar.rs (renamed from tests/run-make/issue-14500/bar.rs)0
-rw-r--r--tests/run-make/reachable-extern-fn-available-lto/foo.c (renamed from tests/run-make/issue-14500/foo.c)0
-rw-r--r--tests/run-make/reachable-extern-fn-available-lto/foo.rs (renamed from tests/run-make/issue-14500/foo.rs)0
-rw-r--r--tests/run-make/reachable-extern-fn-available-lto/rmake.rs26
-rw-r--r--tests/run-make/rustdoc-map-file/rmake.rs6
-rw-r--r--tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs10
-rw-r--r--tests/run-make/rustdoc-themes/Makefile11
-rw-r--r--tests/run-make/rustdoc-themes/rmake.rs31
-rw-r--r--tests/run-make/rustdoc-with-out-dir-option/Makefile8
-rw-r--r--tests/run-make/rustdoc-with-out-dir-option/rmake.rs7
-rw-r--r--tests/run-make/same-lib-two-locations-no-panic/bar.rs (renamed from tests/run-make/issue-11908/bar.rs)0
-rw-r--r--tests/run-make/same-lib-two-locations-no-panic/foo.rs (renamed from tests/run-make/issue-11908/foo.rs)0
-rw-r--r--tests/run-make/same-lib-two-locations-no-panic/rmake.rs28
-rw-r--r--tests/rustdoc/notable-trait/doc-notable_trait-negative.negative.html1
-rw-r--r--tests/rustdoc/notable-trait/doc-notable_trait-negative.positive.html1
-rw-r--r--tests/rustdoc/notable-trait/doc-notable_trait-negative.rs22
-rw-r--r--tests/ui/const-generics/lookup-method.rs19
-rw-r--r--tests/ui/const-generics/lookup-method.stderr15
-rw-r--r--tests/ui/delegation/bad-resolve.rs4
-rw-r--r--tests/ui/delegation/bad-resolve.stderr16
-rw-r--r--tests/ui/delegation/body-identity-list.rs32
-rw-r--r--tests/ui/delegation/empty-list.rs8
-rw-r--r--tests/ui/delegation/empty-list.stderr8
-rw-r--r--tests/ui/delegation/inner-attr.rs8
-rw-r--r--tests/ui/delegation/inner-attr.stderr18
-rw-r--r--tests/ui/delegation/list.rs46
-rw-r--r--tests/ui/delegation/macro-inside-list.rs26
-rw-r--r--tests/ui/delegation/rename.rs15
-rw-r--r--tests/ui/diagnostic_namespace/suggest_typos.rs18
-rw-r--r--tests/ui/diagnostic_namespace/suggest_typos.stderr40
-rw-r--r--tests/ui/macros/macro-span-issue-116502.rs16
-rw-r--r--tests/ui/macros/macro-span-issue-116502.stderr30
-rw-r--r--tests/ui/macros/meta-variable-depth-outside-repeat.rs4
-rw-r--r--tests/ui/macros/meta-variable-depth-outside-repeat.stderr6
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs108
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs11
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs10
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs6
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr6
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs7
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr6
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs9
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr122
-rw-r--r--tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.rs163
-rw-r--r--tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.stderr84
-rw-r--r--tests/ui/pattern/skipped-ref-pats-issue-125058.rs18
-rw-r--r--tests/ui/pattern/skipped-ref-pats-issue-125058.stderr24
-rw-r--r--triagebot.toml3
138 files changed, 2306 insertions, 1053 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 56d4f53f9ee..14e04774788 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2961,6 +2961,7 @@ impl Item {
             | ItemKind::GlobalAsm(_)
             | ItemKind::MacCall(_)
             | ItemKind::Delegation(_)
+            | ItemKind::DelegationMac(_)
             | ItemKind::MacroDef(_) => None,
             ItemKind::Static(_) => None,
             ItemKind::Const(i) => Some(&i.generics),
@@ -3123,8 +3124,16 @@ pub struct Delegation {
     /// Path resolution id.
     pub id: NodeId,
     pub qself: Option<P<QSelf>>,
-    pub rename: Option<Ident>,
     pub path: Path,
+    pub rename: Option<Ident>,
+    pub body: Option<P<Block>>,
+}
+
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct DelegationMac {
+    pub qself: Option<P<QSelf>>,
+    pub prefix: Path,
+    pub suffixes: ThinVec<(Ident, Option<Ident>)>,
     pub body: Option<P<Block>>,
 }
 
@@ -3243,10 +3252,13 @@ pub enum ItemKind {
     /// A macro definition.
     MacroDef(MacroDef),
 
-    /// A delegation item (`reuse`).
+    /// A single delegation item (`reuse`).
     ///
     /// E.g. `reuse <Type as Trait>::name { target_expr_template }`.
     Delegation(Box<Delegation>),
+    /// A list delegation item (`reuse prefix::{a, b, c}`).
+    /// Treated similarly to a macro call and expanded early.
+    DelegationMac(Box<DelegationMac>),
 }
 
 impl ItemKind {
@@ -3256,7 +3268,7 @@ impl ItemKind {
         match self {
             Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
             | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
-            | Delegation(..) => "a",
+            | Delegation(..) | DelegationMac(..) => "a",
             ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
         }
     }
@@ -3281,6 +3293,7 @@ impl ItemKind {
             ItemKind::MacroDef(..) => "macro definition",
             ItemKind::Impl { .. } => "implementation",
             ItemKind::Delegation(..) => "delegated function",
+            ItemKind::DelegationMac(..) => "delegation",
         }
     }
 
@@ -3324,6 +3337,8 @@ pub enum AssocItemKind {
     MacCall(P<MacCall>),
     /// An associated delegation item.
     Delegation(Box<Delegation>),
+    /// An associated delegation item list.
+    DelegationMac(Box<DelegationMac>),
 }
 
 impl AssocItemKind {
@@ -3332,7 +3347,9 @@ impl AssocItemKind {
             Self::Const(box ConstItem { defaultness, .. })
             | Self::Fn(box Fn { defaultness, .. })
             | Self::Type(box TyAlias { defaultness, .. }) => defaultness,
-            Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final,
+            Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
+                Defaultness::Final
+            }
         }
     }
 }
@@ -3345,6 +3362,7 @@ impl From<AssocItemKind> for ItemKind {
             AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
             AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
             AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
+            AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation),
         }
     }
 }
@@ -3359,6 +3377,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
             ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
             ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
             ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
+            ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d),
             _ => return Err(item_kind),
         })
     }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 5c4162295bb..1cfb8972a62 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1170,6 +1170,19 @@ impl NoopVisitItemKind for ItemKind {
                     vis.visit_block(body);
                 }
             }
+            ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+                vis.visit_qself(qself);
+                vis.visit_path(prefix);
+                for (ident, rename) in suffixes {
+                    vis.visit_ident(ident);
+                    if let Some(rename) = rename {
+                        vis.visit_ident(rename);
+                    }
+                }
+                if let Some(body) = body {
+                    vis.visit_block(body);
+                }
+            }
         }
     }
 }
@@ -1213,6 +1226,19 @@ impl NoopVisitItemKind for AssocItemKind {
                     visitor.visit_block(body);
                 }
             }
+            AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+                visitor.visit_qself(qself);
+                visitor.visit_path(prefix);
+                for (ident, rename) in suffixes {
+                    visitor.visit_ident(ident);
+                    if let Some(rename) = rename {
+                        visitor.visit_ident(rename);
+                    }
+                }
+                if let Some(body) = body {
+                    visitor.visit_block(body);
+                }
+            }
         }
     }
 }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index d36193ef7b0..7794edc3505 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -403,6 +403,19 @@ impl WalkItemKind for ItemKind {
                 visit_opt!(visitor, visit_ident, *rename);
                 visit_opt!(visitor, visit_block, body);
             }
+            ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+                if let Some(qself) = qself {
+                    try_visit!(visitor.visit_ty(&qself.ty));
+                }
+                try_visit!(visitor.visit_path(prefix, item.id));
+                for (ident, rename) in suffixes {
+                    visitor.visit_ident(*ident);
+                    if let Some(rename) = rename {
+                        visitor.visit_ident(*rename);
+                    }
+                }
+                visit_opt!(visitor, visit_block, body);
+            }
         }
         V::Result::output()
     }
@@ -815,6 +828,19 @@ impl WalkItemKind for AssocItemKind {
                 visit_opt!(visitor, visit_ident, *rename);
                 visit_opt!(visitor, visit_block, body);
             }
+            AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+                if let Some(qself) = qself {
+                    try_visit!(visitor.visit_ty(&qself.ty));
+                }
+                try_visit!(visitor.visit_path(prefix, item.id));
+                for (ident, rename) in suffixes {
+                    visitor.visit_ident(*ident);
+                    if let Some(rename) = rename {
+                        visitor.visit_ident(*rename);
+                    }
+                }
+                visit_opt!(visitor, visit_block, body);
+            }
         }
         V::Result::output()
     }
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 61fb5c16ad6..1255c1bba08 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -460,8 +460,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     delegation_results.body_id,
                 )
             }
-            ItemKind::MacCall(..) => {
-                panic!("`TyMac` should have been expanded by now")
+            ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
+                panic!("macros should have been expanded by now")
             }
         }
     }
@@ -845,7 +845,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 (delegation_results.generics, item_kind, true)
             }
-            AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
+            AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+                panic!("macros should have been expanded by now")
+            }
         };
 
         let item = hir::TraitItem {
@@ -869,7 +871,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
                 has_self: self.delegation_has_self(i.id, delegation.id, i.span),
             },
-            AssocItemKind::MacCall(..) => unimplemented!(),
+            AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+                panic!("macros should have been expanded by now")
+            }
         };
         let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
         hir::TraitItemRef {
@@ -964,7 +968,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
                 )
             }
-            AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
+            AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+                panic!("macros should have been expanded by now")
+            }
         };
 
         let item = hir::ImplItem {
@@ -993,7 +999,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
                     has_self: self.delegation_has_self(i.id, delegation.id, i.span),
                 },
-                AssocItemKind::MacCall(..) => unimplemented!(),
+                AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+                    panic!("macros should have been expanded by now")
+                }
             },
             trait_item_def_id: self
                 .resolver
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 09f9ca53a7a..16c3ee948a4 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -5,6 +5,7 @@ use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
 use ast::StaticItem;
 use itertools::{Itertools, Position};
 use rustc_ast as ast;
+use rustc_ast::ptr::P;
 use rustc_ast::ModKind;
 use rustc_span::symbol::Ident;
 
@@ -374,9 +375,22 @@ impl<'a> State<'a> {
                     state.print_visibility(&item.vis)
                 });
             }
-            ast::ItemKind::Delegation(box delegation) => {
-                self.print_delegation(delegation, &item.vis, &item.attrs)
-            }
+            ast::ItemKind::Delegation(deleg) => self.print_delegation(
+                &item.attrs,
+                &item.vis,
+                &deleg.qself,
+                &deleg.path,
+                None,
+                &deleg.body,
+            ),
+            ast::ItemKind::DelegationMac(deleg) => self.print_delegation(
+                &item.attrs,
+                &item.vis,
+                &deleg.qself,
+                &deleg.prefix,
+                Some(&deleg.suffixes),
+                &deleg.body,
+            ),
         }
         self.ann.post(self, AnnNode::Item(item))
     }
@@ -553,31 +567,63 @@ impl<'a> State<'a> {
                     self.word(";");
                 }
             }
-            ast::AssocItemKind::Delegation(box delegation) => {
-                self.print_delegation(delegation, vis, &item.attrs)
-            }
+            ast::AssocItemKind::Delegation(deleg) => self.print_delegation(
+                &item.attrs,
+                vis,
+                &deleg.qself,
+                &deleg.path,
+                None,
+                &deleg.body,
+            ),
+            ast::AssocItemKind::DelegationMac(deleg) => self.print_delegation(
+                &item.attrs,
+                vis,
+                &deleg.qself,
+                &deleg.prefix,
+                Some(&deleg.suffixes),
+                &deleg.body,
+            ),
         }
         self.ann.post(self, AnnNode::SubItem(id))
     }
 
     pub(crate) fn print_delegation(
         &mut self,
-        delegation: &ast::Delegation,
-        vis: &ast::Visibility,
         attrs: &[ast::Attribute],
+        vis: &ast::Visibility,
+        qself: &Option<P<ast::QSelf>>,
+        path: &ast::Path,
+        suffixes: Option<&[(Ident, Option<Ident>)]>,
+        body: &Option<P<ast::Block>>,
     ) {
-        if delegation.body.is_some() {
+        if body.is_some() {
             self.head("");
         }
         self.print_visibility(vis);
-        self.word_space("reuse");
+        self.word_nbsp("reuse");
 
-        if let Some(qself) = &delegation.qself {
-            self.print_qpath(&delegation.path, qself, false);
+        if let Some(qself) = qself {
+            self.print_qpath(path, qself, false);
         } else {
-            self.print_path(&delegation.path, false, 0);
+            self.print_path(path, false, 0);
+        }
+        if let Some(suffixes) = suffixes {
+            self.word("::");
+            self.word("{");
+            for (i, (ident, rename)) in suffixes.iter().enumerate() {
+                self.print_ident(*ident);
+                if let Some(rename) = rename {
+                    self.nbsp();
+                    self.word_nbsp("as");
+                    self.print_ident(*rename);
+                }
+                if i != suffixes.len() - 1 {
+                    self.word_space(",");
+                }
+            }
+            self.word("}");
         }
-        if let Some(body) = &delegation.body {
+        if let Some(body) = body {
             self.nbsp();
             self.print_block_with_attrs(body, attrs);
         } else {
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index c51a7744a30..26ea95f0f0d 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -207,13 +207,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
                 let cond_bitmap = coverage_context
                                     .try_get_mcdc_condition_bitmap(&instance, decision_depth)
                                     .expect("mcdc cond bitmap should have been allocated for merging into the global bitmap");
-                let bitmap_bytes = bx.tcx().coverage_ids_info(instance.def).mcdc_bitmap_bytes;
+                let bitmap_bytes = function_coverage_info.mcdc_bitmap_bytes;
                 assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range");
-                assert!(
-                    bitmap_bytes <= function_coverage_info.mcdc_bitmap_bytes,
-                    "bitmap length disagreement: query says {bitmap_bytes} but function info only has {}",
-                    function_coverage_info.mcdc_bitmap_bytes
-                );
 
                 let fn_name = bx.get_pgo_func_name_var(instance);
                 let hash = bx.const_u64(function_coverage_info.function_source_hash);
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 1610135a0ef..18bb71bd99f 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -896,7 +896,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         style: SuggestionStyle,
     ) -> &mut Self {
         suggestion.sort_unstable();
-        suggestion.dedup();
+        suggestion.dedup_by(|(s1, m1), (s2, m2)| s1.source_equal(*s2) && m1 == m2);
 
         let parts = suggestion
             .into_iter()
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 2cc0167dbaa..d9add1c9b3b 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -106,6 +106,12 @@ impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTrait
     }
 }
 
+impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst<I> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+        format!("{self:?}").into_diag_arg()
+    }
+}
+
 into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
 
 impl IntoDiagArg for bool {
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index b7aae2af9ef..7ae988a5be6 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -30,6 +30,9 @@ expand_duplicate_matcher_binding = duplicate matcher binding
     .label = duplicate binding
     .label2 = previous binding
 
+expand_empty_delegation_list =
+    empty list delegation is not supported
+
 expand_expected_paren_or_brace =
     expected `(` or `{"{"}`, found `{$token}`
 
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index b0563bfdea7..a5fc9e9d89c 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -433,3 +433,10 @@ pub struct ExpectedParenOrBrace<'a> {
     pub span: Span,
     pub token: Cow<'a, str>,
 }
+
+#[derive(Diagnostic)]
+#[diag(expand_empty_delegation_list)]
+pub(crate) struct EmptyDelegationList {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index ddf7b1a007a..a049ac251e1 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1,8 +1,8 @@
 use crate::base::*;
 use crate::config::StripUnconfigured;
 use crate::errors::{
-    IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported,
-    UnsupportedKeyValue, WrongFragmentKind,
+    EmptyDelegationList, IncompleteParse, RecursionLimitReached, RemoveExprNotSupported,
+    RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind,
 };
 use crate::mbe::diagnostics::annotate_err_with_kind;
 use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
@@ -1041,6 +1041,7 @@ enum AddSemicolon {
 trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     type OutputTy = SmallVec<[Self; 1]>;
     type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec;
+    type ItemKind = ItemKind;
     const KIND: AstFragmentKind;
     fn to_annotatable(self) -> Annotatable;
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
@@ -1059,6 +1060,18 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         unreachable!()
     }
+    fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
+        None
+    }
+    fn delegation_item_kind(_deleg: Box<ast::Delegation>) -> Self::ItemKind {
+        unreachable!()
+    }
+    fn from_item(_item: ast::Item<Self::ItemKind>) -> Self {
+        unreachable!()
+    }
+    fn flatten_outputs(_outputs: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
+        unreachable!()
+    }
     fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}
     fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) {
     }
@@ -1106,6 +1119,21 @@ impl InvocationCollectorNode for P<ast::Item> {
             _ => unreachable!(),
         }
     }
+    fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
+        match &self.kind {
+            ItemKind::DelegationMac(deleg) => Some((deleg, self)),
+            _ => None,
+        }
+    }
+    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
+        ItemKind::Delegation(deleg)
+    }
+    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
+        P(item)
+    }
+    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
+        items.flatten().collect()
+    }
     fn wrap_flat_map_node_noop_flat_map(
         mut node: Self,
         collector: &mut InvocationCollector<'_, '_>,
@@ -1214,6 +1242,7 @@ impl InvocationCollectorNode for P<ast::Item> {
 struct TraitItemTag;
 impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag> {
     type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
+    type ItemKind = AssocItemKind;
     const KIND: AstFragmentKind = AstFragmentKind::TraitItems;
     fn to_annotatable(self) -> Annotatable {
         Annotatable::TraitItem(self.wrapped)
@@ -1234,11 +1263,27 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag>
             _ => unreachable!(),
         }
     }
+    fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
+        match &self.wrapped.kind {
+            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
+            _ => None,
+        }
+    }
+    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
+        AssocItemKind::Delegation(deleg)
+    }
+    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
+        AstNodeWrapper::new(P(item), TraitItemTag)
+    }
+    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
+        items.flatten().collect()
+    }
 }
 
 struct ImplItemTag;
 impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag> {
     type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
+    type ItemKind = AssocItemKind;
     const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
     fn to_annotatable(self) -> Annotatable {
         Annotatable::ImplItem(self.wrapped)
@@ -1259,6 +1304,21 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
             _ => unreachable!(),
         }
     }
+    fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
+        match &self.wrapped.kind {
+            AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
+            _ => None,
+        }
+    }
+    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
+        AssocItemKind::Delegation(deleg)
+    }
+    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
+        AstNodeWrapper::new(P(item), ImplItemTag)
+    }
+    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
+        items.flatten().collect()
+    }
 }
 
 impl InvocationCollectorNode for P<ast::ForeignItem> {
@@ -1420,6 +1480,24 @@ impl InvocationCollectorNode for ast::Stmt {
         };
         (mac, attrs, if add_semicolon { AddSemicolon::Yes } else { AddSemicolon::No })
     }
+    fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
+        match &self.kind {
+            StmtKind::Item(item) => match &item.kind {
+                ItemKind::DelegationMac(deleg) => Some((deleg, item)),
+                _ => None,
+            },
+            _ => None,
+        }
+    }
+    fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
+        ItemKind::Delegation(deleg)
+    }
+    fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
+        ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(P(item)) }
+    }
+    fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
+        items.flatten().collect()
+    }
     fn post_flat_map_node_collect_bang(stmts: &mut Self::OutputTy, add_semicolon: AddSemicolon) {
         // If this is a macro invocation with a semicolon, then apply that
         // semicolon to the final statement produced by expansion.
@@ -1818,6 +1896,40 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                     Node::post_flat_map_node_collect_bang(&mut res, add_semicolon);
                     res
                 }
+                None if let Some((deleg, item)) = node.delegation_list() => {
+                    if deleg.suffixes.is_empty() {
+                        // Report an error for now, to avoid keeping stem for resolution and
+                        // stability checks.
+                        self.cx.dcx().emit_err(EmptyDelegationList { span: item.span });
+                    }
+
+                    Node::flatten_outputs(deleg.suffixes.iter().map(|&(ident, rename)| {
+                        let mut path = deleg.prefix.clone();
+                        path.segments.push(ast::PathSegment {
+                            ident,
+                            id: ast::DUMMY_NODE_ID,
+                            args: None,
+                        });
+
+                        let mut item = Node::from_item(ast::Item {
+                            attrs: item.attrs.clone(),
+                            id: ast::DUMMY_NODE_ID,
+                            span: ident.span,
+                            vis: item.vis.clone(),
+                            ident: rename.unwrap_or(ident),
+                            kind: Node::delegation_item_kind(Box::new(ast::Delegation {
+                                id: ast::DUMMY_NODE_ID,
+                                qself: deleg.qself.clone(),
+                                path,
+                                rename,
+                                body: deleg.body.clone(),
+                            })),
+                            tokens: None,
+                        });
+
+                        assign_id!(self, item.node_id_mut(), || item.noop_flat_map(self))
+                    }))
+                }
                 None => {
                     match Node::wrap_flat_map_node_noop_flat_map(node, self, |mut node, this| {
                         assign_id!(this, node.node_id_mut(), || node.noop_flat_map(this))
@@ -1866,6 +1978,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         self.collect_bang(mac, Node::KIND).make_ast::<Node>()
                     })
                 }
+                None if node.delegation_list().is_some() => unreachable!(),
                 None => {
                     assign_id!(self, node.node_id_mut(), || node.noop_visit(self))
                 }
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 8239cfd46cb..128e9f48ff5 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -23,7 +23,7 @@ pub(crate) enum MetaVarExpr {
 
     /// The length of the repetition at a particular depth, where 0 is the inner-most
     /// repetition. The `usize` is the depth.
-    Length(usize),
+    Len(usize),
 }
 
 impl MetaVarExpr {
@@ -48,13 +48,13 @@ impl MetaVarExpr {
                 MetaVarExpr::Ignore(parse_ident(&mut iter, psess, ident.span)?)
             }
             "index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?),
-            "length" => MetaVarExpr::Length(parse_depth(&mut iter, psess, ident.span)?),
+            "len" => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?),
             _ => {
                 let err_msg = "unrecognized meta-variable expression";
                 let mut err = psess.dcx.struct_span_err(ident.span, err_msg);
                 err.span_suggestion(
                     ident.span,
-                    "supported expressions are count, ignore, index and length",
+                    "supported expressions are count, ignore, index and len",
                     "",
                     Applicability::MachineApplicable,
                 );
@@ -68,7 +68,7 @@ impl MetaVarExpr {
     pub(crate) fn ident(&self) -> Option<Ident> {
         match *self {
             MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(ident),
-            MetaVarExpr::Index(..) | MetaVarExpr::Length(..) => None,
+            MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
         }
     }
 }
@@ -111,7 +111,7 @@ fn parse_count<'psess>(
     Ok(MetaVarExpr::Count(ident, depth))
 }
 
-/// Parses the depth used by index(depth) and length(depth).
+/// Parses the depth used by index(depth) and len(depth).
 fn parse_depth<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
     psess: &'psess ParseSess,
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 06c1612ddba..2e5596f51c3 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -357,7 +357,7 @@ fn parse_sep_and_kleene_op<'a>(
 
 // `$$` or a meta-variable is the lhs of a macro but shouldn't.
 //
-// For example, `macro_rules! foo { ( ${length()} ) => {} }`
+// For example, `macro_rules! foo { ( ${len()} ) => {} }`
 fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &Session, token: &Token) {
     sess.dcx()
         .span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token)));
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index e35eba0f859..3901b82eb52 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -685,14 +685,14 @@ fn transcribe_metavar_expr<'a>(
             }
             None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "index")),
         },
-        MetaVarExpr::Length(depth) => match repeats.iter().nth_back(depth) {
+        MetaVarExpr::Len(depth) => match repeats.iter().nth_back(depth) {
             Some((_, length)) => {
                 result.push(TokenTree::token_alone(
                     TokenKind::lit(token::Integer, sym::integer(*length), None),
                     visited_span(),
                 ));
             }
-            None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "length")),
+            None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "len")),
         },
     }
     Ok(())
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 706f6f875bf..6da5adc7a6e 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -938,14 +938,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
     }
 
-    pub fn get_conversion_methods(
+    pub fn get_conversion_methods_for_diagnostic(
         &self,
         span: Span,
         expected: Ty<'tcx>,
         checked_ty: Ty<'tcx>,
         hir_id: hir::HirId,
     ) -> Vec<AssocItem> {
-        let methods = self.probe_for_return_type(
+        let methods = self.probe_for_return_type_for_diagnostic(
             span,
             probe::Mode::MethodCall,
             expected,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f283c013805..5a9eab1ffea 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2414,7 +2414,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let guar = if field.name == kw::Empty {
             self.dcx().span_delayed_bug(field.span, "field name with no name")
-        } else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) {
+        } else if self.method_exists_for_diagnostic(
+            field,
+            base_ty,
+            expr.hir_id,
+            expected.only_has_type(self),
+        ) {
             self.ban_take_value_of_method(expr, base_ty, field)
         } else if !base_ty.is_primitive_ty() {
             self.ban_nonexisting_field(field, base, expr, base_ty)
@@ -2600,7 +2605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut err = self.private_field_err(field, base_did);
 
         // Also check if an accessible method exists, which is often what is meant.
-        if self.method_exists(field, expr_t, expr.hir_id, return_ty)
+        if self.method_exists_for_diagnostic(field, expr_t, expr.hir_id, return_ty)
             && !self.expr_in_place(expr.hir_id)
         {
             self.suggest_method_call(
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 1864c7e6ef8..89f62577506 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -18,12 +18,12 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{HirId, PatKind};
-use rustc_middle::{bug, span_bug};
 use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{
     self, adjustment, AdtKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use rustc_trait_selection::infer::InferCtxtExt;
@@ -1181,6 +1181,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
                 return Ok(*first_ty);
             }
+        } else if let PatKind::Ref(subpat, _) = pat.kind
+            && self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id)
+        {
+            return self.pat_ty_adjusted(subpat);
         }
 
         self.pat_ty_unadjusted(pat)
@@ -1712,6 +1716,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 self.cat_pattern(place_with_id, subpat, op)?;
             }
 
+            PatKind::Ref(subpat, _)
+                if self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id) =>
+            {
+                self.cat_pattern(place_with_id, subpat, op)?;
+            }
+
             PatKind::Box(subpat) | PatKind::Ref(subpat, _) => {
                 // box p1, &p1, &mut p1. we can ignore the mutability of
                 // PatKind::Ref since that information is already contained
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 11f288391c3..fe0dd4e393f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -290,7 +290,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) -> bool {
         let expr = expr.peel_blocks();
-        let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
+        let methods =
+            self.get_conversion_methods_for_diagnostic(expr.span, expected, found, expr.hir_id);
 
         if let Some((suggestion, msg, applicability, verbose, annotation)) =
             self.suggest_deref_or_ref(expr, found, expected)
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index f82182fa058..a40fa600c19 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -91,7 +91,7 @@ pub enum CandidateSource {
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Determines whether the type `self_ty` supports a visible method named `method_name` or not.
     #[instrument(level = "debug", skip(self))]
-    pub fn method_exists(
+    pub fn method_exists_for_diagnostic(
         &self,
         method_name: Ident,
         self_ty: Ty<'tcx>,
@@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             probe::Mode::MethodCall,
             method_name,
             return_type,
-            IsSuggestion(false),
+            IsSuggestion(true),
             self_ty,
             call_expr_id,
             ProbeScope::TraitsInScope,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 81e179c9090..6cfdacf6a24 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -90,6 +90,11 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
     >,
 
     scope_expr_id: HirId,
+
+    /// Is this probe being done for a diagnostic? This will skip some error reporting
+    /// machinery, since we don't particularly care about, for example, similarly named
+    /// candidates if we're *reporting* similarly named candidates.
+    is_suggestion: IsSuggestion,
 }
 
 impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
@@ -220,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// would use to decide if a method is a plausible fit for
     /// ambiguity purposes).
     #[instrument(level = "debug", skip(self, candidate_filter))]
-    pub fn probe_for_return_type(
+    pub fn probe_for_return_type_for_diagnostic(
         &self,
         span: Span,
         mode: Mode,
@@ -459,6 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &orig_values,
                 steps.steps,
                 scope_expr_id,
+                is_suggestion,
             );
 
             probe_cx.assemble_inherent_candidates();
@@ -553,6 +559,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
         steps: &'tcx [CandidateStep<'tcx>],
         scope_expr_id: HirId,
+        is_suggestion: IsSuggestion,
     ) -> ProbeContext<'a, 'tcx> {
         ProbeContext {
             fcx,
@@ -570,6 +577,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             static_candidates: RefCell::new(Vec::new()),
             unsatisfied_predicates: RefCell::new(Vec::new()),
             scope_expr_id,
+            is_suggestion,
         }
     }
 
@@ -944,6 +952,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             return r;
         }
 
+        // If it's a `lookup_probe_for_diagnostic`, then quit early. No need to
+        // probe for other candidates.
+        if self.is_suggestion.0 {
+            return Err(MethodError::NoMatch(NoMatchData {
+                static_candidates: vec![],
+                unsatisfied_predicates: vec![],
+                out_of_scope_traits: vec![],
+                similar_candidate: None,
+                mode: self.mode,
+            }));
+        }
+
         debug!("pick: actual search failed, assemble diagnostics");
 
         let static_candidates = std::mem::take(self.static_candidates.get_mut());
@@ -1631,6 +1651,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 self.orig_steps_var_values,
                 self.steps,
                 self.scope_expr_id,
+                IsSuggestion(true),
             );
             pcx.allow_similar_names = true;
             pcx.assemble_inherent_candidates();
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index d50e9943384..db510d44392 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1143,7 +1143,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
 
-        let label_span_not_found = |err: &mut Diag<'_>| {
+        let mut find_candidate_for_method = false;
+
+        let mut label_span_not_found = |err: &mut Diag<'_>| {
             if unsatisfied_predicates.is_empty() {
                 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
                 let is_string_or_ref_str = match rcvr_ty.kind() {
@@ -1219,6 +1221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.note(format!(
                             "the {item_kind} was found for\n{type_candidates}{additional_types}"
                         ));
+                        find_candidate_for_method = mode == Mode::MethodCall;
                     }
                 }
             } else {
@@ -1371,9 +1374,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
         }
-        // If an appropriate error source is not found, check method chain for possible candiates
-        if unsatisfied_predicates.is_empty()
-            && let Mode::MethodCall = mode
+
+        if !find_candidate_for_method {
+            self.lookup_segments_chain_for_no_match_method(
+                &mut err,
+                item_name,
+                item_kind,
+                source,
+                no_match_data,
+            );
+        }
+
+        self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
+        Some(err)
+    }
+
+    /// If an appropriate error source is not found, check method chain for possible candidates
+    fn lookup_segments_chain_for_no_match_method(
+        &self,
+        err: &mut Diag<'_>,
+        item_name: Ident,
+        item_kind: &str,
+        source: SelfSource<'tcx>,
+        no_match_data: &NoMatchData<'tcx>,
+    ) {
+        if no_match_data.unsatisfied_predicates.is_empty()
+            && let Mode::MethodCall = no_match_data.mode
             && let SelfSource::MethodCall(mut source_expr) = source
         {
             let mut stack_methods = vec![];
@@ -1394,6 +1420,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .unwrap_or(Ty::new_misc_error(self.tcx)),
                 );
 
+                // FIXME: `probe_for_name_many` searches for methods in inherent implementations,
+                // so it may return a candidate that doesn't belong to this `revr_ty`. We need to
+                // check whether the instantiated type matches the received one.
                 for _matched_method in self.probe_for_name_many(
                     Mode::MethodCall,
                     item_name,
@@ -1416,8 +1445,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
         }
-        self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
-        Some(err)
     }
 
     fn find_likely_intended_associated_item(
@@ -2814,7 +2841,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Some(output_ty) => self.resolve_vars_if_possible(output_ty),
             _ => return,
         };
-        let method_exists = self.method_exists(item_name, output_ty, call.hir_id, return_type);
+        let method_exists =
+            self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type);
         debug!("suggest_await_before_method: is_method_exist={}", method_exists);
         if method_exists {
             err.span_suggestion_verbose(
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 8458b539335..5ad3ff71a6d 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -347,5 +347,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
                 "reduce the glob import's visibility or increase visibility of imported items",
             );
         }
+        BuiltinLintDiag::MaybeTypo { span, name } => {
+            diag.span_suggestion_verbose(
+                span,
+                "an attribute with a similar name exists",
+                name,
+                Applicability::MachineApplicable,
+            );
+        }
     }
 }
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index ed165188787..e06e3e9b805 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -663,6 +663,10 @@ pub enum BuiltinLintDiag {
         span: Span,
         max_vis: String,
     },
+    MaybeTypo {
+        span: Span,
+        name: Symbol,
+    },
 }
 
 /// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 477303e2434..7f9a5a366d7 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -129,17 +129,11 @@ pub enum CoverageKind {
     /// Marks the point in MIR control flow represented by a evaluated condition.
     ///
     /// This is eventually lowered to `llvm.instrprof.mcdc.condbitmap.update` in LLVM IR.
-    ///
-    /// If this statement does not survive MIR optimizations, the condition would never be
-    /// taken as evaluated.
     CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 },
 
     /// Marks the point in MIR control flow represented by a evaluated decision.
     ///
     /// This is eventually lowered to `llvm.instrprof.mcdc.tvbitmap.update` in LLVM IR.
-    ///
-    /// If this statement does not survive MIR optimizations, the decision would never be
-    /// taken as evaluated.
     TestVectorBitmapUpdate { bitmap_idx: u32, decision_depth: u16 },
 }
 
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 9a7af6135e4..9d70231be3b 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -362,8 +362,4 @@ pub struct CoverageIdsInfo {
     /// InstrumentCoverage MIR pass, if the highest-numbered counter increments
     /// were removed by MIR optimizations.
     pub max_counter_id: mir::coverage::CounterId,
-
-    /// Coverage codegen for mcdc needs to know the size of the global bitmap so that it can
-    /// set the `bytemap-bytes` argument of the `llvm.instrprof.mcdc.tvbitmap.update` intrinsic.
-    pub mcdc_bitmap_bytes: u32,
 }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 4278ce823d0..e124b478f41 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1480,13 +1480,17 @@ pub enum BinOp {
     BitOr,
     /// The `<<` operator (shift left)
     ///
-    /// The offset is truncated to the size of the first operand and made unsigned before shifting.
+    /// The offset is (uniquely) determined as follows:
+    /// - it is "equal modulo LHS::BITS" to the RHS
+    /// - it is in the range `0..LHS::BITS`
     Shl,
     /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0
     ShlUnchecked,
     /// The `>>` operator (shift right)
     ///
-    /// The offset is truncated to the size of the first operand and made unsigned before shifting.
+    /// The offset is (uniquely) determined as follows:
+    /// - it is "equal modulo LHS::BITS" to the RHS
+    /// - it is in the range `0..LHS::BITS`
     ///
     /// This is an arithmetic shift if the LHS is signed
     /// and a logical shift if the LHS is unsigned.
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
index 2ddcb8aab25..9e944899026 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -153,6 +153,8 @@ pub enum ProbeKind<'tcx> {
     /// do a probe to find out what projection type(s) may be used to prove that
     /// the source type upholds all of the target type's object bounds.
     UpcastProjectionCompatibility,
+    /// Looking for param-env candidates that satisfy the trait ref for a projection.
+    ShadowedEnvProbing,
     /// Try to unify an opaque type with an existing key in the storage.
     OpaqueTypeStorageLookup { result: QueryResult<'tcx> },
 }
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index e652f0586c4..5b3c50cb973 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -118,6 +118,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
             ProbeKind::TraitCandidate { source, result } => {
                 write!(self.f, "CANDIDATE {source:?}: {result:?}")
             }
+            ProbeKind::ShadowedEnvProbing => {
+                write!(self.f, "PROBING FOR IMPLS SHADOWED BY PARAM-ENV CANDIDATE:")
+            }
         }?;
 
         self.nested(|this| {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 329d5f34a21..9dc30447f0e 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -7,8 +7,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
-use rustc_type_ir::ConstKind as IrConstKind;
-use rustc_type_ir::{TypeFlags, WithCachedTypeInfo};
+use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
 
 mod int;
 mod kind;
@@ -20,7 +19,8 @@ use rustc_span::Span;
 use rustc_span::DUMMY_SP;
 pub use valtree::*;
 
-pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
+pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
+pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
 
 #[cfg(target_pointer_width = "64")]
 rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
@@ -184,6 +184,14 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
         Const::new_bound(tcx, debruijn, var, ty)
     }
 
+    fn new_unevaluated(
+        interner: TyCtxt<'tcx>,
+        uv: ty::UnevaluatedConst<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> Self {
+        Const::new_unevaluated(interner, uv, ty)
+    }
+
     fn ty(self) -> Ty<'tcx> {
         self.ty()
     }
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 7e49b0ac915..d7ae050ed4d 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,30 +1,15 @@
 use super::Const;
 use crate::mir;
 use crate::ty::abstract_const::CastKind;
-use crate::ty::GenericArgsRef;
 use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
-use rustc_hir::def_id::DefId;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 
-/// An unevaluated (potentially generic) constant used in the type-system.
-#[derive(Copy, Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
-#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
-pub struct UnevaluatedConst<'tcx> {
-    pub def: DefId,
-    pub args: GenericArgsRef<'tcx>,
-}
-
-impl rustc_errors::IntoDiagArg for UnevaluatedConst<'_> {
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
-        format!("{self:?}").into_diag_arg()
-    }
-}
-
-impl<'tcx> UnevaluatedConst<'tcx> {
+#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
+impl<'tcx> ty::UnevaluatedConst<'tcx> {
     /// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this
     /// hurts performance.
     #[inline]
-    pub(crate) fn prepare_for_eval(
+    fn prepare_for_eval(
         self,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
@@ -55,13 +40,6 @@ impl<'tcx> UnevaluatedConst<'tcx> {
     }
 }
 
-impl<'tcx> UnevaluatedConst<'tcx> {
-    #[inline]
-    pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
-        UnevaluatedConst { def, args }
-    }
-}
-
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
 #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
 pub enum Expr<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index e831db1a41b..d7e185dd5e1 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -76,6 +76,7 @@ use rustc_type_ir::TyKind::*;
 use rustc_type_ir::WithCachedTypeInfo;
 use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
 
+use std::assert_matches::assert_matches;
 use std::borrow::Borrow;
 use std::cmp::Ordering;
 use std::fmt;
@@ -91,67 +92,124 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
     type AdtDef = ty::AdtDef<'tcx>;
     type GenericArgs = ty::GenericArgsRef<'tcx>;
+    type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>];
     type GenericArg = ty::GenericArg<'tcx>;
-    type Term = ty::Term<'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 CanonicalVars = CanonicalVarInfos<'tcx>;
 
+    type CanonicalVars = CanonicalVarInfos<'tcx>;
     type Ty = Ty<'tcx>;
     type Tys = &'tcx List<Ty<'tcx>>;
-    type AliasTy = ty::AliasTy<'tcx>;
     type ParamTy = ParamTy;
     type BoundTy = ty::BoundTy;
     type PlaceholderTy = ty::PlaceholderType;
-    type ErrorGuaranteed = ErrorGuaranteed;
 
+    type ErrorGuaranteed = ErrorGuaranteed;
     type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
     type PolyFnSig = PolyFnSig<'tcx>;
     type AllocId = crate::mir::interpret::AllocId;
-    type Pat = Pattern<'tcx>;
 
+    type Pat = Pattern<'tcx>;
     type Const = ty::Const<'tcx>;
     type AliasConst = ty::UnevaluatedConst<'tcx>;
     type PlaceholderConst = ty::PlaceholderConst;
     type ParamConst = ty::ParamConst;
     type BoundConst = ty::BoundVar;
     type ValueConst = ty::ValTree<'tcx>;
-    type ExprConst = ty::Expr<'tcx>;
 
+    type ExprConst = ty::Expr<'tcx>;
     type Region = Region<'tcx>;
     type EarlyParamRegion = ty::EarlyParamRegion;
     type LateParamRegion = ty::LateParamRegion;
     type BoundRegion = ty::BoundRegion;
     type InferRegion = ty::RegionVid;
-    type PlaceholderRegion = ty::PlaceholderRegion;
 
+    type PlaceholderRegion = ty::PlaceholderRegion;
     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 AliasTerm = ty::AliasTerm<'tcx>;
     type NormalizesTo = ty::NormalizesTo<'tcx>;
     type SubtypePredicate = ty::SubtypePredicate<'tcx>;
     type CoercePredicate = ty::CoercePredicate<'tcx>;
     type ClosureKind = ty::ClosureKind;
-    type Clauses = ty::Clauses<'tcx>;
 
+    type Clauses = ty::Clauses<'tcx>;
     fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
         self.mk_canonical_var_infos(infos)
     }
 
     type GenericsOf = &'tcx ty::Generics;
+
     fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics {
         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 alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind {
+        match self.def_kind(alias.def_id) {
+            DefKind::AssocTy => {
+                if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id))
+                {
+                    ty::Inherent
+                } else {
+                    ty::Projection
+                }
+            }
+            DefKind::OpaqueTy => ty::Opaque,
+            DefKind::TyAlias => ty::Weak,
+            kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
+        }
+    }
+
+    fn alias_term_kind(self, alias: ty::AliasTerm<'tcx>) -> ty::AliasTermKind {
+        match self.def_kind(alias.def_id) {
+            DefKind::AssocTy => {
+                if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id))
+                {
+                    ty::AliasTermKind::InherentTy
+                } else {
+                    ty::AliasTermKind::ProjectionTy
+                }
+            }
+            DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
+            DefKind::TyAlias => ty::AliasTermKind::WeakTy,
+            DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
+            DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
+            kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
+        }
+    }
+
+    fn trait_ref_and_own_args_for_alias(
+        self,
+        def_id: Self::DefId,
+        args: Self::GenericArgs,
+    ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
+        assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst);
+        let trait_def_id = self.parent(def_id);
+        assert_matches!(self.def_kind(trait_def_id), DefKind::Trait);
+        let trait_generics = self.generics_of(trait_def_id);
+        (
+            ty::TraitRef::new(self, trait_def_id, args.truncate_to(self, trait_generics)),
+            &args[trait_generics.count()..],
+        )
+    }
+
     fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
         self.mk_args(args)
     }
 
+    fn mk_args_from_iter(self, args: impl Iterator<Item = Self::GenericArg>) -> Self::GenericArgs {
+        self.mk_args_from_iter(args)
+    }
+
     fn check_and_mk_args(
         self,
         def_id: DefId,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index dc5e881843a..93ccc0a7de4 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -96,9 +96,9 @@ pub use self::list::{List, ListWithCachedTypeInfo};
 pub use self::parameterized::ParameterizedOverTcx;
 pub use self::pattern::{Pattern, PatternKind};
 pub use self::predicate::{
-    Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialPredicateStableCmpExt,
-    ExistentialProjection, ExistentialTraitRef, NormalizesTo, OutlivesPredicate,
-    PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
+    AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
+    ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, NormalizesTo,
+    OutlivesPredicate, PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
     PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
     PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate,
     PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
@@ -110,11 +110,11 @@ pub use self::region::{
 };
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::{
-    AliasTerm, 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,
+    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,
 };
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index e78856517b2..16ca098853e 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -13,6 +13,7 @@ use crate::ty::{
 };
 
 pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
+pub type AliasTerm<'tcx> = ir::AliasTerm<TyCtxt<'tcx>>;
 pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>;
 pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
 pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 8d8ed70a757..3577db7234d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3038,6 +3038,33 @@ define_print! {
         p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
     }
 
+    ty::AliasTy<'tcx> {
+        let alias_term: ty::AliasTerm<'tcx> = (*self).into();
+        p!(print(alias_term))
+    }
+
+    ty::AliasTerm<'tcx> {
+        match self.kind(cx.tcx()) {
+            ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
+            ty::AliasTermKind::ProjectionTy
+            | ty::AliasTermKind::WeakTy
+            | ty::AliasTermKind::OpaqueTy
+            | ty::AliasTermKind::UnevaluatedConst
+            | ty::AliasTermKind::ProjectionConst => {
+                // If we're printing verbosely, or don't want to invoke queries
+                // (`is_impl_trait_in_trait`), then fall back to printing the def path.
+                // This is likely what you want if you're debugging the compiler anyways.
+                if !(cx.should_print_verbose() || with_reduced_queries())
+                    && cx.tcx().is_impl_trait_in_trait(self.def_id)
+                {
+                    return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
+                } else {
+                    p!(print_def_path(self.def_id, self.args));
+                }
+            }
+        }
+    }
+
     ty::TraitPredicate<'tcx> {
         p!(print(self.trait_ref.self_ty()), ": ");
         p!(pretty_print_bound_constness(self.trait_ref));
@@ -3205,33 +3232,6 @@ define_print_and_forward_display! {
       }
     }
 
-    ty::AliasTy<'tcx> {
-        let alias_term: ty::AliasTerm<'tcx> = (*self).into();
-        p!(print(alias_term))
-    }
-
-    ty::AliasTerm<'tcx> {
-        match self.kind(cx.tcx()) {
-            ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
-            ty::AliasTermKind::ProjectionTy
-            | ty::AliasTermKind::WeakTy
-            | ty::AliasTermKind::OpaqueTy
-            | ty::AliasTermKind::UnevaluatedConst
-            | ty::AliasTermKind::ProjectionConst => {
-                // If we're printing verbosely, or don't want to invoke queries
-                // (`is_impl_trait_in_trait`), then fall back to printing the def path.
-                // This is likely what you want if you're debugging the compiler anyways.
-                if !(cx.should_print_verbose() || with_reduced_queries())
-                    && cx.tcx().is_impl_trait_in_trait(self.def_id)
-                {
-                    return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
-                } else {
-                    p!(print_def_path(self.def_id, self.args));
-                }
-            }
-        }
-    }
-
     ty::Predicate<'tcx> {
         p!(print(self.kind()))
     }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 6abd685343b..7523cd15320 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -7,7 +7,7 @@ use crate::mir::interpret;
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
 use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
 use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
+use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
 use rustc_ast_ir::try_visit;
 use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::def::Namespace;
@@ -164,23 +164,6 @@ impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Debug for AliasTy<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTy<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        f.debug_struct("AliasTy")
-            .field("args", &this.map(|data| data.args))
-            .field("def_id", &this.data.def_id)
-            .finish()
-    }
-}
-
 impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Pattern<'tcx> {
     fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
         this: WithInfcx<'_, Infcx, &Self>,
@@ -230,23 +213,6 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut core::fmt::Formatter<'_>,
-    ) -> core::fmt::Result {
-        f.debug_struct("UnevaluatedConst")
-            .field("def", &this.data.def)
-            .field("args", &this.wrap(this.data.args))
-            .finish()
-    }
-}
-
 impl<'tcx> fmt::Debug for ty::Const<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         WithInfcx::with_no_infcx(self).fmt(f)
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 16301633247..74b03d6db66 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -28,20 +28,17 @@ use std::iter;
 use std::ops::{ControlFlow, Deref, Range};
 use ty::util::IntTypeExt;
 
-use rustc_type_ir::BoundVar;
-use rustc_type_ir::CollectAndApply;
-use rustc_type_ir::DynKind;
-use rustc_type_ir::TyKind as IrTyKind;
 use rustc_type_ir::TyKind::*;
-use rustc_type_ir::TypeAndMut as IrTypeAndMut;
+use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind};
 
 use super::fold::FnMutDelegate;
 use super::GenericParamDefKind;
 
 // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
 #[rustc_diagnostic_item = "TyKind"]
-pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
-pub type TypeAndMut<'tcx> = IrTypeAndMut<TyCtxt<'tcx>>;
+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 trait Article {
     fn article(&self) -> &'static str;
@@ -1105,371 +1102,6 @@ where
     }
 }
 
-/// Represents the unprojected term of a projection goal.
-///
-/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
-/// * For an inherent projection, this would be `Ty::N<...>`.
-/// * For an opaque type, there is no explicit syntax.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct AliasTerm<'tcx> {
-    /// The parameters of the associated or opaque item.
-    ///
-    /// For a projection, these are the generic parameters for the trait and the
-    /// GAT parameters, if there are any.
-    ///
-    /// For an inherent projection, they consist of the self type and the GAT parameters,
-    /// if there are any.
-    ///
-    /// For RPIT the generic parameters are for the generics of the function,
-    /// while for TAIT it is used for the generic parameters of the alias.
-    pub args: GenericArgsRef<'tcx>,
-
-    /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
-    /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
-    /// this is an opaque.
-    ///
-    /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
-    /// underlying type if the type is an opaque.
-    ///
-    /// Note that if this is an associated type, this is not the `DefId` of the
-    /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
-    /// aka. `tcx.parent(def_id)`.
-    pub def_id: DefId,
-
-    /// This field exists to prevent the creation of `AliasTerm` without using
-    /// [AliasTerm::new].
-    _use_alias_term_new_instead: (),
-}
-
-// FIXME: Remove these when we uplift `AliasTerm`
-use crate::ty::{DebugWithInfcx, InferCtxtLike, WithInfcx};
-impl<'tcx> std::fmt::Debug for AliasTerm<'tcx> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        WithInfcx::with_no_infcx(self).fmt(f)
-    }
-}
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTerm<'tcx> {
-    fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
-        this: WithInfcx<'_, Infcx, &Self>,
-        f: &mut std::fmt::Formatter<'_>,
-    ) -> std::fmt::Result {
-        f.debug_struct("AliasTerm")
-            .field("args", &this.map(|data| data.args))
-            .field("def_id", &this.data.def_id)
-            .finish()
-    }
-}
-
-impl<'tcx> rustc_type_ir::inherent::AliasTerm<TyCtxt<'tcx>> for AliasTerm<'tcx> {
-    fn new(
-        interner: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
-    ) -> Self {
-        AliasTerm::new(interner, trait_def_id, args)
-    }
-
-    fn def_id(self) -> DefId {
-        self.def_id
-    }
-
-    fn args(self) -> ty::GenericArgsRef<'tcx> {
-        self.args
-    }
-
-    fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId {
-        self.trait_def_id(interner)
-    }
-
-    fn self_ty(self) -> Ty<'tcx> {
-        self.self_ty()
-    }
-
-    fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        self.with_self_ty(tcx, self_ty)
-    }
-}
-
-impl<'tcx> AliasTerm<'tcx> {
-    pub fn new(
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
-        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
-    ) -> AliasTerm<'tcx> {
-        let args = tcx.check_and_mk_args(def_id, args);
-        AliasTerm { def_id, args, _use_alias_term_new_instead: () }
-    }
-
-    pub fn expect_ty(self, tcx: TyCtxt<'tcx>) -> AliasTy<'tcx> {
-        match self.kind(tcx) {
-            ty::AliasTermKind::ProjectionTy
-            | ty::AliasTermKind::InherentTy
-            | ty::AliasTermKind::OpaqueTy
-            | ty::AliasTermKind::WeakTy => {}
-            ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
-                bug!("Cannot turn `UnevaluatedConst` into `AliasTy`")
-            }
-        }
-        ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
-    }
-
-    pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTermKind {
-        match tcx.def_kind(self.def_id) {
-            DefKind::AssocTy => {
-                if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) {
-                    ty::AliasTermKind::InherentTy
-                } else {
-                    ty::AliasTermKind::ProjectionTy
-                }
-            }
-            DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
-            DefKind::TyAlias => ty::AliasTermKind::WeakTy,
-            DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
-            DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
-            kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
-        }
-    }
-}
-
-/// The following methods work only with (trait) associated item projections.
-impl<'tcx> AliasTerm<'tcx> {
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.args.type_at(0)
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        AliasTerm::new(
-            tcx,
-            self.def_id,
-            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
-        )
-    }
-
-    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),
-            kind => bug!("expected a projection AliasTy; found {kind:?}"),
-        }
-    }
-
-    /// Extracts the underlying trait reference from this projection.
-    /// For example, if this is a projection of `<T as Iterator>::Item`,
-    /// then this function would return a `T: Iterator` trait reference.
-    ///
-    /// NOTE: This will drop the args for generic associated types
-    /// consider calling [Self::trait_ref_and_own_args] to get those
-    /// as well.
-    pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
-        let def_id = self.trait_def_id(tcx);
-        ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id)))
-    }
-
-    /// Extracts the underlying trait reference and own args from this projection.
-    /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
-    /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args
-    pub fn trait_ref_and_own_args(
-        self,
-        tcx: TyCtxt<'tcx>,
-    ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
-        let trait_def_id = self.trait_def_id(tcx);
-        let trait_generics = tcx.generics_of(trait_def_id);
-        (
-            ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)),
-            &self.args[trait_generics.count()..],
-        )
-    }
-
-    pub fn to_term(self, tcx: TyCtxt<'tcx>) -> ty::Term<'tcx> {
-        match self.kind(tcx) {
-            ty::AliasTermKind::ProjectionTy => Ty::new_alias(
-                tcx,
-                ty::Projection,
-                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
-            )
-            .into(),
-            ty::AliasTermKind::InherentTy => Ty::new_alias(
-                tcx,
-                ty::Inherent,
-                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
-            )
-            .into(),
-            ty::AliasTermKind::OpaqueTy => Ty::new_alias(
-                tcx,
-                ty::Opaque,
-                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
-            )
-            .into(),
-            ty::AliasTermKind::WeakTy => Ty::new_alias(
-                tcx,
-                ty::Weak,
-                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
-            )
-            .into(),
-            ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
-                ty::Const::new_unevaluated(
-                    tcx,
-                    ty::UnevaluatedConst::new(self.def_id, self.args),
-                    tcx.type_of(self.def_id).instantiate(tcx, self.args),
-                )
-                .into()
-            }
-        }
-    }
-}
-
-impl<'tcx> From<AliasTy<'tcx>> for AliasTerm<'tcx> {
-    fn from(ty: AliasTy<'tcx>) -> Self {
-        AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
-    }
-}
-
-impl<'tcx> From<ty::UnevaluatedConst<'tcx>> for AliasTerm<'tcx> {
-    fn from(ct: ty::UnevaluatedConst<'tcx>) -> Self {
-        AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
-    }
-}
-
-/// Represents the projection of an associated, opaque, or lazy-type-alias type.
-///
-/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
-/// * For an inherent projection, this would be `Ty::N<...>`.
-/// * For an opaque type, there is no explicit syntax.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct AliasTy<'tcx> {
-    /// The parameters of the associated or opaque type.
-    ///
-    /// For a projection, these are the generic parameters for the trait and the
-    /// GAT parameters, if there are any.
-    ///
-    /// For an inherent projection, they consist of the self type and the GAT parameters,
-    /// if there are any.
-    ///
-    /// For RPIT the generic parameters are for the generics of the function,
-    /// while for TAIT it is used for the generic parameters of the alias.
-    pub args: GenericArgsRef<'tcx>,
-
-    /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
-    /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
-    /// this is an opaque.
-    ///
-    /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
-    /// underlying type if the type is an opaque.
-    ///
-    /// Note that if this is an associated type, this is not the `DefId` of the
-    /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
-    /// aka. `tcx.parent(def_id)`.
-    pub def_id: DefId,
-
-    /// This field exists to prevent the creation of `AliasT` without using
-    /// [AliasTy::new].
-    _use_alias_ty_new_instead: (),
-}
-
-impl<'tcx> AliasTy<'tcx> {
-    pub fn new(
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
-        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
-    ) -> ty::AliasTy<'tcx> {
-        let args = tcx.check_and_mk_args(def_id, args);
-        ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () }
-    }
-
-    pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTyKind {
-        match tcx.def_kind(self.def_id) {
-            DefKind::AssocTy
-                if let DefKind::Impl { of_trait: false } =
-                    tcx.def_kind(tcx.parent(self.def_id)) =>
-            {
-                ty::Inherent
-            }
-            DefKind::AssocTy => ty::Projection,
-            DefKind::OpaqueTy => ty::Opaque,
-            DefKind::TyAlias => ty::Weak,
-            kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
-        }
-    }
-
-    /// Whether this alias type is an opaque.
-    pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool {
-        matches!(self.kind(tcx), ty::Opaque)
-    }
-
-    pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        Ty::new_alias(tcx, self.kind(tcx), self)
-    }
-}
-
-/// The following methods work only with (trait) associated type projections.
-impl<'tcx> AliasTy<'tcx> {
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.args.type_at(0)
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1)))
-    }
-
-    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),
-            kind => bug!("expected a projection AliasTy; found {kind:?}"),
-        }
-    }
-
-    /// Extracts the underlying trait reference and own args from this projection.
-    /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
-    /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args
-    pub fn trait_ref_and_own_args(
-        self,
-        tcx: TyCtxt<'tcx>,
-    ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
-        let trait_def_id = self.trait_def_id(tcx);
-        let trait_generics = tcx.generics_of(trait_def_id);
-        (
-            ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)),
-            &self.args[trait_generics.count()..],
-        )
-    }
-
-    /// Extracts the underlying trait reference from this projection.
-    /// For example, if this is a projection of `<T as Iterator>::Item`,
-    /// then this function would return a `T: Iterator` trait reference.
-    ///
-    /// WARNING: This will drop the args for generic associated types
-    /// consider calling [Self::trait_ref_and_own_args] to get those
-    /// as well.
-    pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
-        let def_id = self.trait_def_id(tcx);
-        ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id)))
-    }
-}
-
-/// The following methods work only with inherent associated type projections.
-impl<'tcx> AliasTy<'tcx> {
-    /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that.
-    ///
-    /// Does the following transformation:
-    ///
-    /// ```text
-    /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
-    ///
-    ///     I_i impl args
-    ///     P_j GAT args
-    /// ```
-    pub fn rebase_inherent_args_onto_impl(
-        self,
-        impl_args: ty::GenericArgsRef<'tcx>,
-        tcx: TyCtxt<'tcx>,
-    ) -> ty::GenericArgsRef<'tcx> {
-        debug_assert_eq!(self.kind(tcx), ty::Inherent);
-
-        tcx.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1)))
-    }
-}
-
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
 pub struct GenSig<'tcx> {
     pub resume_ty: Ty<'tcx>,
@@ -2020,6 +1652,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
     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 })
     }
+
+    fn new_alias(
+        interner: TyCtxt<'tcx>,
+        kind: ty::AliasTyKind,
+        alias_ty: ty::AliasTy<'tcx>,
+    ) -> Self {
+        Ty::new_alias(interner, kind, alias_ty)
+    }
 }
 
 /// Type utilities
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 04ce3de8874..7f3d6a713d9 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1130,7 +1130,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for WeakAliasTypeExpander<'tcx> {
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if !ct.ty().has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
+        if !ct.has_type_flags(ty::TypeFlags::HAS_TY_WEAK) {
             return ct;
         }
         ct.super_fold_with(self)
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index f77ee63d02c..65715253647 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -61,17 +61,7 @@ fn coverage_ids_info<'tcx>(
         .max()
         .unwrap_or(CounterId::ZERO);
 
-    let mcdc_bitmap_bytes = mir_body
-        .coverage_branch_info
-        .as_deref()
-        .map(|info| {
-            info.mcdc_decision_spans
-                .iter()
-                .fold(0, |acc, decision| acc + (1_u32 << decision.conditions_num).div_ceil(8))
-        })
-        .unwrap_or_default();
-
-    CoverageIdsInfo { max_counter_id, mcdc_bitmap_bytes }
+    CoverageIdsInfo { max_counter_id }
 }
 
 fn all_coverage_in_mir_body<'a, 'tcx>(
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 34cdf8a9b5f..3e1be6461eb 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -686,20 +686,35 @@ impl<'a> Parser<'a> {
             (None, self.parse_path(PathStyle::Expr)?)
         };
 
-        let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None };
+        let rename = |this: &mut Self| {
+            Ok(if this.eat_keyword(kw::As) { Some(this.parse_ident()?) } else { None })
+        };
+        let body = |this: &mut Self| {
+            Ok(if this.check(&token::OpenDelim(Delimiter::Brace)) {
+                Some(this.parse_block()?)
+            } else {
+                this.expect(&token::Semi)?;
+                None
+            })
+        };
 
-        let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
-            Some(self.parse_block()?)
+        let (ident, item_kind) = if self.eat(&token::PathSep) {
+            let (suffixes, _) = self.parse_delim_comma_seq(Delimiter::Brace, |p| {
+                Ok((p.parse_path_segment_ident()?, rename(p)?))
+            })?;
+            let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? };
+            (Ident::empty(), ItemKind::DelegationMac(Box::new(deleg)))
         } else {
-            self.expect(&token::Semi)?;
-            None
+            let rename = rename(self)?;
+            let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
+            let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body: body(self)? };
+            (ident, ItemKind::Delegation(Box::new(deleg)))
         };
+
         let span = span.to(self.prev_token.span);
         self.psess.gated_spans.gate(sym::fn_delegation, span);
 
-        let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
-        let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body };
-        Ok((ident, ItemKind::Delegation(Box::new(deleg))))
+        Ok((ident, item_kind))
     }
 
     fn parse_item_list<T>(
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index c37d3f0441d..d845e8ab90d 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -95,12 +95,15 @@ impl<'a> Parser<'a> {
             debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
         }
 
-        if !self.recover_colon_before_qpath_proj() {
+        let is_import_coupler = self.is_import_coupler();
+        if !is_import_coupler && !self.recover_colon_before_qpath_proj() {
             self.expect(&token::PathSep)?;
         }
 
         let qself = P(QSelf { ty, path_span, position: path.segments.len() });
-        self.parse_path_segments(&mut path.segments, style, None)?;
+        if !is_import_coupler {
+            self.parse_path_segments(&mut path.segments, style, None)?;
+        }
 
         Ok((
             qself,
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index d7664d1c1ff..a980d5dcaba 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -522,7 +522,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
                 Impl,
                 MacCall,
                 MacroDef,
-                Delegation
+                Delegation,
+                DelegationMac
             ]
         );
         ast_visit::walk_item(self, i)
@@ -650,7 +651,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
         record_variants!(
             (self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind),
-            [Const, Fn, Type, MacCall, Delegation]
+            [Const, Fn, Type, MacCall, Delegation, DelegationMac]
         );
         ast_visit::walk_assoc_item(self, i, ctxt);
     }
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index c1da8928f30..a5fa94faead 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -285,7 +285,9 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
             ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias,
             ast::ItemKind::Impl(_) => Target::Impl,
             ast::ItemKind::MacroDef(_) => Target::MacroDef,
-            ast::ItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
+            ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => {
+                unreachable!("macros should have been expanded")
+            }
         };
 
         self.check_for_lang(
@@ -340,7 +342,9 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
             }
             ast::AssocItemKind::Const(ct) => (Target::AssocConst, Some(&ct.generics)),
             ast::AssocItemKind::Type(ty) => (Target::AssocTy, Some(&ty.generics)),
-            ast::AssocItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
+            ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(_) => {
+                unreachable!("macros should have been expanded")
+            }
         };
 
         self.check_for_lang(
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 3467f1c3edf..3e9aa3e0a6f 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -825,7 +825,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
             ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
 
-            ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(),
+            ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
+                unreachable!()
+            }
         }
     }
 
@@ -1381,7 +1383,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 | AssocItemKind::Delegation(..)
                 | AssocItemKind::Fn(..) => ValueNS,
                 AssocItemKind::Type(..) => TypeNS,
-                AssocItemKind::MacCall(_) => bug!(), // handled above
+                AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above
             };
 
             let parent = self.parent_scope.module;
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index a27a6bceda3..741a650da55 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -139,6 +139,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
             ItemKind::Use(..) => return visit::walk_item(self, i),
             ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
+            ItemKind::DelegationMac(..) => unreachable!(),
         };
         let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span);
 
@@ -278,6 +279,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             AssocItemKind::Const(..) => DefKind::AssocConst,
             AssocItemKind::Type(..) => DefKind::AssocTy,
             AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
+            AssocItemKind::DelegationMac(..) => unreachable!(),
         };
 
         let def = self.create_def(i.id, i.ident.name, def_kind, i.span);
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 3443bbe6e11..074bf810eaf 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -236,7 +236,7 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't
             ast::ItemKind::Impl(..) => return,
 
             // Should be unreachable at this stage
-            ast::ItemKind::MacCall(..) => panic!(
+            ast::ItemKind::MacCall(..) | ast::ItemKind::DelegationMac(..) => panic!(
                 "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
             ),
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 5dd95a1896b..322f2922f92 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2561,7 +2561,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
             ItemKind::ExternCrate(..) => {}
 
-            ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
+            ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
+                panic!("unexpanded macro in resolve!")
+            }
         }
     }
 
@@ -2849,7 +2851,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
                         walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
                     }),
-                AssocItemKind::MacCall(_) => {
+                AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
                     panic!("unexpanded macro in resolve!")
                 }
             };
@@ -3116,7 +3118,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     },
                 );
             }
-            AssocItemKind::MacCall(_) => {
+            AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
                 panic!("unexpanded macro in resolve!")
             }
         }
@@ -3218,7 +3220,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             AssocItemKind::Fn(..) => (E0324, "method"),
             AssocItemKind::Type(..) => (E0325, "type"),
             AssocItemKind::Delegation(..) => (E0324, "method"),
-            AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
+            AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
+                span_bug!(span, "unexpanded macro")
+            }
         };
         let trait_path = path_names_to_string(path);
         self.report_error(
@@ -4790,7 +4794,8 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
             | ItemKind::ExternCrate(..)
             | ItemKind::MacroDef(..)
             | ItemKind::GlobalAsm(..)
-            | ItemKind::MacCall(..) => {}
+            | ItemKind::MacCall(..)
+            | ItemKind::DelegationMac(..) => {}
             ItemKind::Delegation(..) => {
                 // Delegated functions have lifetimes, their count is not necessarily zero.
                 // But skipping the delegation items here doesn't mean that the count will be considered zero,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 64451030adf..12815291c1d 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2045,7 +2045,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                             AssocSuggestion::MethodWithSelf { called }
                         }
                         ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called },
-                        ast::AssocItemKind::MacCall(_) => continue,
+                        ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(..) => {
+                            continue;
+                        }
                     });
                 }
             }
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 35bf3f761df..e3cfe6a6e05 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -29,6 +29,7 @@ use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE};
 use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES};
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::feature_err;
+use rustc_span::edit_distance::edit_distance;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
 use rustc_span::hygiene::{AstPass, MacroKind};
@@ -568,15 +569,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
-            && path.segments.len() >= 2
-            && path.segments[0].ident.name == sym::diagnostic
-            && path.segments[1].ident.name != sym::on_unimplemented
+            && let [namespace, attribute, ..] = &*path.segments
+            && namespace.ident.name == sym::diagnostic
+            && attribute.ident.name != sym::on_unimplemented
         {
-            self.tcx.sess.psess.buffer_lint(
+            let distance =
+                edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
+
+            let help = if distance.is_some() {
+                BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented }
+            } else {
+                BuiltinLintDiag::Normal
+            };
+            self.tcx.sess.psess.buffer_lint_with_diagnostic(
                 UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
-                path.segments[1].span(),
+                attribute.span(),
                 node_id,
                 "unknown diagnostic attribute",
+                help,
             );
         }
 
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 919fa2140d5..fc79c9232d1 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -779,16 +779,21 @@ impl RiscvInterruptKind {
 /// Metadata describing how the arguments to a native function
 /// should be passed in order to respect the native ABI.
 ///
+/// The signature represented by this type may not match the MIR function signature.
+/// Certain attributes, like `#[track_caller]` can introduce additional arguments, which are present in [`FnAbi`], but not in `FnSig`.
+/// While this difference is rarely relevant, it should still be kept in mind.
+///
 /// I will do my best to describe this structure, but these
 /// comments are reverse-engineered and may be inaccurate. -NDM
 #[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)]
 pub struct FnAbi<'a, Ty> {
-    /// The LLVM types of each argument.
+    /// The type, layout, and information about how each argument is passed.
     pub args: Box<[ArgAbi<'a, Ty>]>,
 
-    /// LLVM return type.
+    /// The layout, type, and the way a value is returned from this function.
     pub ret: ArgAbi<'a, Ty>,
 
+    /// Marks this function as variadic (accepting a variable number of arguments).
     pub c_variadic: bool,
 
     /// The count of non-variadic arguments.
@@ -796,9 +801,9 @@ pub struct FnAbi<'a, Ty> {
     /// Should only be different from args.len() when c_variadic is true.
     /// This can be used to know whether an argument is variadic or not.
     pub fixed_count: u32,
-
+    /// The calling convention of this function.
     pub conv: Conv,
-
+    /// Indicates if an unwind may happen across a call to this function.
     pub can_unwind: bool,
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 9a027d7f937..97bea28f06a 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -1,7 +1,7 @@
 //! Code shared by trait and projection goals for candidate assembly.
 
 use crate::solve::GoalSource;
-use crate::solve::{inspect, EvalCtxt, SolverMode};
+use crate::solve::{EvalCtxt, SolverMode};
 use rustc_hir::def_id::DefId;
 use rustc_infer::traits::query::NoSolution;
 use rustc_middle::bug;
@@ -16,7 +16,6 @@ use rustc_middle::ty::{fast_reject, TypeFoldable};
 use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
 use rustc_span::{ErrorGuaranteed, DUMMY_SP};
 use std::fmt::Debug;
-use std::mem;
 
 pub(super) mod structural_traits;
 
@@ -792,17 +791,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         goal: Goal<'tcx, G>,
         candidates: &mut Vec<Candidate<'tcx>>,
     ) {
-        // HACK: We temporarily remove the `ProofTreeBuilder` to
-        // avoid adding `Trait` candidates to the candidates used
-        // to prove the current goal.
-        let inspect = mem::replace(&mut self.inspect, inspect::ProofTreeBuilder::new_noop());
-
         let tcx = self.tcx();
         let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> =
             goal.with(tcx, goal.predicate.trait_ref(tcx));
-        let mut trait_candidates_from_env = Vec::new();
-        self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env);
-        self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env);
+
+        let mut trait_candidates_from_env = vec![];
+        self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
+            ecx.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env);
+            ecx.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env);
+        });
+
         if !trait_candidates_from_env.is_empty() {
             let trait_env_result = self.merge_candidates(trait_candidates_from_env);
             match trait_env_result.unwrap().value.certainty {
@@ -831,7 +829,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 }
             }
         }
-        self.inspect = inspect;
     }
 
     /// If there are multiple ways to prove a trait or projection goal, we have
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index 6fda5f4af25..68c0c8bf09e 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -176,7 +176,8 @@ fn to_selection<'tcx>(
         | ProbeKind::UnsizeAssembly
         | ProbeKind::UpcastProjectionCompatibility
         | ProbeKind::OpaqueTypeStorageLookup { result: _ }
-        | ProbeKind::Root { result: _ } => {
+        | ProbeKind::Root { result: _ }
+        | ProbeKind::ShadowedEnvProbing => {
             span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind())
         }
     })
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index fd36b7ffd4e..b71a1b339cb 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -18,8 +18,8 @@ use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{inspect, QueryResult};
 use rustc_middle::traits::solve::{Certainty, Goal};
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty;
 use rustc_middle::ty::TypeFoldable;
+use rustc_middle::{bug, ty};
 use rustc_span::{Span, DUMMY_SP};
 
 use crate::solve::eval_ctxt::canonical;
@@ -290,12 +290,25 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
             match *step {
                 inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
                 inspect::ProbeStep::NestedProbe(ref probe) => {
-                    // Nested probes have to prove goals added in their parent
-                    // but do not leak them, so we truncate the added goals
-                    // afterwards.
-                    let num_goals = nested_goals.len();
-                    self.candidates_recur(candidates, nested_goals, probe);
-                    nested_goals.truncate(num_goals);
+                    match probe.kind {
+                        // These never assemble candidates for the goal we're trying to solve.
+                        inspect::ProbeKind::UpcastProjectionCompatibility
+                        | inspect::ProbeKind::ShadowedEnvProbing => continue,
+
+                        inspect::ProbeKind::NormalizedSelfTyAssembly
+                        | inspect::ProbeKind::UnsizeAssembly
+                        | inspect::ProbeKind::Root { .. }
+                        | inspect::ProbeKind::TryNormalizeNonRigid { .. }
+                        | inspect::ProbeKind::TraitCandidate { .. }
+                        | inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => {
+                            // Nested probes have to prove goals added in their parent
+                            // but do not leak them, so we truncate the added goals
+                            // afterwards.
+                            let num_goals = nested_goals.len();
+                            self.candidates_recur(candidates, nested_goals, probe);
+                            nested_goals.truncate(num_goals);
+                        }
+                    }
                 }
                 inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
                     assert_eq!(shallow_certainty.replace(c), None);
@@ -308,9 +321,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         }
 
         match probe.kind {
-            inspect::ProbeKind::NormalizedSelfTyAssembly
-            | inspect::ProbeKind::UnsizeAssembly
-            | inspect::ProbeKind::UpcastProjectionCompatibility => (),
+            inspect::ProbeKind::UpcastProjectionCompatibility
+            | inspect::ProbeKind::ShadowedEnvProbing => bug!(),
+
+            inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {}
 
             // We add a candidate even for the root evaluation if there
             // is only one way to prove a given goal, e.g. for `WellFormed`.
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index c748cdf6ed2..af07e9ff96b 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -2,6 +2,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 #[cfg(feature = "nightly")]
 use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
+use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 use std::fmt;
 
 use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
@@ -86,6 +87,46 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
     }
 }
 
+/// An unevaluated (potentially generic) constant used in the type-system.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct UnevaluatedConst<I: Interner> {
+    pub def: I::DefId,
+    pub args: I::GenericArgs,
+}
+
+impl<I: Interner> UnevaluatedConst<I> {
+    #[inline]
+    pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst<I> {
+        UnevaluatedConst { def, args }
+    }
+}
+
+impl<I: Interner> fmt::Debug for UnevaluatedConst<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        WithInfcx::with_no_infcx(self).fmt(f)
+    }
+}
+impl<I: Interner> DebugWithInfcx<I> for UnevaluatedConst<I> {
+    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
+        this: WithInfcx<'_, Infcx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        f.debug_struct("UnevaluatedConst")
+            .field("def", &this.data.def)
+            .field("args", &this.wrap(this.data.args))
+            .finish()
+    }
+}
+
 rustc_index::newtype_index! {
     /// A **`const`** **v**ariable **ID**.
     #[encodable]
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 5e981636438..92b1e08ab0a 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -5,7 +5,8 @@ use std::ops::Deref;
 use crate::fold::TypeSuperFoldable;
 use crate::visit::{Flags, TypeSuperVisitable};
 use crate::{
-    BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind, TyKind, UniverseIndex,
+    AliasTy, AliasTyKind, BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind,
+    TyKind, UnevaluatedConst, UniverseIndex,
 };
 
 pub trait Ty<I: Interner<Ty = Self>>:
@@ -14,12 +15,15 @@ pub trait Ty<I: Interner<Ty = Self>>:
     + Hash
     + Eq
     + Into<I::GenericArg>
+    + Into<I::Term>
     + IntoKind<Kind = TyKind<I>>
     + TypeSuperVisitable<I>
     + TypeSuperFoldable<I>
     + Flags
 {
     fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+
+    fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy<I>) -> Self;
 }
 
 pub trait Region<I: Interner<Region = Self>>:
@@ -36,6 +40,7 @@ pub trait Const<I: Interner<Const = Self>>:
     + Hash
     + Eq
     + Into<I::GenericArg>
+    + Into<I::Term>
     + IntoKind<Kind = ConstKind<I>>
     + TypeSuperVisitable<I>
     + TypeSuperFoldable<I>
@@ -43,6 +48,8 @@ pub trait Const<I: Interner<Const = Self>>:
 {
     fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
 
+    fn new_unevaluated(interner: I, uv: UnevaluatedConst<I>, ty: I::Ty) -> Self;
+
     fn ty(self) -> I::Ty;
 }
 
@@ -89,21 +96,3 @@ pub trait BoundVars<I: Interner> {
 
     fn has_no_bound_vars(&self) -> bool;
 }
-
-pub trait AliasTerm<I: Interner>: Copy + DebugWithInfcx<I> + Hash + Eq + Sized {
-    fn new(
-        interner: I,
-        trait_def_id: I::DefId,
-        args: impl IntoIterator<Item: Into<I::GenericArg>>,
-    ) -> Self;
-
-    fn def_id(self) -> I::DefId;
-
-    fn args(self) -> I::GenericArgs;
-
-    fn trait_def_id(self, interner: I) -> I::DefId;
-
-    fn self_ty(self) -> I::Ty;
-
-    fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self;
-}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index af0e833b9e9..d6680977168 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -6,13 +6,16 @@ use crate::inherent::*;
 use crate::ir_print::IrPrint;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
 use crate::{
-    CanonicalVarInfo, CoercePredicate, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef,
-    NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
+    AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate,
+    DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, NormalizesTo, ProjectionPredicate,
+    SubtypePredicate, TraitPredicate, TraitRef,
 };
 
 pub trait Interner:
     Sized
     + Copy
+    + IrPrint<AliasTy<Self>>
+    + IrPrint<AliasTerm<Self>>
     + IrPrint<TraitRef<Self>>
     + IrPrint<TraitPredicate<Self>>
     + IrPrint<ExistentialTraitRef<Self>>
@@ -27,6 +30,7 @@ pub trait Interner:
     type AdtDef: Copy + Debug + Hash + Eq;
 
     type GenericArgs: GenericArgs<Self>;
+    type GenericArgsSlice: Copy + Debug + Hash + Eq;
     type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq;
     type Term: Copy + Debug + Hash + Eq;
 
@@ -39,7 +43,6 @@ pub trait Interner:
     // Kinds of tys
     type Ty: Ty<Self>;
     type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
-    type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq + Sized;
     type ParamTy: Copy + Debug + Hash + Eq;
     type BoundTy: Copy + Debug + Hash + Eq;
     type PlaceholderTy: PlaceholderLike;
@@ -74,7 +77,6 @@ pub trait Interner:
     type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
     type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
     type ProjectionPredicate: Copy + Debug + Hash + Eq;
-    type AliasTerm: AliasTerm<Self>;
     type NormalizesTo: Copy + Debug + Hash + Eq;
     type SubtypePredicate: Copy + Debug + Hash + Eq;
     type CoercePredicate: Copy + Debug + Hash + Eq;
@@ -86,8 +88,23 @@ pub trait Interner:
     type GenericsOf: GenericsOf<Self>;
     fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
 
+    // FIXME: Remove after uplifting `EarlyBinder`
+    fn type_of_instantiated(self, def_id: Self::DefId, args: Self::GenericArgs) -> Self::Ty;
+
+    fn alias_ty_kind(self, alias: AliasTy<Self>) -> AliasTyKind;
+
+    fn alias_term_kind(self, alias: AliasTerm<Self>) -> AliasTermKind;
+
+    fn trait_ref_and_own_args_for_alias(
+        self,
+        def_id: Self::DefId,
+        args: Self::GenericArgs,
+    ) -> (TraitRef<Self>, Self::GenericArgsSlice);
+
     fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs;
 
+    fn mk_args_from_iter(self, args: impl Iterator<Item = Self::GenericArg>) -> Self::GenericArgs;
+
     fn check_and_mk_args(
         self,
         def_id: Self::DefId,
diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs
index 5885139754a..2a766d0bc09 100644
--- a/compiler/rustc_type_ir/src/ir_print.rs
+++ b/compiler/rustc_type_ir/src/ir_print.rs
@@ -1,8 +1,8 @@
 use std::fmt;
 
 use crate::{
-    CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, NormalizesTo,
-    ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
+    AliasTerm, AliasTy, CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner,
+    NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
 };
 
 pub trait IrPrint<T> {
@@ -43,6 +43,8 @@ define_display_via_print!(
     NormalizesTo,
     SubtypePredicate,
     CoercePredicate,
+    AliasTy,
+    AliasTerm,
 );
 
 define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection);
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 71f198d2b8e..b6c7c2c348c 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -6,7 +6,9 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
 
 use crate::inherent::*;
 use crate::visit::TypeVisitableExt as _;
-use crate::{DebugWithInfcx, Interner};
+use crate::{
+    AliasTy, AliasTyKind, DebugWithInfcx, InferCtxtLike, Interner, UnevaluatedConst, WithInfcx,
+};
 
 /// A complete reference to a trait. These take numerous guises in syntax,
 /// but perhaps the most recognizable form is in a where-clause:
@@ -272,20 +274,20 @@ impl<I: Interner> ExistentialProjection<I> {
     /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
     /// then this function would return an `exists T. T: Iterator` existential trait
     /// reference.
-    pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef<I> {
-        let def_id = tcx.parent(self.def_id);
-        let args_count = tcx.generics_of(def_id).count() - 1;
-        let args = tcx.mk_args(&self.args[..args_count]);
+    pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef<I> {
+        let def_id = interner.parent(self.def_id);
+        let args_count = interner.generics_of(def_id).count() - 1;
+        let args = interner.mk_args(&self.args[..args_count]);
         ExistentialTraitRef { def_id, args }
     }
 
-    pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
+    pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
         // otherwise the escaping regions would be captured by the binders
         debug_assert!(!self_ty.has_escaping_bound_vars());
 
         ProjectionPredicate {
-            projection_term: I::AliasTerm::new(
-                tcx,
+            projection_term: AliasTerm::new(
+                interner,
                 self.def_id,
                 [self_ty.into()].into_iter().chain(self.args),
             ),
@@ -293,13 +295,13 @@ impl<I: Interner> ExistentialProjection<I> {
         }
     }
 
-    pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate<I>) -> Self {
+    pub fn erase_self_ty(interner: I, projection_predicate: ProjectionPredicate<I>) -> Self {
         // Assert there is a Self.
-        projection_predicate.projection_term.args().type_at(0);
+        projection_predicate.projection_term.args.type_at(0);
 
         Self {
-            def_id: projection_predicate.projection_term.def_id(),
-            args: tcx.mk_args(&projection_predicate.projection_term.args()[1..]),
+            def_id: projection_predicate.projection_term.def_id,
+            args: interner.mk_args(&projection_predicate.projection_term.args[1..]),
             term: projection_predicate.term,
         }
     }
@@ -339,6 +341,190 @@ impl AliasTermKind {
     }
 }
 
+/// Represents the unprojected term of a projection goal.
+///
+/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
+/// * For an inherent projection, this would be `Ty::N<...>`.
+/// * For an opaque type, there is no explicit syntax.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct AliasTerm<I: Interner> {
+    /// The parameters of the associated or opaque item.
+    ///
+    /// For a projection, these are the generic parameters for the trait and the
+    /// GAT parameters, if there are any.
+    ///
+    /// For an inherent projection, they consist of the self type and the GAT parameters,
+    /// if there are any.
+    ///
+    /// For RPIT the generic parameters are for the generics of the function,
+    /// while for TAIT it is used for the generic parameters of the alias.
+    pub args: I::GenericArgs,
+
+    /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
+    /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
+    /// this is an opaque.
+    ///
+    /// During codegen, `interner.type_of(def_id)` can be used to get the type of the
+    /// underlying type if the type is an opaque.
+    ///
+    /// Note that if this is an associated type, this is not the `DefId` of the
+    /// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`,
+    /// aka. `interner.parent(def_id)`.
+    pub def_id: I::DefId,
+
+    /// This field exists to prevent the creation of `AliasTerm` without using
+    /// [AliasTerm::new].
+    _use_alias_term_new_instead: (),
+}
+
+impl<I: Interner> std::fmt::Debug for AliasTerm<I> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        WithInfcx::with_no_infcx(self).fmt(f)
+    }
+}
+impl<I: Interner> DebugWithInfcx<I> for AliasTerm<I> {
+    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
+        this: WithInfcx<'_, Infcx, &Self>,
+        f: &mut std::fmt::Formatter<'_>,
+    ) -> std::fmt::Result {
+        f.debug_struct("AliasTerm")
+            .field("args", &this.map(|data| data.args))
+            .field("def_id", &this.data.def_id)
+            .finish()
+    }
+}
+
+impl<I: Interner> AliasTerm<I> {
+    pub fn new(
+        interner: I,
+        def_id: I::DefId,
+        args: impl IntoIterator<Item: Into<I::GenericArg>>,
+    ) -> AliasTerm<I> {
+        let args = interner.check_and_mk_args(def_id, args);
+        AliasTerm { def_id, args, _use_alias_term_new_instead: () }
+    }
+
+    pub fn expect_ty(self, interner: I) -> AliasTy<I> {
+        match self.kind(interner) {
+            AliasTermKind::ProjectionTy
+            | AliasTermKind::InherentTy
+            | AliasTermKind::OpaqueTy
+            | AliasTermKind::WeakTy => {}
+            AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
+                panic!("Cannot turn `UnevaluatedConst` into `AliasTy`")
+            }
+        }
+        AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
+    }
+
+    pub fn kind(self, interner: I) -> AliasTermKind {
+        interner.alias_term_kind(self)
+    }
+
+    pub fn to_term(self, interner: I) -> I::Term {
+        match self.kind(interner) {
+            AliasTermKind::ProjectionTy => Ty::new_alias(
+                interner,
+                AliasTyKind::Projection,
+                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+            )
+            .into(),
+            AliasTermKind::InherentTy => Ty::new_alias(
+                interner,
+                AliasTyKind::Inherent,
+                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+            )
+            .into(),
+            AliasTermKind::OpaqueTy => Ty::new_alias(
+                interner,
+                AliasTyKind::Opaque,
+                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+            )
+            .into(),
+            AliasTermKind::WeakTy => Ty::new_alias(
+                interner,
+                AliasTyKind::Weak,
+                AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
+            )
+            .into(),
+            AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
+                I::Const::new_unevaluated(
+                    interner,
+                    UnevaluatedConst::new(self.def_id, self.args),
+                    interner.type_of_instantiated(self.def_id, self.args),
+                )
+                .into()
+            }
+        }
+    }
+}
+
+/// The following methods work only with (trait) associated type projections.
+impl<I: Interner> AliasTerm<I> {
+    pub fn self_ty(self) -> I::Ty {
+        self.args.type_at(0)
+    }
+
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+        AliasTerm::new(
+            interner,
+            self.def_id,
+            [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
+        )
+    }
+
+    pub fn trait_def_id(self, interner: I) -> I::DefId {
+        assert!(
+            matches!(
+                self.kind(interner),
+                AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst
+            ),
+            "expected a projection"
+        );
+        interner.parent(self.def_id)
+    }
+
+    /// Extracts the underlying trait reference and own args from this projection.
+    /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
+    /// then this function would return a `T: StreamingIterator` trait reference and
+    /// `['a]` as the own args.
+    pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) {
+        interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
+    }
+
+    /// Extracts the underlying trait reference from this projection.
+    /// For example, if this is a projection of `<T as Iterator>::Item`,
+    /// then this function would return a `T: Iterator` trait reference.
+    ///
+    /// WARNING: This will drop the args for generic associated types
+    /// consider calling [Self::trait_ref_and_own_args] to get those
+    /// as well.
+    pub fn trait_ref(self, interner: I) -> TraitRef<I> {
+        self.trait_ref_and_own_args(interner).0
+    }
+}
+
+impl<I: Interner> From<AliasTy<I>> for AliasTerm<I> {
+    fn from(ty: AliasTy<I>) -> Self {
+        AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
+    }
+}
+
+impl<I: Interner> From<UnevaluatedConst<I>> for AliasTerm<I> {
+    fn from(ct: UnevaluatedConst<I>) -> Self {
+        AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
+    }
+}
+
 /// This kind of predicate has no *direct* correspondent in the
 /// syntax, but it roughly corresponds to the syntactic forms:
 ///
@@ -362,7 +548,7 @@ impl AliasTermKind {
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
 pub struct ProjectionPredicate<I: Interner> {
-    pub projection_term: I::AliasTerm,
+    pub projection_term: AliasTerm<I>,
     pub term: I::Term,
 }
 
@@ -371,16 +557,16 @@ impl<I: Interner> ProjectionPredicate<I> {
         self.projection_term.self_ty()
     }
 
-    pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
-        Self { projection_term: self.projection_term.with_self_ty(tcx, self_ty), ..self }
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
+        Self { projection_term: self.projection_term.with_self_ty(interner, self_ty), ..self }
     }
 
-    pub fn trait_def_id(self, tcx: I) -> I::DefId {
-        self.projection_term.trait_def_id(tcx)
+    pub fn trait_def_id(self, interner: I) -> I::DefId {
+        self.projection_term.trait_def_id(interner)
     }
 
     pub fn def_id(self) -> I::DefId {
-        self.projection_term.def_id()
+        self.projection_term.def_id
     }
 }
 
@@ -403,7 +589,7 @@ impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
 pub struct NormalizesTo<I: Interner> {
-    pub alias: I::AliasTerm,
+    pub alias: AliasTerm<I>,
     pub term: I::Term,
 }
 
@@ -412,16 +598,16 @@ impl<I: Interner> NormalizesTo<I> {
         self.alias.self_ty()
     }
 
-    pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> NormalizesTo<I> {
-        Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo<I> {
+        Self { alias: self.alias.with_self_ty(interner, self_ty), ..self }
     }
 
-    pub fn trait_def_id(self, tcx: I) -> I::DefId {
-        self.alias.trait_def_id(tcx)
+    pub fn trait_def_id(self, interner: I) -> I::DefId {
+        self.alias.trait_def_id(interner)
     }
 
     pub fn def_id(self) -> I::DefId {
-        self.alias.def_id()
+        self.alias.def_id
     }
 }
 
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 6e544d0e6ac..672c890f94e 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -4,11 +4,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
-use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
+use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 use std::fmt;
 
-use crate::Interner;
-use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
+use crate::inherent::*;
+use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, TraitRef, WithInfcx};
 
 use self::TyKind::*;
 
@@ -88,7 +88,7 @@ pub enum TyKind<I: Interner> {
     /// for `struct List<T>` and the args `[i32]`.
     ///
     /// Note that generic parameters in fields only get lazily instantiated
-    /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, args))`.
+    /// by using something like `adt_def.all_fields().map(|field| field.ty(interner, args))`.
     Adt(I::AdtDef, I::GenericArgs),
 
     /// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
@@ -201,7 +201,7 @@ pub enum TyKind<I: Interner> {
     /// A projection, opaque type, weak type alias, or inherent associated type.
     /// All of these types are represented as pairs of def-id and args, and can
     /// be normalized, so they are grouped conceptually.
-    Alias(AliasTyKind, I::AliasTy),
+    Alias(AliasTyKind, AliasTy<I>),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
     Param(I::ParamTy),
@@ -422,6 +422,154 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
     }
 }
 
+/// Represents the projection of an associated, opaque, or lazy-type-alias type.
+///
+/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
+/// * For an inherent projection, this would be `Ty::N<...>`.
+/// * For an opaque type, there is no explicit syntax.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct AliasTy<I: Interner> {
+    /// The parameters of the associated or opaque type.
+    ///
+    /// For a projection, these are the generic parameters for the trait and the
+    /// GAT parameters, if there are any.
+    ///
+    /// For an inherent projection, they consist of the self type and the GAT parameters,
+    /// if there are any.
+    ///
+    /// For RPIT the generic parameters are for the generics of the function,
+    /// while for TAIT it is used for the generic parameters of the alias.
+    pub args: I::GenericArgs,
+
+    /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
+    /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
+    /// this is an opaque.
+    ///
+    /// During codegen, `interner.type_of(def_id)` can be used to get the type of the
+    /// underlying type if the type is an opaque.
+    ///
+    /// Note that if this is an associated type, this is not the `DefId` of the
+    /// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`,
+    /// aka. `interner.parent(def_id)`.
+    pub def_id: I::DefId,
+
+    /// This field exists to prevent the creation of `AliasTy` without using
+    /// [AliasTy::new].
+    pub(crate) _use_alias_ty_new_instead: (),
+}
+
+impl<I: Interner> AliasTy<I> {
+    pub fn new(
+        interner: I,
+        def_id: I::DefId,
+        args: impl IntoIterator<Item: Into<I::GenericArg>>,
+    ) -> AliasTy<I> {
+        let args = interner.check_and_mk_args(def_id, args);
+        AliasTy { def_id, args, _use_alias_ty_new_instead: () }
+    }
+
+    pub fn kind(self, interner: I) -> AliasTyKind {
+        interner.alias_ty_kind(self)
+    }
+
+    /// Whether this alias type is an opaque.
+    pub fn is_opaque(self, interner: I) -> bool {
+        matches!(self.kind(interner), AliasTyKind::Opaque)
+    }
+
+    pub fn to_ty(self, interner: I) -> I::Ty {
+        Ty::new_alias(interner, self.kind(interner), self)
+    }
+}
+
+/// The following methods work only with (trait) associated type projections.
+impl<I: Interner> AliasTy<I> {
+    pub fn self_ty(self) -> I::Ty {
+        self.args.type_at(0)
+    }
+
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+        AliasTy::new(
+            interner,
+            self.def_id,
+            [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
+        )
+    }
+
+    pub fn trait_def_id(self, interner: I) -> I::DefId {
+        assert_eq!(self.kind(interner), AliasTyKind::Projection, "expected a projection");
+        interner.parent(self.def_id)
+    }
+
+    /// Extracts the underlying trait reference and own args from this projection.
+    /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
+    /// then this function would return a `T: StreamingIterator` trait reference and
+    /// `['a]` as the own args.
+    pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) {
+        debug_assert_eq!(self.kind(interner), AliasTyKind::Projection);
+        interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
+    }
+
+    /// Extracts the underlying trait reference from this projection.
+    /// For example, if this is a projection of `<T as Iterator>::Item`,
+    /// then this function would return a `T: Iterator` trait reference.
+    ///
+    /// WARNING: This will drop the args for generic associated types
+    /// consider calling [Self::trait_ref_and_own_args] to get those
+    /// as well.
+    pub fn trait_ref(self, interner: I) -> TraitRef<I> {
+        self.trait_ref_and_own_args(interner).0
+    }
+}
+
+/// The following methods work only with inherent associated type projections.
+impl<I: Interner> AliasTy<I> {
+    /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that.
+    ///
+    /// Does the following transformation:
+    ///
+    /// ```text
+    /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
+    ///
+    ///     I_i impl args
+    ///     P_j GAT args
+    /// ```
+    pub fn rebase_inherent_args_onto_impl(
+        self,
+        impl_args: I::GenericArgs,
+        interner: I,
+    ) -> I::GenericArgs {
+        debug_assert_eq!(self.kind(interner), AliasTyKind::Inherent);
+        interner.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1)))
+    }
+}
+
+impl<I: Interner> fmt::Debug for AliasTy<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        WithInfcx::with_no_infcx(self).fmt(f)
+    }
+}
+impl<I: Interner> DebugWithInfcx<I> for AliasTy<I> {
+    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
+        this: WithInfcx<'_, Infcx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        f.debug_struct("AliasTy")
+            .field("args", &this.map(|data| data.args))
+            .field("def_id", &this.data.def_id)
+            .finish()
+    }
+}
+
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
 pub enum IntTy {
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index c29e5565d51..e9f4d0f93ed 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -91,17 +91,21 @@ pub struct EscapeDefault(escape::EscapeIterInner<4>);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn escape_default(c: u8) -> EscapeDefault {
-    let mut data = [Char::Null; 4];
-    let range = escape::escape_ascii_into(&mut data, c);
-    EscapeDefault(escape::EscapeIterInner::new(data, range))
+    EscapeDefault::new(c)
 }
 
 impl EscapeDefault {
+    #[inline]
+    pub(crate) const fn new(c: u8) -> Self {
+        Self(escape::EscapeIterInner::ascii(c))
+    }
+
+    #[inline]
     pub(crate) fn empty() -> Self {
-        let data = [Char::Null; 4];
-        EscapeDefault(escape::EscapeIterInner::new(data, 0..0))
+        Self(escape::EscapeIterInner::empty())
     }
 
+    #[inline]
     pub(crate) fn as_str(&self) -> &str {
         self.0.as_str()
     }
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index a93b94867ce..458be49fb15 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -449,10 +449,10 @@ impl char {
             '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark),
             '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe),
             _ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
-                EscapeDebug::from_unicode(self.escape_unicode())
+                EscapeDebug::unicode(self)
             }
             _ if is_printable(self) => EscapeDebug::printable(self),
-            _ => EscapeDebug::from_unicode(self.escape_unicode()),
+            _ => EscapeDebug::unicode(self),
         }
     }
 
@@ -555,9 +555,9 @@ impl char {
             '\t' => EscapeDefault::backslash(ascii::Char::SmallT),
             '\r' => EscapeDefault::backslash(ascii::Char::SmallR),
             '\n' => EscapeDefault::backslash(ascii::Char::SmallN),
-            '\\' | '\'' | '"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
+            '\\' | '\'' | '\"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
             '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()),
-            _ => EscapeDefault::from_unicode(self.escape_unicode()),
+            _ => EscapeDefault::unicode(self),
         }
     }
 
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index a860c7c6aaa..f3683fe3f9c 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -152,10 +152,9 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
 pub struct EscapeUnicode(escape::EscapeIterInner<10>);
 
 impl EscapeUnicode {
-    fn new(chr: char) -> Self {
-        let mut data = [ascii::Char::Null; 10];
-        let range = escape::escape_unicode_into(&mut data, chr);
-        Self(escape::EscapeIterInner::new(data, range))
+    #[inline]
+    const fn new(c: char) -> Self {
+        Self(escape::EscapeIterInner::unicode(c))
     }
 }
 
@@ -219,18 +218,19 @@ impl fmt::Display for EscapeUnicode {
 pub struct EscapeDefault(escape::EscapeIterInner<10>);
 
 impl EscapeDefault {
-    fn printable(chr: ascii::Char) -> Self {
-        let data = [chr];
-        Self(escape::EscapeIterInner::from_array(data))
+    #[inline]
+    const fn printable(c: ascii::Char) -> Self {
+        Self(escape::EscapeIterInner::ascii(c.to_u8()))
     }
 
-    fn backslash(chr: ascii::Char) -> Self {
-        let data = [ascii::Char::ReverseSolidus, chr];
-        Self(escape::EscapeIterInner::from_array(data))
+    #[inline]
+    const fn backslash(c: ascii::Char) -> Self {
+        Self(escape::EscapeIterInner::backslash(c))
     }
 
-    fn from_unicode(esc: EscapeUnicode) -> Self {
-        Self(esc.0)
+    #[inline]
+    const fn unicode(c: char) -> Self {
+        Self(escape::EscapeIterInner::unicode(c))
     }
 }
 
@@ -304,23 +304,24 @@ enum EscapeDebugInner {
 }
 
 impl EscapeDebug {
-    fn printable(chr: char) -> Self {
+    #[inline]
+    const fn printable(chr: char) -> Self {
         Self(EscapeDebugInner::Char(chr))
     }
 
-    fn backslash(chr: ascii::Char) -> Self {
-        let data = [ascii::Char::ReverseSolidus, chr];
-        let iter = escape::EscapeIterInner::from_array(data);
-        Self(EscapeDebugInner::Bytes(iter))
+    #[inline]
+    const fn backslash(c: ascii::Char) -> Self {
+        Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::backslash(c)))
     }
 
-    fn from_unicode(esc: EscapeUnicode) -> Self {
-        Self(EscapeDebugInner::Bytes(esc.0))
+    #[inline]
+    const fn unicode(c: char) -> Self {
+        Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::unicode(c)))
     }
 
+    #[inline]
     fn clear(&mut self) {
-        let bytes = escape::EscapeIterInner::from_array([]);
-        self.0 = EscapeDebugInner::Bytes(bytes);
+        self.0 = EscapeDebugInner::Bytes(escape::EscapeIterInner::empty());
     }
 }
 
@@ -339,6 +340,7 @@ impl Iterator for EscapeDebug {
         }
     }
 
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let n = self.len();
         (n, Some(n))
diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs
index 143e277283e..f6ec30b9f79 100644
--- a/library/core/src/escape.rs
+++ b/library/core/src/escape.rs
@@ -6,56 +6,79 @@ use crate::ops::Range;
 
 const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap();
 
-/// Escapes a byte into provided buffer; returns length of escaped
-/// representation.
-pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Range<u8> {
-    #[inline]
-    fn backslash(a: ascii::Char) -> ([ascii::Char; 4], u8) {
-        ([ascii::Char::ReverseSolidus, a, ascii::Char::Null, ascii::Char::Null], 2)
-    }
+#[inline]
+const fn backslash<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], Range<u8>) {
+    const { assert!(N >= 2) };
+
+    let mut output = [ascii::Char::Null; N];
+
+    output[0] = ascii::Char::ReverseSolidus;
+    output[1] = a;
+
+    (output, 0..2)
+}
 
-    let (data, len) = match byte {
+/// Escapes an ASCII character.
+///
+/// Returns a buffer and the length of the escaped representation.
+const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) {
+    const { assert!(N >= 4) };
+
+    match byte {
         b'\t' => backslash(ascii::Char::SmallT),
         b'\r' => backslash(ascii::Char::SmallR),
         b'\n' => backslash(ascii::Char::SmallN),
         b'\\' => backslash(ascii::Char::ReverseSolidus),
         b'\'' => backslash(ascii::Char::Apostrophe),
         b'\"' => backslash(ascii::Char::QuotationMark),
-        _ => {
-            if let Some(a) = byte.as_ascii()
+        byte => {
+            let mut output = [ascii::Char::Null; N];
+
+            if let Some(c) = byte.as_ascii()
                 && !byte.is_ascii_control()
             {
-                ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1)
+                output[0] = c;
+                (output, 0..1)
             } else {
-                let hi = HEX_DIGITS[usize::from(byte >> 4)];
-                let lo = HEX_DIGITS[usize::from(byte & 0xf)];
-                ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4)
+                let hi = HEX_DIGITS[(byte >> 4) as usize];
+                let lo = HEX_DIGITS[(byte & 0xf) as usize];
+
+                output[0] = ascii::Char::ReverseSolidus;
+                output[1] = ascii::Char::SmallX;
+                output[2] = hi;
+                output[3] = lo;
+
+                (output, 0..4)
             }
         }
-    };
-    *output = data;
-    0..len
+    }
 }
 
-/// Escapes a character into provided buffer using `\u{NNNN}` representation.
-pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> Range<u8> {
+/// Escapes a character `\u{NNNN}` representation.
+///
+/// Returns a buffer and the length of the escaped representation.
+const fn escape_unicode<const N: usize>(c: char) -> ([ascii::Char; N], Range<u8>) {
+    const { assert!(N >= 10 && N < u8::MAX as usize) };
+
+    let c = u32::from(c);
+
+    // OR-ing `1` ensures that for `c == 0` the code computes that
+    // one digit should be printed.
+    let start = (c | 1).leading_zeros() as usize / 4 - 2;
+
+    let mut output = [ascii::Char::Null; N];
+    output[3] = HEX_DIGITS[((c >> 20) & 15) as usize];
+    output[4] = HEX_DIGITS[((c >> 16) & 15) as usize];
+    output[5] = HEX_DIGITS[((c >> 12) & 15) as usize];
+    output[6] = HEX_DIGITS[((c >> 8) & 15) as usize];
+    output[7] = HEX_DIGITS[((c >> 4) & 15) as usize];
+    output[8] = HEX_DIGITS[((c >> 0) & 15) as usize];
     output[9] = ascii::Char::RightCurlyBracket;
+    output[start + 0] = ascii::Char::ReverseSolidus;
+    output[start + 1] = ascii::Char::SmallU;
+    output[start + 2] = ascii::Char::LeftCurlyBracket;
 
-    let ch = ch as u32;
-    output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize];
-    output[4] = HEX_DIGITS[((ch >> 16) & 15) as usize];
-    output[5] = HEX_DIGITS[((ch >> 12) & 15) as usize];
-    output[6] = HEX_DIGITS[((ch >> 8) & 15) as usize];
-    output[7] = HEX_DIGITS[((ch >> 4) & 15) as usize];
-    output[8] = HEX_DIGITS[((ch >> 0) & 15) as usize];
-
-    // or-ing 1 ensures that for ch==0 the code computes that one digit should
-    // be printed.
-    let start = (ch | 1).leading_zeros() as usize / 4 - 2;
-    const UNICODE_ESCAPE_PREFIX: &[ascii::Char; 3] = b"\\u{".as_ascii().unwrap();
-    output[start..][..3].copy_from_slice(UNICODE_ESCAPE_PREFIX);
-
-    (start as u8)..10
+    (output, (start as u8)..(N as u8))
 }
 
 /// An iterator over an fixed-size array.
@@ -65,45 +88,63 @@ pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> R
 #[derive(Clone, Debug)]
 pub(crate) struct EscapeIterInner<const N: usize> {
     // The element type ensures this is always ASCII, and thus also valid UTF-8.
-    pub(crate) data: [ascii::Char; N],
+    data: [ascii::Char; N],
 
-    // Invariant: alive.start <= alive.end <= N.
-    pub(crate) alive: Range<u8>,
+    // Invariant: `alive.start <= alive.end <= N`
+    alive: Range<u8>,
 }
 
 impl<const N: usize> EscapeIterInner<N> {
-    pub fn new(data: [ascii::Char; N], alive: Range<u8>) -> Self {
-        const { assert!(N < 256) };
-        debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}");
-        Self { data, alive }
+    pub const fn backslash(c: ascii::Char) -> Self {
+        let (data, range) = backslash(c);
+        Self { data, alive: range }
+    }
+
+    pub const fn ascii(c: u8) -> Self {
+        let (data, range) = escape_ascii(c);
+        Self { data, alive: range }
     }
 
-    pub fn from_array<const M: usize>(array: [ascii::Char; M]) -> Self {
-        const { assert!(M <= N) };
+    pub const fn unicode(c: char) -> Self {
+        let (data, range) = escape_unicode(c);
+        Self { data, alive: range }
+    }
 
-        let mut data = [ascii::Char::Null; N];
-        data[..M].copy_from_slice(&array);
-        Self::new(data, 0..M as u8)
+    #[inline]
+    pub const fn empty() -> Self {
+        Self { data: [ascii::Char::Null; N], alive: 0..0 }
     }
 
+    #[inline]
     pub fn as_ascii(&self) -> &[ascii::Char] {
-        &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)]
+        // SAFETY: `self.alive` is guaranteed to be a valid range for indexing `self.data`.
+        unsafe {
+            self.data.get_unchecked(usize::from(self.alive.start)..usize::from(self.alive.end))
+        }
     }
 
+    #[inline]
     pub fn as_str(&self) -> &str {
         self.as_ascii().as_str()
     }
 
+    #[inline]
     pub fn len(&self) -> usize {
         usize::from(self.alive.end - self.alive.start)
     }
 
     pub fn next(&mut self) -> Option<u8> {
-        self.alive.next().map(|i| self.data[usize::from(i)].to_u8())
+        let i = self.alive.next()?;
+
+        // SAFETY: `i` is guaranteed to be a valid index for `self.data`.
+        unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) }
     }
 
     pub fn next_back(&mut self) -> Option<u8> {
-        self.alive.next_back().map(|i| self.data[usize::from(i)].to_u8())
+        let i = self.alive.next_back()?;
+
+        // SAFETY: `i` is guaranteed to be a valid index for `self.data`.
+        unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) }
     }
 
     pub fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 48a96c5792c..446d0658c12 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -584,11 +584,11 @@ macro_rules! uint_impl {
             // Thus, rather than using `overflowing_sub` that produces a wrapping
             // subtraction, check it ourself so we can use an unchecked one.
 
-            if self >= rhs {
+            if self < rhs {
+                None
+            } else {
                 // SAFETY: just checked this can't overflow
                 Some(unsafe { intrinsics::unchecked_sub(self, rhs) })
-            } else {
-                None
             }
         }
 
diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs
index 993bf55edcf..9014bb3782a 100644
--- a/library/std/src/sys/pal/unix/alloc.rs
+++ b/library/std/src/sys/pal/unix/alloc.rs
@@ -87,21 +87,18 @@ cfg_if::cfg_if! {
             //                                       /memory/aligned_memory.cc
             libc::memalign(layout.align(), layout.size()) as *mut u8
         }
-    } else if #[cfg(target_os = "wasi")] {
-        #[inline]
-        unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-            // C11 aligned_alloc requires that the size be a multiple of the alignment.
-            // Layout already checks that the size rounded up doesn't overflow isize::MAX.
-            let align = layout.align();
-            let size = layout.size().next_multiple_of(align);
-            libc::aligned_alloc(align, size) as *mut u8
-        }
     } else {
         #[inline]
         unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
             let mut out = ptr::null_mut();
-            // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
-            // Since these are all powers of 2, we can just use max.
+            // We prefer posix_memalign over aligned_malloc since with aligned_malloc,
+            // implementations are making almost arbitrary choices for which alignments are
+            // "supported", making it hard to use. For instance, some implementations require the
+            // size to be a multiple of the alignment (wasi emmalloc), while others require the
+            // alignment to be at least the pointer size (Illumos, macOS) -- which may or may not be
+            // standards-compliant, but that does not help us.
+            // posix_memalign only has one, clear requirement: that the alignment be a multiple of
+            // `sizeof(void*)`. Since these are all powers of 2, we can just use max.
             let align = layout.align().max(crate::mem::size_of::<usize>());
             let ret = libc::posix_memalign(&mut out, align, layout.size());
             if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml
index d93c5fd25a1..fd2da246990 100644
--- a/src/bootstrap/defaults/config.compiler.toml
+++ b/src/bootstrap/defaults/config.compiler.toml
@@ -8,6 +8,8 @@ compiler-docs = true
 # where adding `debug!()` appears to do nothing.
 # However, it makes running the compiler slightly slower.
 debug-logging = true
+# Get actually-useful information from backtraces, profiling, etc. with minimal added bytes
+debuginfo-level = "line-tables-only"
 # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
 incremental = true
 # Print backtrace on internal compiler errors during bootstrap
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 5bc9d7615e2..1f006e1453f 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -26,7 +26,9 @@ use crate::core::build_steps::tool::{self, Tool};
 use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
 use crate::utils::channel::{self, Info};
-use crate::utils::helpers::{exe, is_dylib, output, t, target_supports_cranelift_backend, timeit};
+use crate::utils::helpers::{
+    exe, is_dylib, move_file, output, t, target_supports_cranelift_backend, timeit,
+};
 use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
 use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
 
@@ -2024,7 +2026,7 @@ impl Step for Extended {
             builder.run(&mut cmd);
 
             if !builder.config.dry_run() {
-                t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
+                t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
             }
         }
     }
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index a074d53aa36..60f48c5923e 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -12,7 +12,7 @@ use build_helper::ci::CiEnv;
 use build_helper::stage0_parser::VersionMetadata;
 use xz2::bufread::XzDecoder;
 
-use crate::utils::helpers::{check_run, exe, program_out_of_date};
+use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date};
 use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
 use crate::{t, Config};
 
@@ -209,7 +209,7 @@ impl Config {
             None => panic!("no protocol in {url}"),
         }
         t!(
-            std::fs::rename(&tempfile, dest_path),
+            move_file(&tempfile, dest_path),
             format!("failed to rename {tempfile:?} to {dest_path:?}")
         );
     }
@@ -313,7 +313,7 @@ impl Config {
             if src_path.is_dir() && dst_path.exists() {
                 continue;
             }
-            t!(fs::rename(src_path, dst_path));
+            t!(move_file(src_path, dst_path));
         }
         let dst_dir = dst.join(directory_prefix);
         if dst_dir.exists() {
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index c3a03693f71..a1c9ddebb5d 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -180,4 +180,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "New option `build.lldb` that will override the default lldb binary path used in debuginfo tests",
     },
+    ChangeInfo {
+        change_id: 123337,
+        severity: ChangeSeverity::Info,
+        summary: r#"The compiler profile now defaults to rust.debuginfo-level = "line-tables-only""#,
+    },
 ];
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 0d2ff4f951b..278359cb08e 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -150,6 +150,21 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result<
     }
 }
 
+/// Rename a file if from and to are in the same filesystem or
+/// copy and remove the file otherwise
+pub fn move_file<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
+    match fs::rename(&from, &to) {
+        // FIXME: Once `ErrorKind::CrossesDevices` is stabilized use
+        // if e.kind() == io::ErrorKind::CrossesDevices {
+        #[cfg(unix)]
+        Err(e) if e.raw_os_error() == Some(libc::EXDEV) => {
+            std::fs::copy(&from, &to)?;
+            std::fs::remove_file(&from)
+        }
+        r => r,
+    }
+}
+
 pub fn forcing_clang_based_tests() -> bool {
     if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") {
         match &var.to_string_lossy().to_lowercase()[..] {
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 2a950e669b9..57cdf7473a1 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -13,7 +13,7 @@ use std::{
 use crate::core::builder::Builder;
 use crate::core::{build_steps::dist::distdir, builder::Kind};
 use crate::utils::channel;
-use crate::utils::helpers::t;
+use crate::utils::helpers::{move_file, t};
 
 #[derive(Copy, Clone)]
 pub(crate) enum OverlayKind {
@@ -284,7 +284,7 @@ impl<'a> Tarball<'a> {
         // name, not "image". We rename the image directory just before passing
         // into rust-installer.
         let dest = self.temp_dir.join(self.package_name());
-        t!(std::fs::rename(&self.image_dir, &dest));
+        t!(move_file(&self.image_dir, &dest));
 
         self.run(|this, cmd| {
             let distdir = distdir(this.builder);
diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md
index 9d593f80810..74e873e35ff 100644
--- a/src/doc/style-guide/src/editions.md
+++ b/src/doc/style-guide/src/editions.md
@@ -40,6 +40,8 @@ include:
   of a delimited expression, delimited expressions are generally combinable,
   regardless of the number of members. Previously only applied with exactly
   one member (except for closures with explicit blocks).
+- When line-breaking a binary operator, if the first operand spans multiple
+  lines, use the base indentation of the last line.
 - Miscellaneous `rustfmt` bugfixes.
 - Use version-sort (sort `x8`, `x16`, `x32`, `x64`, `x128` in that order).
 - Change "ASCIIbetical" sort to Unicode-aware "non-lowercase before lowercase".
diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md
index 171a24cd89d..3bb0ee6d5ff 100644
--- a/src/doc/style-guide/src/expressions.md
+++ b/src/doc/style-guide/src/expressions.md
@@ -328,6 +328,37 @@ foo_bar
 Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather
 than at other binary operators.
 
+If line-breaking at a binary operator (including assignment operators) where the
+first operand spans multiple lines, use the base indentation of the *last*
+line of the first operand, and indent relative to that:
+
+```rust
+impl SomeType {
+    fn method(&mut self) {
+        self.array[array_index as usize]
+            .as_mut()
+            .expect("thing must exist")
+            .extra_info =
+                long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
+
+        self.array[array_index as usize]
+            .as_mut()
+            .expect("thing must exist")
+            .extra_info
+                + long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
+
+        self.array[array_index as usize]
+            .as_mut()
+            .expect("thing must exist")
+            .extra_info = Some(ExtraInfo {
+                parent,
+                count: count as u16,
+                children: children.into_boxed_slice(),
+            });
+    }
+}
+```
+
 ### Casts (`as`)
 
 Format `as` casts like a binary operator. In particular, always include spaces
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index b4e62e39d8d..18323e0b8ad 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1424,6 +1424,10 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O
     if let Some(impls) = cx.cache().impls.get(&did) {
         for i in impls {
             let impl_ = i.inner_impl();
+            if impl_.polarity != ty::ImplPolarity::Positive {
+                continue;
+            }
+
             if !ty.is_doc_subtype_of(&impl_.for_, cx.cache()) {
                 // Two different types might have the same did,
                 // without actually being the same.
@@ -1459,6 +1463,10 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
 
     for i in impls {
         let impl_ = i.inner_impl();
+        if impl_.polarity != ty::ImplPolarity::Positive {
+            continue;
+        }
+
         if !ty.is_doc_subtype_of(&impl_.for_, cx.cache()) {
             // Two different types might have the same did,
             // without actually being the same.
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 1d69ed59859..02c9d384ab7 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2478,6 +2478,15 @@ impl<'test> TestCx<'test> {
             }
         }
 
+        let set_mir_dump_dir = |rustc: &mut Command| {
+            let mir_dump_dir = self.get_mir_dump_dir();
+            remove_and_create_dir_all(&mir_dump_dir);
+            let mut dir_opt = "-Zdump-mir-dir=".to_string();
+            dir_opt.push_str(mir_dump_dir.to_str().unwrap());
+            debug!("dir_opt: {:?}", dir_opt);
+            rustc.arg(dir_opt);
+        };
+
         match self.config.mode {
             Incremental => {
                 // If we are extracting and matching errors in the new
@@ -2532,13 +2541,7 @@ impl<'test> TestCx<'test> {
                     ]);
                 }
 
-                let mir_dump_dir = self.get_mir_dump_dir();
-                remove_and_create_dir_all(&mir_dump_dir);
-                let mut dir_opt = "-Zdump-mir-dir=".to_string();
-                dir_opt.push_str(mir_dump_dir.to_str().unwrap());
-                debug!("dir_opt: {:?}", dir_opt);
-
-                rustc.arg(dir_opt);
+                set_mir_dump_dir(&mut rustc);
             }
             CoverageMap => {
                 rustc.arg("-Cinstrument-coverage");
@@ -2560,8 +2563,11 @@ impl<'test> TestCx<'test> {
             Assembly | Codegen => {
                 rustc.arg("-Cdebug-assertions=no");
             }
+            Crashes => {
+                set_mir_dump_dir(&mut rustc);
+            }
             RunPassValgrind | Pretty | DebugInfo | Rustdoc | RustdocJson | RunMake
-            | CodegenUnits | JsDocTest | Crashes => {
+            | CodegenUnits | JsDocTest => {
                 // do not use JSON output
             }
         }
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index ffb01210e04..bd0a3815855 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -69,6 +69,10 @@ enum EnvironmentCmd {
         #[arg(long, default_value = "opt-artifacts")]
         artifact_dir: Utf8PathBuf,
 
+        /// Checkout directory of `rustc-perf`, it will be fetched automatically if unspecified.
+        #[arg(long)]
+        rustc_perf_checkout_dir: Option<Utf8PathBuf>,
+
         /// Is LLVM for `rustc` built in shared library mode?
         #[arg(long, default_value_t = true)]
         llvm_shared: bool,
@@ -109,6 +113,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
             llvm_dir,
             python,
             artifact_dir,
+            rustc_perf_checkout_dir,
             llvm_shared,
             use_bolt,
             skipped_tests,
@@ -121,6 +126,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
                 .host_llvm_dir(llvm_dir)
                 .artifact_dir(artifact_dir)
                 .build_dir(checkout_dir)
+                .prebuilt_rustc_perf(rustc_perf_checkout_dir)
                 .shared_llvm(llvm_shared)
                 .use_bolt(use_bolt)
                 .skipped_tests(skipped_tests)
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index cc81d23a8ff..9854d91e19e 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -40,12 +40,17 @@ pub fn target() -> String {
 
 /// Check if target is windows-like.
 pub fn is_windows() -> bool {
-    env::var_os("IS_WINDOWS").is_some()
+    target().contains("windows")
 }
 
 /// Check if target uses msvc.
 pub fn is_msvc() -> bool {
-    env::var_os("IS_MSVC").is_some()
+    target().contains("msvc")
+}
+
+/// Check if target uses macOS.
+pub fn is_darwin() -> bool {
+    target().contains("darwin")
 }
 
 /// Construct a path to a static library under `$TMPDIR` given the library name. This will return a
@@ -59,6 +64,12 @@ pub fn python_command() -> Command {
     Command::new(python_path)
 }
 
+pub fn htmldocck() -> Command {
+    let mut python = python_command();
+    python.arg(source_path().join("src/etc/htmldocck.py"));
+    python
+}
+
 pub fn source_path() -> PathBuf {
     std::env::var("S").expect("S variable does not exist").into()
 }
@@ -82,9 +93,47 @@ pub fn static_lib_name(name: &str) -> String {
     //     endif
     // endif
     // ```
-    assert!(!name.contains(char::is_whitespace), "name cannot contain whitespace");
+    assert!(!name.contains(char::is_whitespace), "static library name cannot contain whitespace");
+
+    if is_msvc() { format!("{name}.lib") } else { format!("lib{name}.a") }
+}
+
+/// Construct a path to a dynamic library under `$TMPDIR` given the library name. This will return a
+/// path with `$TMPDIR` joined with platform-and-compiler-specific library name.
+pub fn dynamic_lib(name: &str) -> PathBuf {
+    tmp_dir().join(dynamic_lib_name(name))
+}
+
+/// Construct the dynamic library name based on the platform.
+pub fn dynamic_lib_name(name: &str) -> String {
+    // See tools.mk (irrelevant lines omitted):
+    //
+    // ```makefile
+    // ifeq ($(UNAME),Darwin)
+    //     DYLIB = $(TMPDIR)/lib$(1).dylib
+    // else
+    //     ifdef IS_WINDOWS
+    //         DYLIB = $(TMPDIR)/$(1).dll
+    //     else
+    //         DYLIB = $(TMPDIR)/lib$(1).so
+    //     endif
+    // endif
+    // ```
+    assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace");
+
+    if is_darwin() {
+        format!("lib{name}.dylib")
+    } else if is_windows() {
+        format!("{name}.dll")
+    } else {
+        format!("lib{name}.so")
+    }
+}
 
-    if target().contains("msvc") { format!("{name}.lib") } else { format!("lib{name}.a") }
+/// Construct a path to a rust library (rlib) under `$TMPDIR` given the library name. This will return a
+/// path with `$TMPDIR` joined with the library name.
+pub fn rust_lib(name: &str) -> PathBuf {
+    tmp_dir().join(format!("lib{name}.rlib"))
 }
 
 /// Construct the binary name based on platform.
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index 1671a01860a..d034826a830 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -91,7 +91,7 @@ impl Rustc {
         self
     }
 
-    /// Specify path to the output file.
+    /// Specify path to the output file. Equivalent to `-o`` in rustc.
     pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self.cmd.arg("-o");
         self.cmd.arg(path.as_ref());
@@ -150,6 +150,13 @@ impl Rustc {
         self
     }
 
+    /// Add a directory to the library search path. Equivalent to `-L`` in rustc.
+    pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("-L");
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
     /// Specify the edition year.
     pub fn edition(&mut self, edition: &str) -> &mut Self {
         self.cmd.arg("--edition");
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index e196d1817f3..90e9e58ef9c 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -739,8 +739,8 @@ impl<'a> FmtVisitor<'a> {
                 (_, Const(..)) => Ordering::Greater,
                 (MacCall(..), _) => Ordering::Less,
                 (_, MacCall(..)) => Ordering::Greater,
-                (Delegation(..), _) => Ordering::Less,
-                (_, Delegation(..)) => Ordering::Greater,
+                (Delegation(..), _) | (DelegationMac(..), _) => Ordering::Less,
+                (_, Delegation(..)) | (_, DelegationMac(..)) => Ordering::Greater,
             });
             let mut prev_kind = None;
             for (buf, item) in buffer {
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 6209b37004b..e1c7dc35087 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -586,7 +586,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     );
                     self.push_rewrite(item.span, rewrite);
                 }
-                ast::ItemKind::Delegation(..) => {
+                ast::ItemKind::Delegation(..) | ast::ItemKind::DelegationMac(..) => {
                     // TODO: rewrite delegation items once syntax is established.
                     // For now, leave the contents of the Span unformatted.
                     self.push_rewrite(item.span, None)
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 83a3ea84b24..1a3d6f8d813 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -8,7 +8,6 @@ run-make/branch-protection-check-IBT/Makefile
 run-make/c-dynamic-dylib/Makefile
 run-make/c-dynamic-rlib/Makefile
 run-make/c-link-to-rust-dylib/Makefile
-run-make/c-link-to-rust-staticlib/Makefile
 run-make/c-static-dylib/Makefile
 run-make/c-static-rlib/Makefile
 run-make/c-unwind-abi-catch-lib-panic/Makefile
@@ -94,8 +93,6 @@ run-make/invalid-staticlib/Makefile
 run-make/issue-107094/Makefile
 run-make/issue-10971-temps-dir/Makefile
 run-make/issue-109934-lto-debuginfo/Makefile
-run-make/issue-11908/Makefile
-run-make/issue-14500/Makefile
 run-make/issue-14698/Makefile
 run-make/issue-15460/Makefile
 run-make/issue-18943/Makefile
@@ -181,7 +178,6 @@ run-make/native-link-modifier-whole-archive/Makefile
 run-make/no-alloc-shim/Makefile
 run-make/no-builtins-attribute/Makefile
 run-make/no-builtins-lto/Makefile
-run-make/no-cdylib-as-rdylib/Makefile
 run-make/no-duplicate-libs/Makefile
 run-make/no-intermediate-extras/Makefile
 run-make/obey-crate-type-flag/Makefile
@@ -194,7 +190,6 @@ run-make/output-with-hyphens/Makefile
 run-make/override-aliased-flags/Makefile
 run-make/overwrite-input/Makefile
 run-make/panic-abort-eh_frame/Makefile
-run-make/panic-impl-transitive/Makefile
 run-make/pass-linker-flags-flavor/Makefile
 run-make/pass-linker-flags-from-dep/Makefile
 run-make/pass-linker-flags/Makefile
@@ -247,9 +242,7 @@ run-make/rustdoc-scrape-examples-multiple/Makefile
 run-make/rustdoc-scrape-examples-remap/Makefile
 run-make/rustdoc-scrape-examples-test/Makefile
 run-make/rustdoc-scrape-examples-whitespace/Makefile
-run-make/rustdoc-themes/Makefile
 run-make/rustdoc-verify-output-files/Makefile
-run-make/rustdoc-with-out-dir-option/Makefile
 run-make/rustdoc-with-output-option/Makefile
 run-make/rustdoc-with-short-out-dir-option/Makefile
 run-make/sanitizer-cdylib-link/Makefile
diff --git a/tests/run-make/c-link-to-rust-staticlib/Makefile b/tests/run-make/c-link-to-rust-staticlib/Makefile
deleted file mode 100644
index d36cc421c46..00000000000
--- a/tests/run-make/c-link-to-rust-staticlib/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# This test checks that C linking with Rust does not encounter any errors, with static libraries.
-# See https://github.com/rust-lang/rust/issues/10434
-
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-freebsd
-# FIXME
-
-all:
-	$(RUSTC) foo.rs
-	$(CC) bar.c $(call STATICLIB,foo) $(call OUT_EXE,bar) \
-		$(EXTRACFLAGS) $(EXTRACXXFLAGS)
-	$(call RUN,bar)
-	rm $(call STATICLIB,foo)
-	$(call RUN,bar)
diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs
new file mode 100644
index 00000000000..63d5eb78c69
--- /dev/null
+++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs
@@ -0,0 +1,15 @@
+// This test checks that C linking with Rust does not encounter any errors, with a static library.
+// See https://github.com/rust-lang/rust/issues/10434
+
+//@ ignore-cross-compile
+
+use run_make_support::{cc, extra_c_flags, run, rustc, static_lib};
+use std::fs;
+
+fn main() {
+    rustc().input("foo.rs").run();
+    cc().input("bar.c").input(static_lib("foo")).out_exe("bar").args(&extra_c_flags()).run();
+    run("bar");
+    fs::remove_file(static_lib("foo"));
+    run("bar");
+}
diff --git a/tests/run-make/doctests-keep-binaries/rmake.rs b/tests/run-make/doctests-keep-binaries/rmake.rs
index ad0c2764df7..0613ef4839b 100644
--- a/tests/run-make/doctests-keep-binaries/rmake.rs
+++ b/tests/run-make/doctests-keep-binaries/rmake.rs
@@ -26,8 +26,7 @@ fn main() {
             .arg("--test")
             .arg("--persist-doctests")
             .arg(out_dir)
-            .arg("--extern")
-            .arg(format!("t={}", extern_path.display()))
+            .extern_("t", extern_path)
             .run();
         check_generated_binaries();
     });
@@ -38,8 +37,7 @@ fn main() {
             .arg("--test")
             .arg("--persist-doctests")
             .arg(out_dir)
-            .arg("--extern")
-            .arg(format!("t={}", extern_path.display()))
+            .extern_("t", extern_path)
             .arg("--no-run")
             .run();
         check_generated_binaries();
@@ -59,8 +57,7 @@ fn main() {
             .arg("doctests")
             .arg("--test-run-directory")
             .arg(run_dir)
-            .arg("--extern")
-            .arg("t=libt.rlib")
+            .extern_("t", "libt.rlib")
             .run();
 
         remove_dir_all(run_dir_path);
diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs
index 6f89bf23b47..6cc7c6bbdaf 100644
--- a/tests/run-make/doctests-runtool/rmake.rs
+++ b/tests/run-make/doctests-runtool/rmake.rs
@@ -29,8 +29,7 @@ fn main() {
         .arg(run_dir_name)
         .arg("--runtool")
         .arg(&run_tool_binary)
-        .arg("--extern")
-        .arg("t=libt.rlib")
+        .extern_("t", "libt.rlib")
         .current_dir(tmp_dir())
         .run();
 
diff --git a/tests/run-make/issue-11908/Makefile b/tests/run-make/issue-11908/Makefile
deleted file mode 100644
index 38586662fc7..00000000000
--- a/tests/run-make/issue-11908/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-# ignore-cross-compile
-# This test ensures that if you have the same rlib or dylib at two locations
-# in the same path that you don't hit an assertion in the compiler.
-#
-# Note that this relies on `liburl` to be in the path somewhere else,
-# and then our aux-built libraries will collide with liburl (they have
-# the same version listed)
-
-include ../tools.mk
-
-all:
-	mkdir $(TMPDIR)/other
-	$(RUSTC) foo.rs --crate-type=dylib -C prefer-dynamic
-	mv $(call DYLIB,foo) $(TMPDIR)/other
-	$(RUSTC) foo.rs --crate-type=dylib -C prefer-dynamic
-	$(RUSTC) bar.rs -L $(TMPDIR)/other
-	rm -rf $(TMPDIR)
-	mkdir -p $(TMPDIR)/other
-	$(RUSTC) foo.rs --crate-type=rlib
-	mv $(TMPDIR)/libfoo.rlib $(TMPDIR)/other
-	$(RUSTC) foo.rs --crate-type=rlib
-	$(RUSTC) bar.rs -L $(TMPDIR)/other
diff --git a/tests/run-make/issue-14500/Makefile b/tests/run-make/issue-14500/Makefile
deleted file mode 100644
index eeab48de3b9..00000000000
--- a/tests/run-make/issue-14500/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-include ../tools.mk
-
-# ignore-cross-compile
-
-# Test to make sure that reachable extern fns are always available in final
-# productcs, including when LTO is used. In this test, the `foo` crate has a
-# reahable symbol, and is a dependency of the `bar` crate. When the `bar` crate
-# is compiled with LTO, it shouldn't strip the symbol from `foo`, and that's the
-# only way that `foo.c` will successfully compile.
-
-all:
-	$(RUSTC) foo.rs --crate-type=rlib
-	$(RUSTC) bar.rs --crate-type=staticlib -C lto -L. -o $(TMPDIR)/libbar.a
-	$(CC) foo.c $(TMPDIR)/libbar.a $(EXTRACFLAGS) $(call OUT_EXE,foo)
-	$(call RUN,foo)
diff --git a/tests/run-make/no-cdylib-as-rdylib/Makefile b/tests/run-make/no-cdylib-as-rdylib/Makefile
deleted file mode 100644
index 4d2be0aea91..00000000000
--- a/tests/run-make/no-cdylib-as-rdylib/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Test that rustc will not attempt to link against a cdylib as if
-# it is a rust dylib when an rlib for the same crate is available.
-# Previously rustc didn't actually check if any further formats of
-# a crate which has been loaded are of the same version and if
-# they are actually valid. This caused a cdylib to be interpreted
-# as rust dylib as soon as the corresponding rlib was loaded. As
-# cdylibs don't export any rust symbols, linking would fail if
-# rustc decides to link against the cdylib rather than the rlib.
-
-all:
-	$(RUSTC) bar.rs --crate-type=rlib --crate-type=cdylib
-	$(RUSTC) foo.rs -C prefer-dynamic
-	$(call RUN,foo)
diff --git a/tests/run-make/no-cdylib-as-rdylib/rmake.rs b/tests/run-make/no-cdylib-as-rdylib/rmake.rs
new file mode 100644
index 00000000000..42e89df6c2b
--- /dev/null
+++ b/tests/run-make/no-cdylib-as-rdylib/rmake.rs
@@ -0,0 +1,16 @@
+// This test produces an rlib and a cdylib from bar.rs.
+// Then, foo.rs attempts to link to the bar library.
+// If the test passes, that means rustc favored the rlib and ignored the cdylib.
+// If the test fails, that is because the cdylib was picked, which does not export
+// any Rust symbols.
+// See https://github.com/rust-lang/rust/pull/113695
+
+//@ ignore-cross-compile
+
+use run_make_support::{run, rustc};
+
+fn main() {
+    rustc().input("bar.rs").crate_type("rlib").crate_type("cdylib").run();
+    rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
+    run("foo");
+}
diff --git a/tests/run-make/panic-impl-transitive/Makefile b/tests/run-make/panic-impl-transitive/Makefile
deleted file mode 100644
index 9a271a22e10..00000000000
--- a/tests/run-make/panic-impl-transitive/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../tools.mk
-
-# NOTE we use --emit=llvm-ir to avoid running the linker (linking will fail because there's no main
-# in this crate)
-all:
-	$(RUSTC) panic-impl-provider.rs
-	$(RUSTC) panic-impl-consumer.rs -C panic=abort --emit=llvm-ir -L $(TMPDIR)
diff --git a/tests/run-make/panic-impl-transitive/rmake.rs b/tests/run-make/panic-impl-transitive/rmake.rs
new file mode 100644
index 00000000000..86308f593b3
--- /dev/null
+++ b/tests/run-make/panic-impl-transitive/rmake.rs
@@ -0,0 +1,19 @@
+// In Rust programs where the standard library is unavailable (#![no_std]), we may be interested
+// in customizing how panics are handled. Here, the provider specifies that panics should be handled
+// by entering an infinite loop. This test checks that this panic implementation can be transitively
+// provided by an external crate.
+// --emit=llvm-ir is used to avoid running the linker, as linking will fail due to the lack of main
+// function in the crate.
+// See https://github.com/rust-lang/rust/pull/50338
+
+use run_make_support::{rustc, tmp_dir};
+
+fn main() {
+    rustc().input("panic-impl-provider.rs").run();
+    rustc()
+        .input("panic-impl-consumer.rs")
+        .panic("abort")
+        .emit("llvm-ir")
+        .library_search_path(tmp_dir())
+        .run();
+}
diff --git a/tests/run-make/issue-14500/bar.rs b/tests/run-make/reachable-extern-fn-available-lto/bar.rs
index 49af74e1b74..49af74e1b74 100644
--- a/tests/run-make/issue-14500/bar.rs
+++ b/tests/run-make/reachable-extern-fn-available-lto/bar.rs
diff --git a/tests/run-make/issue-14500/foo.c b/tests/run-make/reachable-extern-fn-available-lto/foo.c
index 2353d400df3..2353d400df3 100644
--- a/tests/run-make/issue-14500/foo.c
+++ b/tests/run-make/reachable-extern-fn-available-lto/foo.c
diff --git a/tests/run-make/issue-14500/foo.rs b/tests/run-make/reachable-extern-fn-available-lto/foo.rs
index 7c19c1f2c67..7c19c1f2c67 100644
--- a/tests/run-make/issue-14500/foo.rs
+++ b/tests/run-make/reachable-extern-fn-available-lto/foo.rs
diff --git a/tests/run-make/reachable-extern-fn-available-lto/rmake.rs b/tests/run-make/reachable-extern-fn-available-lto/rmake.rs
new file mode 100644
index 00000000000..c7262b9461b
--- /dev/null
+++ b/tests/run-make/reachable-extern-fn-available-lto/rmake.rs
@@ -0,0 +1,26 @@
+// Test to make sure that reachable extern fns are always available in final
+// productcs, including when link time optimizations (LTO) are used.
+
+// In this test, the `foo` crate has a reahable symbol,
+// and is a dependency of the `bar` crate. When the `bar` crate
+// is compiled with LTO, it shouldn't strip the symbol from `foo`, and that's the
+// only way that `foo.c` will successfully compile.
+// See https://github.com/rust-lang/rust/issues/14500
+
+//@ ignore-cross-compile
+
+use run_make_support::{cc, extra_c_flags, run, rustc, static_lib};
+
+fn main() {
+    let libbar_path = static_lib("bar");
+    rustc().input("foo.rs").crate_type("rlib").run();
+    rustc()
+        .input("bar.rs")
+        .crate_type("staticlib")
+        .arg("-Clto")
+        .library_search_path(".")
+        .output(&libbar_path)
+        .run();
+    cc().input("foo.c").input(libbar_path).args(&extra_c_flags()).out_exe("foo").run();
+    run("foo");
+}
diff --git a/tests/run-make/rustdoc-map-file/rmake.rs b/tests/run-make/rustdoc-map-file/rmake.rs
index aaa7fea0b6b..d017b41bcdd 100644
--- a/tests/run-make/rustdoc-map-file/rmake.rs
+++ b/tests/run-make/rustdoc-map-file/rmake.rs
@@ -1,5 +1,4 @@
-use run_make_support::{rustdoc, tmp_dir};
-use std::process::Command;
+use run_make_support::{python_command, rustdoc, tmp_dir};
 
 fn main() {
     let out_dir = tmp_dir().join("out");
@@ -10,6 +9,5 @@ fn main() {
         .output(&out_dir)
         .run();
     // FIXME (GuillaumeGomez): Port the python script to Rust as well.
-    let python = std::env::var("PYTHON").unwrap_or("python".into());
-    assert!(Command::new(python).arg("validate_json.py").arg(&out_dir).status().unwrap().success());
+    assert!(python_command().arg("validate_json.py").arg(&out_dir).status().unwrap().success());
 }
diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs
index edcf3406d47..1bc23ec8881 100644
--- a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs
+++ b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs
@@ -1,4 +1,4 @@
-use run_make_support::{python_command, rustc, rustdoc, source_path, tmp_dir};
+use run_make_support::{htmldocck, rustc, rustdoc, source_path, tmp_dir};
 use std::fs::read_dir;
 use std::path::Path;
 
@@ -45,11 +45,5 @@ fn main() {
     }
     rustdoc.run();
 
-    python_command()
-        .arg(source_path().join("/src/etc/htmldocck.py"))
-        .arg(out_dir)
-        .arg("src/lib.rs")
-        .status()
-        .unwrap()
-        .success();
+    assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
 }
diff --git a/tests/run-make/rustdoc-themes/Makefile b/tests/run-make/rustdoc-themes/Makefile
deleted file mode 100644
index a4980eb0b3e..00000000000
--- a/tests/run-make/rustdoc-themes/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-include ../tools.mk
-
-# Test that rustdoc will properly load in a theme file and display it in the theme selector.
-
-OUTPUT_DIR := "$(TMPDIR)/rustdoc-themes"
-
-all:
-	awk '/Begin theme: light/ {in_theme=1;next} /End theme:/ {in_theme=0} { if (in_theme) print }' \
-		< '$(S)/src/librustdoc/html/static/css/noscript.css' > '$(TMPDIR)/test.css'
-	$(RUSTDOC) -o $(OUTPUT_DIR) foo.rs --theme $(TMPDIR)/test.css
-	$(HTMLDOCCK) $(OUTPUT_DIR) foo.rs
diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs
new file mode 100644
index 00000000000..e9da4e25940
--- /dev/null
+++ b/tests/run-make/rustdoc-themes/rmake.rs
@@ -0,0 +1,31 @@
+// Test that rustdoc will properly load in a theme file and display it in the theme selector.
+
+use run_make_support::{htmldocck, rustdoc, source_path, tmp_dir};
+
+fn main() {
+    let out_dir = tmp_dir().join("rustdoc-themes");
+    let test_css = out_dir.join("test.css");
+
+    let no_script =
+        std::fs::read_to_string(source_path().join("src/librustdoc/html/static/css/noscript.css"))
+            .unwrap();
+
+    let mut test_content = String::new();
+    let mut found_begin_light = false;
+    for line in no_script.split('\n') {
+        if line == "/* Begin theme: light */" {
+            found_begin_light = true;
+        } else if line == "/* End theme: light */" {
+            break;
+        } else if found_begin_light {
+            test_content.push_str(line);
+            test_content.push('\n');
+        }
+    }
+    assert!(!test_content.is_empty());
+    std::fs::create_dir_all(&out_dir).unwrap();
+    std::fs::write(&test_css, test_content).unwrap();
+
+    rustdoc().output(&out_dir).input("foo.rs").arg("--theme").arg(&test_css).run();
+    assert!(htmldocck().arg(out_dir).arg("foo.rs").status().unwrap().success());
+}
diff --git a/tests/run-make/rustdoc-with-out-dir-option/Makefile b/tests/run-make/rustdoc-with-out-dir-option/Makefile
deleted file mode 100644
index f5d5060ed13..00000000000
--- a/tests/run-make/rustdoc-with-out-dir-option/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
-OUTPUT_DIR := "$(TMPDIR)/rustdoc"
-
-all:
-	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR)
-
-	$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/tests/run-make/rustdoc-with-out-dir-option/rmake.rs b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs
new file mode 100644
index 00000000000..86471093834
--- /dev/null
+++ b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs
@@ -0,0 +1,7 @@
+use run_make_support::{htmldocck, rustdoc, tmp_dir};
+
+fn main() {
+    let out_dir = tmp_dir().join("rustdoc");
+    rustdoc().input("src/lib.rs").crate_name("foobar").crate_type("lib").output(&out_dir).run();
+    assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
+}
diff --git a/tests/run-make/issue-11908/bar.rs b/tests/run-make/same-lib-two-locations-no-panic/bar.rs
index bb7b36c496e..bb7b36c496e 100644
--- a/tests/run-make/issue-11908/bar.rs
+++ b/tests/run-make/same-lib-two-locations-no-panic/bar.rs
diff --git a/tests/run-make/issue-11908/foo.rs b/tests/run-make/same-lib-two-locations-no-panic/foo.rs
index 82b2dfe9fdb..82b2dfe9fdb 100644
--- a/tests/run-make/issue-11908/foo.rs
+++ b/tests/run-make/same-lib-two-locations-no-panic/foo.rs
diff --git a/tests/run-make/same-lib-two-locations-no-panic/rmake.rs b/tests/run-make/same-lib-two-locations-no-panic/rmake.rs
new file mode 100644
index 00000000000..2900c3c8b74
--- /dev/null
+++ b/tests/run-make/same-lib-two-locations-no-panic/rmake.rs
@@ -0,0 +1,28 @@
+// A path which contains the same rlib or dylib in two locations
+// should not cause an assertion panic in the compiler.
+// This test tries to replicate the linked issue and checks
+// if the bugged error makes a resurgence.
+
+// See https://github.com/rust-lang/rust/issues/11908
+
+//@ ignore-cross-compile
+
+use run_make_support::{dynamic_lib, rust_lib, rustc, tmp_dir};
+use std::fs;
+
+fn main() {
+    let tmp_dir_other = tmp_dir().join("other");
+
+    fs::create_dir(&tmp_dir_other);
+    rustc().input("foo.rs").crate_type("dylib").arg("-Cprefer-dynamic").run();
+    fs::rename(dynamic_lib("foo"), &tmp_dir_other);
+    rustc().input("foo.rs").crate_type("dylib").arg("-Cprefer-dynamic").run();
+    rustc().input("bar.rs").library_search_path(&tmp_dir_other).run();
+    fs::remove_dir_all(tmp_dir());
+
+    fs::create_dir_all(&tmp_dir_other);
+    rustc().input("foo.rs").crate_type("rlib").run();
+    fs::rename(rust_lib("foo"), &tmp_dir_other);
+    rustc().input("foo.rs").crate_type("rlib").run();
+    rustc().input("bar.rs").library_search_path(tmp_dir_other).run();
+}
diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-negative.negative.html b/tests/rustdoc/notable-trait/doc-notable_trait-negative.negative.html
new file mode 100644
index 00000000000..6f19558cc15
--- /dev/null
+++ b/tests/rustdoc/notable-trait/doc-notable_trait-negative.negative.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"Negative":"&lt;/code&gt;&lt;/pre&gt;"}</script>
\ No newline at end of file
diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-negative.positive.html b/tests/rustdoc/notable-trait/doc-notable_trait-negative.positive.html
new file mode 100644
index 00000000000..a3d0fedaaf4
--- /dev/null
+++ b/tests/rustdoc/notable-trait/doc-notable_trait-negative.positive.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"Positive":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Positive.html\" title=\"struct doc_notable_trait_negative::Positive\"&gt;Positive&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;div class=\"where\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait_negative::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Positive.html\" title=\"struct doc_notable_trait_negative::Positive\"&gt;Positive&lt;/a&gt;&lt;/div&gt;"}</script>
\ No newline at end of file
diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-negative.rs b/tests/rustdoc/notable-trait/doc-notable_trait-negative.rs
new file mode 100644
index 00000000000..2bbe0a3ef8c
--- /dev/null
+++ b/tests/rustdoc/notable-trait/doc-notable_trait-negative.rs
@@ -0,0 +1,22 @@
+#![feature(doc_notable_trait, negative_impls)]
+
+#[doc(notable_trait)]
+pub trait SomeTrait {}
+
+pub struct Positive;
+impl SomeTrait for Positive {}
+
+pub struct Negative;
+impl !SomeTrait for Negative {}
+
+// @has doc_notable_trait_negative/fn.positive.html
+// @snapshot positive - '//script[@id="notable-traits-data"]'
+pub fn positive() -> Positive {
+    todo!()
+}
+
+// @has doc_notable_trait_negative/fn.negative.html
+// @count - '//script[@id="notable-traits-data"]' 0
+pub fn negative() -> Negative {
+    &[]
+}
diff --git a/tests/ui/const-generics/lookup-method.rs b/tests/ui/const-generics/lookup-method.rs
new file mode 100644
index 00000000000..915935c94a5
--- /dev/null
+++ b/tests/ui/const-generics/lookup-method.rs
@@ -0,0 +1,19 @@
+// https://github.com/rust-lang/rust/issues/124946
+
+struct Builder<const A: bool, const B: bool>;
+
+impl<const A: bool> Builder<A, false> {
+    fn cast(self) -> Builder<A, true> {
+        Builder
+    }
+}
+
+impl Builder<true, true> {
+    fn build(self) {}
+}
+
+fn main() {
+    let b = Builder::<false, false>;
+    b.cast().build();
+    //~^ ERROR: no method named `build` found for struct `Builder<false, true>` in the current scope
+}
diff --git a/tests/ui/const-generics/lookup-method.stderr b/tests/ui/const-generics/lookup-method.stderr
new file mode 100644
index 00000000000..4cbd1e17c7b
--- /dev/null
+++ b/tests/ui/const-generics/lookup-method.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `build` found for struct `Builder<false, true>` in the current scope
+  --> $DIR/lookup-method.rs:17:14
+   |
+LL | struct Builder<const A: bool, const B: bool>;
+   | -------------------------------------------- method `build` not found for this struct
+...
+LL |     b.cast().build();
+   |              ^^^^^ method not found in `Builder<false, true>`
+   |
+   = note: the method was found for
+           - `Builder<true, true>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/delegation/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs
index d2723dc32e0..f378e05304b 100644
--- a/tests/ui/delegation/bad-resolve.rs
+++ b/tests/ui/delegation/bad-resolve.rs
@@ -36,4 +36,8 @@ impl Trait for S {
     //~^ ERROR cannot find function `foo` in this scope
 }
 
+mod prefix {}
+reuse unresolved_prefix::{a, b, c}; //~ ERROR use of undeclared crate or module `unresolved_prefix`
+reuse prefix::{self, super, crate}; //~ ERROR `crate` in paths can only be used in start position
+
 fn main() {}
diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr
index f669ac3730e..883ff523bcf 100644
--- a/tests/ui/delegation/bad-resolve.stderr
+++ b/tests/ui/delegation/bad-resolve.stderr
@@ -63,7 +63,19 @@ LL |     type Type;
 LL | impl Trait for S {
    | ^^^^^^^^^^^^^^^^ missing `Type` in implementation
 
-error: aborting due to 8 previous errors
+error[E0433]: failed to resolve: use of undeclared crate or module `unresolved_prefix`
+  --> $DIR/bad-resolve.rs:40:7
+   |
+LL | reuse unresolved_prefix::{a, b, c};
+   |       ^^^^^^^^^^^^^^^^^ use of undeclared crate or module `unresolved_prefix`
+
+error[E0433]: failed to resolve: `crate` in paths can only be used in start position
+  --> $DIR/bad-resolve.rs:41:29
+   |
+LL | reuse prefix::{self, super, crate};
+   |                             ^^^^^ `crate` in paths can only be used in start position
+
+error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0575, E0576.
+Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0433, E0575, E0576.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/delegation/body-identity-list.rs b/tests/ui/delegation/body-identity-list.rs
new file mode 100644
index 00000000000..1f08ab4e1a4
--- /dev/null
+++ b/tests/ui/delegation/body-identity-list.rs
@@ -0,0 +1,32 @@
+//@ check-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait Trait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+}
+
+impl Trait for u8 {}
+
+struct S(u8);
+
+mod to_import {
+    pub fn check(arg: &u8) -> &u8 { arg }
+}
+
+impl Trait for S {
+    reuse Trait::{foo, bar} {
+        use to_import::check;
+
+        let _arr = Some(self.0).map(|x| [x * 2; 3]);
+        check(&self.0)
+    }
+}
+
+fn main() {
+    let s = S(0);
+    s.foo();
+    s.bar();
+}
diff --git a/tests/ui/delegation/empty-list.rs b/tests/ui/delegation/empty-list.rs
new file mode 100644
index 00000000000..e0697f42283
--- /dev/null
+++ b/tests/ui/delegation/empty-list.rs
@@ -0,0 +1,8 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod m {}
+
+reuse m::{}; //~ ERROR empty list delegation is not supported
+
+fn main() {}
diff --git a/tests/ui/delegation/empty-list.stderr b/tests/ui/delegation/empty-list.stderr
new file mode 100644
index 00000000000..50d3c0eee22
--- /dev/null
+++ b/tests/ui/delegation/empty-list.stderr
@@ -0,0 +1,8 @@
+error: empty list delegation is not supported
+  --> $DIR/empty-list.rs:6:1
+   |
+LL | reuse m::{};
+   | ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/delegation/inner-attr.rs b/tests/ui/delegation/inner-attr.rs
new file mode 100644
index 00000000000..6c996807d6b
--- /dev/null
+++ b/tests/ui/delegation/inner-attr.rs
@@ -0,0 +1,8 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+fn a() {}
+
+reuse a as b { #![rustc_dummy] self } //~ ERROR an inner attribute is not permitted in this context
+
+fn main() {}
diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr
new file mode 100644
index 00000000000..f3b53e331ad
--- /dev/null
+++ b/tests/ui/delegation/inner-attr.stderr
@@ -0,0 +1,18 @@
+error: an inner attribute is not permitted in this context
+  --> $DIR/inner-attr.rs:6:16
+   |
+LL | reuse a as b { #![rustc_dummy] self }
+   |                ^^^^^^^^^^^^^^^
+LL |
+LL | fn main() {}
+   | ------------ the inner attribute doesn't annotate this function
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - reuse a as b { #![rustc_dummy] self }
+LL + reuse a as b { #[rustc_dummy] self }
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/delegation/list.rs b/tests/ui/delegation/list.rs
new file mode 100644
index 00000000000..208b1481679
--- /dev/null
+++ b/tests/ui/delegation/list.rs
@@ -0,0 +1,46 @@
+//@ check-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait Trait {
+    fn foo(&self) -> u8 { 0 }
+    fn bar(&self) -> u8 { 1 }
+}
+
+impl Trait for u8 {}
+
+struct S(u8);
+struct Z(u8);
+
+impl Trait for S {
+    reuse Trait::{foo, bar} { &self.0 }
+}
+
+impl Trait for Z {
+    reuse <u8 as Trait>::{foo, bar} { &self.0 }
+}
+
+trait Trait2 where Self: Trait {
+    reuse Trait::{foo, bar};
+}
+
+mod to_reuse {
+    pub fn a() {}
+    pub fn b() {}
+}
+
+reuse to_reuse::{a, b};
+
+fn main() {
+    let s = S(2);
+    s.foo();
+    s.bar();
+
+    let z = Z(3);
+    z.foo();
+    z.bar();
+
+    a();
+    b();
+}
diff --git a/tests/ui/delegation/macro-inside-list.rs b/tests/ui/delegation/macro-inside-list.rs
new file mode 100644
index 00000000000..16c74d396ef
--- /dev/null
+++ b/tests/ui/delegation/macro-inside-list.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait Trait {
+    fn foo(&self) -> u8 { 0 }
+    fn bar(&self) -> u8 { 1 }
+}
+
+impl Trait for u8 {}
+
+struct S(u8);
+
+// Macro expansion works inside delegation items.
+macro_rules! u8 { () => { u8 } }
+macro_rules! self_0 { () => { &self.0 } }
+impl Trait for S {
+    reuse <u8!() as Trait>::{foo, bar} { self_0!() }
+}
+
+fn main() {
+    let s = S(2);
+    s.foo();
+    s.bar();
+}
diff --git a/tests/ui/delegation/rename.rs b/tests/ui/delegation/rename.rs
index f4b3da76c56..80b8724a5bf 100644
--- a/tests/ui/delegation/rename.rs
+++ b/tests/ui/delegation/rename.rs
@@ -5,16 +5,23 @@
 
 mod to_reuse {
     pub fn a() {}
+    pub fn b() {}
 }
 
-reuse to_reuse::a as b;
+reuse to_reuse::a as x;
+reuse to_reuse::{a as y, b as z};
 
 struct S;
 impl S {
-    reuse to_reuse::a as b;
+    reuse to_reuse::a as x;
+    reuse to_reuse::{a as y, b as z};
 }
 
 fn main() {
-    b();
-    S::b();
+    x();
+    y();
+    z();
+    S::x();
+    S::y();
+    S::z();
 }
diff --git a/tests/ui/diagnostic_namespace/suggest_typos.rs b/tests/ui/diagnostic_namespace/suggest_typos.rs
new file mode 100644
index 00000000000..b25f097a8ad
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/suggest_typos.rs
@@ -0,0 +1,18 @@
+#![deny(unknown_or_malformed_diagnostic_attributes)]
+
+#[diagnostic::onunimplemented]
+//~^ERROR unknown diagnostic attribute
+//~^^HELP an attribute with a similar name exists
+trait X{}
+
+#[diagnostic::un_onimplemented]
+//~^ERROR unknown diagnostic attribute
+//~^^HELP an attribute with a similar name exists
+trait Y{}
+
+#[diagnostic::on_implemented]
+//~^ERROR unknown diagnostic attribute
+//~^^HELP an attribute with a similar name exists
+trait Z{}
+
+fn main(){}
diff --git a/tests/ui/diagnostic_namespace/suggest_typos.stderr b/tests/ui/diagnostic_namespace/suggest_typos.stderr
new file mode 100644
index 00000000000..307311258f2
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/suggest_typos.stderr
@@ -0,0 +1,40 @@
+error: unknown diagnostic attribute
+  --> $DIR/suggest_typos.rs:3:15
+   |
+LL | #[diagnostic::onunimplemented]
+   |               ^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/suggest_typos.rs:1:9
+   |
+LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: an attribute with a similar name exists
+   |
+LL | #[diagnostic::on_unimplemented]
+   |               ~~~~~~~~~~~~~~~~
+
+error: unknown diagnostic attribute
+  --> $DIR/suggest_typos.rs:8:15
+   |
+LL | #[diagnostic::un_onimplemented]
+   |               ^^^^^^^^^^^^^^^^
+   |
+help: an attribute with a similar name exists
+   |
+LL | #[diagnostic::on_unimplemented]
+   |               ~~~~~~~~~~~~~~~~
+
+error: unknown diagnostic attribute
+  --> $DIR/suggest_typos.rs:13:15
+   |
+LL | #[diagnostic::on_implemented]
+   |               ^^^^^^^^^^^^^^
+   |
+help: an attribute with a similar name exists
+   |
+LL | #[diagnostic::on_unimplemented]
+   |               ~~~~~~~~~~~~~~~~
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/macros/macro-span-issue-116502.rs b/tests/ui/macros/macro-span-issue-116502.rs
new file mode 100644
index 00000000000..4c254289ee6
--- /dev/null
+++ b/tests/ui/macros/macro-span-issue-116502.rs
@@ -0,0 +1,16 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+fn bug() {
+    macro_rules! m {
+        () => {
+            _ //~ ERROR the placeholder `_` is not allowed within types on item signatures for structs
+        };
+    }
+    struct S<T = m!()>(m!(), T)
+    where
+        T: Trait<m!()>;
+}
+trait Trait<T> {}
+
+fn main() {}
diff --git a/tests/ui/macros/macro-span-issue-116502.stderr b/tests/ui/macros/macro-span-issue-116502.stderr
new file mode 100644
index 00000000000..da02855660a
--- /dev/null
+++ b/tests/ui/macros/macro-span-issue-116502.stderr
@@ -0,0 +1,30 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/macro-span-issue-116502.rs:7:13
+   |
+LL |             _
+   |             ^
+   |             |
+   |             not allowed in type signatures
+   |             not allowed in type signatures
+   |             not allowed in type signatures
+...
+LL |     struct S<T = m!()>(m!(), T)
+   |                  ----  ---- in this macro invocation
+   |                  |
+   |                  in this macro invocation
+LL |     where
+LL |         T: Trait<m!()>;
+   |                  ---- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use type parameters instead
+   |
+LL ~             U
+LL |         };
+LL |     }
+LL ~     struct S<U>(m!(), T)
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/macros/meta-variable-depth-outside-repeat.rs b/tests/ui/macros/meta-variable-depth-outside-repeat.rs
index b7fb947854f..89b47063606 100644
--- a/tests/ui/macros/meta-variable-depth-outside-repeat.rs
+++ b/tests/ui/macros/meta-variable-depth-outside-repeat.rs
@@ -2,8 +2,8 @@
 
 macro_rules! metavar {
     ( $i:expr ) => {
-        ${length(0)}
-        //~^ ERROR meta-variable expression `length` with depth parameter must be called inside of a macro repetition
+        ${len(0)}
+        //~^ ERROR meta-variable expression `len` with depth parameter must be called inside of a macro repetition
     };
 }
 
diff --git a/tests/ui/macros/meta-variable-depth-outside-repeat.stderr b/tests/ui/macros/meta-variable-depth-outside-repeat.stderr
index 49b5053a023..4299ca98424 100644
--- a/tests/ui/macros/meta-variable-depth-outside-repeat.stderr
+++ b/tests/ui/macros/meta-variable-depth-outside-repeat.stderr
@@ -1,8 +1,8 @@
-error: meta-variable expression `length` with depth parameter must be called inside of a macro repetition
+error: meta-variable expression `len` with depth parameter must be called inside of a macro repetition
   --> $DIR/meta-variable-depth-outside-repeat.rs:5:10
    |
-LL |         ${length(0)}
-   |          ^^^^^^^^^^^
+LL |         ${len(0)}
+   |          ^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs
index 3a14e0c64fd..131d4166de0 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs
+++ b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs
@@ -3,60 +3,55 @@
 #![feature(macro_metavar_expr)]
 
 fn main() {
-    macro_rules! one_nested_count_and_length {
+    macro_rules! one_nested_count_and_len {
         ( $( [ $( $l:literal ),* ] ),* ) => {
             [
                 // outer-most repetition
                 $(
                     // inner-most repetition
                     $(
-                        ${ignore($l)} ${index()}, ${length()},
+                        ${ignore($l)} ${index()}, ${len()},
                     )*
-                    ${count($l)}, ${index()}, ${length()},
+                    ${count($l)}, ${index()}, ${len()},
                 )*
                 ${count($l)},
             ]
         };
     }
     assert_eq!(
-        one_nested_count_and_length!(["foo"], ["bar", "baz"]),
+        one_nested_count_and_len!(["foo"], ["bar", "baz"]),
         [
             // # ["foo"]
 
             // ## inner-most repetition (first iteration)
             //
             // `index` is 0 because this is the first inner-most iteration.
-            // `length` is 1 because there is only one inner-most repetition, "foo".
+            // `len` is 1 because there is only one inner-most repetition, "foo".
             0, 1,
-
             // ## outer-most repetition (first iteration)
             //
             // `count` is 1 because of "foo", i,e, `$l` has only one repetition,
             // `index` is 0 because this is the first outer-most iteration.
-            // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"]
+            // `len` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"]
             1, 0, 2,
-
             // # ["bar", "baz"]
 
             // ## inner-most repetition (first iteration)
             //
             // `index` is 0 because this is the first inner-most iteration
-            // `length` is 2 because there are repetitions, "bar" and "baz"
+            // `len` is 2 because there are repetitions, "bar" and "baz"
             0, 2,
-
             // ## inner-most repetition (second iteration)
             //
             // `index` is 1 because this is the second inner-most iteration
-            // `length` is 2 because there are repetitions, "bar" and "baz"
+            // `len` is 2 because there are repetitions, "bar" and "baz"
             1, 2,
-
             // ## outer-most repetition (second iteration)
             //
             // `count` is 2 because of "bar" and "baz", i,e, `$l` has two repetitions,
             // `index` is 1 because this is the second outer-most iteration
-            // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"]
+            // `len` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"]
             2, 1, 2,
-
             // # last count
 
             // Because there are a total of 3 repetitions of `$l`, "foo", "bar" and "baz"
@@ -131,7 +126,6 @@ fn main() {
             &[2][..],
             // t u v w x y z
             &[7][..],
-
             // (a b c) (d e f)
             &[6, 2][..],
             // (g h) (i j k l m)
@@ -142,7 +136,6 @@ fn main() {
             &[5, 3][..],
             // (t u v w x y z)
             &[7, 1][..],
-
             // [ (a b c) (d e f) ]
             // [ (g h) (i j k l m) ]
             // [ (n) ]
@@ -150,7 +143,6 @@ fn main() {
             // [ (o) (p q) (r s) ]
             // [ (t u v w x y z) ]
             &[12, 4, 2][..],
-
             // {
             //     [ (a b c) (d e f) ]
             //     [ (g h) (i j k l m) ]
@@ -165,43 +157,43 @@ fn main() {
     );
 
     // Grouped from the outer-most to the inner-most
-    macro_rules! three_nested_length {
+    macro_rules! three_nested_len {
         ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => {
             &[
                 $( $( $( $(
                     &[
-                        ${ignore($i)} ${length(3)},
-                        ${ignore($i)} ${length(2)},
-                        ${ignore($i)} ${length(1)},
-                        ${ignore($i)} ${length(0)},
+                        ${ignore($i)} ${len(3)},
+                        ${ignore($i)} ${len(2)},
+                        ${ignore($i)} ${len(1)},
+                        ${ignore($i)} ${len(0)},
                     ][..],
                 )* )* )* )*
 
                 $( $( $(
                     &[
-                        ${ignore($i)} ${length(2)},
-                        ${ignore($i)} ${length(1)},
-                        ${ignore($i)} ${length(0)},
+                        ${ignore($i)} ${len(2)},
+                        ${ignore($i)} ${len(1)},
+                        ${ignore($i)} ${len(0)},
                     ][..],
                 )* )* )*
 
                 $( $(
                     &[
-                        ${ignore($i)} ${length(1)},
-                        ${ignore($i)} ${length(0)},
+                        ${ignore($i)} ${len(1)},
+                        ${ignore($i)} ${len(0)},
                     ][..],
                 )* )*
 
                 $(
                     &[
-                        ${ignore($i)} ${length(0)},
+                        ${ignore($i)} ${len(0)},
                     ][..],
                 )*
             ][..]
         }
     }
     assert_eq!(
-        three_nested_length!(
+        three_nested_len!(
             {
                 [ (a b c) (d e f) ]
                 [ (g h) (i j k l m) ]
@@ -214,45 +206,64 @@ fn main() {
         ),
         &[
             // a b c
-            &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..],
+            &[2, 3, 2, 3][..],
+            &[2, 3, 2, 3][..],
+            &[2, 3, 2, 3][..],
             // d e f
-            &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..],
+            &[2, 3, 2, 3][..],
+            &[2, 3, 2, 3][..],
+            &[2, 3, 2, 3][..],
             // g h
-            &[2, 3, 2, 2][..], &[2, 3, 2, 2][..],
+            &[2, 3, 2, 2][..],
+            &[2, 3, 2, 2][..],
             // i j k l m
-            &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..],
+            &[2, 3, 2, 5][..],
+            &[2, 3, 2, 5][..],
+            &[2, 3, 2, 5][..],
+            &[2, 3, 2, 5][..],
             &[2, 3, 2, 5][..],
             // n
             &[2, 3, 1, 1][..],
             // o
             &[2, 2, 3, 1][..],
             // p q
-            &[2, 2, 3, 2][..], &[2, 2, 3, 2][..],
+            &[2, 2, 3, 2][..],
+            &[2, 2, 3, 2][..],
             // r s
-            &[2, 2, 3, 2][..], &[2, 2, 3, 2][..],
+            &[2, 2, 3, 2][..],
+            &[2, 2, 3, 2][..],
             // t u v w x y z
-            &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..],
-            &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..],
-
+            &[2, 2, 1, 7][..],
+            &[2, 2, 1, 7][..],
+            &[2, 2, 1, 7][..],
+            &[2, 2, 1, 7][..],
+            &[2, 2, 1, 7][..],
+            &[2, 2, 1, 7][..],
+            &[2, 2, 1, 7][..],
             // (a b c) (d e f)
-            &[2, 3, 2][..], &[2, 3, 2][..],
+            &[2, 3, 2][..],
+            &[2, 3, 2][..],
             // (g h) (i j k l m)
-            &[2, 3, 2][..], &[2, 3, 2][..],
+            &[2, 3, 2][..],
+            &[2, 3, 2][..],
             // (n)
             &[2, 3, 1][..],
             // (o) (p q) (r s)
-            &[2, 2, 3][..], &[2, 2, 3][..], &[2, 2, 3][..],
+            &[2, 2, 3][..],
+            &[2, 2, 3][..],
+            &[2, 2, 3][..],
             // (t u v w x y z)
             &[2, 2, 1][..],
-
             // [ (a b c) (d e f) ]
             // [ (g h) (i j k l m) ]
             // [ (n) ]
-            &[2, 3][..], &[2, 3][..],  &[2, 3,][..],
+            &[2, 3][..],
+            &[2, 3][..],
+            &[2, 3,][..],
             // [ (o) (p q) (r s) ]
             // [ (t u v w x y z) ]
-            &[2, 2][..], &[2, 2][..],
-
+            &[2, 2][..],
+            &[2, 2][..],
             // {
             //     [ (a b c) (d e f) ]
             //     [ (g h) (i j k l m) ]
@@ -262,10 +273,11 @@ fn main() {
             //     [ (o) (p q) (r s) ]
             //     [ (t u v w x y z) ]
             // }
-            &[2][..], &[2][..]
+            &[2][..],
+            &[2][..]
         ][..]
     );
 
-    // It is possible to say, to some degree, that count is an "amalgamation" of length (see
-    // each length line result and compare them with the count results)
+    // It is possible to say, to some degree, that count is an "amalgamation" of len (see
+    // each len line result and compare them with the count results)
 }
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs b/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs
index 6464fd6f2fd..51445221c57 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs
+++ b/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs
@@ -37,17 +37,17 @@ macro_rules! count_depth_limits {
     };
 }
 
-/// Produce (index, length) pairs for literals in a macro repetition.
+/// Produce (index, len) pairs for literals in a macro repetition.
 /// The literal is not included in the output, so this macro uses the
 /// `ignore` meta-variable expression to create a non-expanding
 /// repetition binding.
 macro_rules! enumerate_literals {
     ( $( ($l:stmt) ),* ) => {
-        [$( ${ignore($l)} (${index()}, ${length()}) ),*]
+        [$( ${ignore($l)} (${index()}, ${len()}) ),*]
     };
 }
 
-/// Produce index and length tuples for literals in a 2-dimensional
+/// Produce index and len tuples for literals in a 2-dimensional
 /// macro repetition.
 macro_rules! enumerate_literals_2 {
     ( $( [ $( ($l:literal) ),* ] ),* ) => {
@@ -56,9 +56,9 @@ macro_rules! enumerate_literals_2 {
                 $(
                     (
                         ${index(1)},
-                        ${length(1)},
+                        ${len(1)},
                         ${index(0)},
-                        ${length(0)},
+                        ${len(0)},
                         $l
                     ),
                 )*
@@ -134,7 +134,6 @@ fn main() {
             (0, 2, 0, 3, "foo"),
             (0, 2, 1, 3, "bar"),
             (0, 2, 2, 3, "baz"),
-
             (1, 2, 0, 4, "qux"),
             (1, 2, 1, 4, "quux"),
             (1, 2, 2, 4, "quuz"),
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs b/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs
index 787b927c449..1d34275874b 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs
+++ b/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs
@@ -17,20 +17,20 @@ macro_rules! example {
             _nested: vec![
             $(
                 Example {
-                    _indexes: &[(${index()}, ${length()})],
+                    _indexes: &[(${index()}, ${len()})],
                     _counts: &[${count($x, 0)}, ${count($x, 1)}],
                     _nested: vec![
                     $(
                         Example {
-                            _indexes: &[(${index(1)}, ${length(1)}), (${index()}, ${length()})],
+                            _indexes: &[(${index(1)}, ${len(1)}), (${index()}, ${len()})],
                             _counts: &[${count($x)}],
                             _nested: vec![
                             $(
                                 Example {
                                     _indexes: &[
-                                        (${index(2)}, ${length(2)}),
-                                        (${index(1)}, ${length(1)}),
-                                        (${index()}, ${length()})
+                                        (${index(2)}, ${len(2)}),
+                                        (${index(1)}, ${len(1)}),
+                                        (${index()}, ${len()})
                                     ],
                                     _counts: &[],
                                     _nested: vec![],
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs
index d195506af36..0caa3ea89e4 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs
+++ b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs
@@ -28,9 +28,9 @@ macro_rules! c {
         (
             $( $(
                 ${ignore($foo)}
-                ${length(0)}
-                ${length(10)}
-                //~^ ERROR depth parameter of meta-variable expression `length` must be less than 2
+                ${len(0)}
+                ${len(10)}
+                //~^ ERROR depth parameter of meta-variable expression `len` must be less than 2
             )* )*
         )
     };
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr
index f757b8af219..0b441cad083 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr
+++ b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr
@@ -10,11 +10,11 @@ error: depth parameter of meta-variable expression `index` must be less than 3
 LL |                 ${index(10)},
    |                  ^^^^^^^^^^^
 
-error: depth parameter of meta-variable expression `length` must be less than 2
+error: depth parameter of meta-variable expression `len` must be less than 2
   --> $DIR/out-of-bounds-arguments.rs:32:18
    |
-LL |                 ${length(10)}
-   |                  ^^^^^^^^^^^^
+LL |                 ${len(10)}
+   |                  ^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs
index 53d045700f9..77c165e3855 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs
+++ b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs
@@ -32,13 +32,12 @@ macro_rules! ignore {
     }};
 }
 
-macro_rules! length {
+macro_rules! len {
     ( $( $e:stmt ),* ) => {
-        $( ${ignore($e)} ${length()} )*
+        $( ${ignore($e)} ${len()} )*
         //~^ ERROR meta-variable expressions are unstable
         //~| ERROR meta-variable expressions are unstable
     };
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
index 7f4adb728c0..f28f822a058 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
+++ b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
@@ -81,7 +81,7 @@ LL |         0 $( + 1 ${ignore($i)} )*
 error[E0658]: meta-variable expressions are unstable
   --> $DIR/required-feature.rs:37:13
    |
-LL |         $( ${ignore($e)} ${length()} )*
+LL |         $( ${ignore($e)} ${len()} )*
    |             ^^^^^^^^^^^^
    |
    = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
@@ -91,8 +91,8 @@ LL |         $( ${ignore($e)} ${length()} )*
 error[E0658]: meta-variable expressions are unstable
   --> $DIR/required-feature.rs:37:27
    |
-LL |         $( ${ignore($e)} ${length()} )*
-   |                           ^^^^^^^^^^
+LL |         $( ${ignore($e)} ${len()} )*
+   |                           ^^^^^^^
    |
    = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
    = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
index 05c65fe8690..9fec546ecd6 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
+++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs
@@ -18,23 +18,27 @@ macro_rules! curly__rhs_dollar__no_round {
     //~^ ERROR `count` can not be placed inside the inner-most repetition
 }
 
+#[rustfmt::skip] // autoformatters can break a few of the error traces
 macro_rules! no_curly__no_rhs_dollar__round {
     ( $( $i:ident ),* ) => { count(i) };
     //~^ ERROR cannot find function `count` in this scope
     //~| ERROR cannot find value `i` in this scope
 }
 
+#[rustfmt::skip] // autoformatters can break a few of the error traces
 macro_rules! no_curly__no_rhs_dollar__no_round {
     ( $i:ident ) => { count(i) };
     //~^ ERROR cannot find function `count` in this scope
     //~| ERROR cannot find value `i` in this scope
 }
 
+#[rustfmt::skip] // autoformatters can break a few of the error traces
 macro_rules! no_curly__rhs_dollar__round {
     ( $( $i:ident ),* ) => { count($i) };
     //~^ ERROR variable 'i' is still repeating at this depth
 }
 
+#[rustfmt::skip] // autoformatters can break a few of the error traces
 macro_rules! no_curly__rhs_dollar__no_round {
     ( $i:ident ) => { count($i) };
     //~^ ERROR cannot find function `count` in this scope
@@ -44,7 +48,7 @@ macro_rules! no_curly__rhs_dollar__no_round {
 
 macro_rules! dollar_dollar_in_the_lhs {
     ( $$ $a:ident ) => {
-    //~^ ERROR unexpected token: $
+        //~^ ERROR unexpected token: $
     };
 }
 
@@ -85,7 +89,7 @@ macro_rules! metavar_depth_is_not_literal {
 }
 
 macro_rules! metavar_in_the_lhs {
-    ( ${ length() } ) => {
+    ( ${ len() } ) => {
         //~^ ERROR unexpected token: {
         //~| ERROR expected one of: `*`, `+`, or `?`
     };
@@ -109,6 +113,7 @@ macro_rules! metavar_without_parens {
     //~| ERROR expected expression, found `$`
 }
 
+#[rustfmt::skip]
 macro_rules! open_brackets_without_tokens {
     ( $( $i:ident ),* ) => { ${ {} } };
     //~^ ERROR expected expression, found `$`
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
index 0dda38290ab..e9cef5ec6cc 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
+++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
@@ -1,200 +1,200 @@
 error: unexpected token: $
-  --> $DIR/syntax-errors.rs:46:8
+  --> $DIR/syntax-errors.rs:50:8
    |
 LL |     ( $$ $a:ident ) => {
    |        ^
 
 note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
-  --> $DIR/syntax-errors.rs:46:8
+  --> $DIR/syntax-errors.rs:50:8
    |
 LL |     ( $$ $a:ident ) => {
    |        ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:53:19
+  --> $DIR/syntax-errors.rs:57:19
    |
 LL |         ${count() a b c}
    |                   ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:53:19
+  --> $DIR/syntax-errors.rs:57:19
    |
 LL |         ${count() a b c}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:56:20
+  --> $DIR/syntax-errors.rs:60:20
    |
 LL |         ${count($i a b c)}
    |                    ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:56:20
+  --> $DIR/syntax-errors.rs:60:20
    |
 LL |         ${count($i a b c)}
    |                    ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:58:23
+  --> $DIR/syntax-errors.rs:62:23
    |
 LL |         ${count($i, 1 a b c)}
    |                       ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:58:23
+  --> $DIR/syntax-errors.rs:62:23
    |
 LL |         ${count($i, 1 a b c)}
    |                       ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:60:21
+  --> $DIR/syntax-errors.rs:64:21
    |
 LL |         ${count($i) a b c}
    |                     ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:60:21
+  --> $DIR/syntax-errors.rs:64:21
    |
 LL |         ${count($i) a b c}
    |                     ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:63:22
+  --> $DIR/syntax-errors.rs:67:22
    |
 LL |         ${ignore($i) a b c}
    |                      ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:63:22
+  --> $DIR/syntax-errors.rs:67:22
    |
 LL |         ${ignore($i) a b c}
    |                      ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:65:21
+  --> $DIR/syntax-errors.rs:69:21
    |
 LL |         ${ignore($i a b c)}
    |                     ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:65:21
+  --> $DIR/syntax-errors.rs:69:21
    |
 LL |         ${ignore($i a b c)}
    |                     ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:68:19
+  --> $DIR/syntax-errors.rs:72:19
    |
 LL |         ${index() a b c}
    |                   ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:68:19
+  --> $DIR/syntax-errors.rs:72:19
    |
 LL |         ${index() a b c}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:70:19
+  --> $DIR/syntax-errors.rs:74:19
    |
 LL |         ${index(1 a b c)}
    |                   ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:70:19
+  --> $DIR/syntax-errors.rs:74:19
    |
 LL |         ${index(1 a b c)}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:73:19
+  --> $DIR/syntax-errors.rs:77:19
    |
 LL |         ${index() a b c}
    |                   ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:73:19
+  --> $DIR/syntax-errors.rs:77:19
    |
 LL |         ${index() a b c}
    |                   ^
 
 error: unexpected token: a
-  --> $DIR/syntax-errors.rs:75:19
+  --> $DIR/syntax-errors.rs:79:19
    |
 LL |         ${index(1 a b c)}
    |                   ^
    |
 note: meta-variable expression must not have trailing tokens
-  --> $DIR/syntax-errors.rs:75:19
+  --> $DIR/syntax-errors.rs:79:19
    |
 LL |         ${index(1 a b c)}
    |                   ^
 
 error: meta-variable expression depth must be a literal
-  --> $DIR/syntax-errors.rs:82:33
+  --> $DIR/syntax-errors.rs:86:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ index(IDX) } };
    |                                 ^^^^^
 
 error: unexpected token: {
-  --> $DIR/syntax-errors.rs:88:8
+  --> $DIR/syntax-errors.rs:92:8
    |
-LL |     ( ${ length() } ) => {
-   |        ^^^^^^^^^^^^
+LL |     ( ${ len() } ) => {
+   |        ^^^^^^^^^
 
 note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
-  --> $DIR/syntax-errors.rs:88:8
+  --> $DIR/syntax-errors.rs:92:8
    |
-LL |     ( ${ length() } ) => {
-   |        ^^^^^^^^^^^^
+LL |     ( ${ len() } ) => {
+   |        ^^^^^^^^^
 
 error: expected one of: `*`, `+`, or `?`
-  --> $DIR/syntax-errors.rs:88:8
+  --> $DIR/syntax-errors.rs:92:8
    |
-LL |     ( ${ length() } ) => {
-   |        ^^^^^^^^^^^^
+LL |     ( ${ len() } ) => {
+   |        ^^^^^^^^^
 
 error: meta-variables within meta-variable expressions must be referenced using a dollar sign
-  --> $DIR/syntax-errors.rs:95:33
+  --> $DIR/syntax-errors.rs:99:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ ignore() } };
    |                                 ^^^^^^
 
 error: only unsuffixes integer literals are supported in meta-variable expressions
-  --> $DIR/syntax-errors.rs:101:33
+  --> $DIR/syntax-errors.rs:105:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ index(1u32) } };
    |                                 ^^^^^
 
 error: meta-variable expression parameter must be wrapped in parentheses
-  --> $DIR/syntax-errors.rs:107:33
+  --> $DIR/syntax-errors.rs:111:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ count{i} } };
    |                                 ^^^^^
 
-error: expected identifier
-  --> $DIR/syntax-errors.rs:113:31
-   |
-LL |     ( $( $i:ident ),* ) => { ${ {} } };
-   |                               ^^^^^^
-
 error: meta-variables within meta-variable expressions must be referenced using a dollar sign
-  --> $DIR/syntax-errors.rs:120:11
+  --> $DIR/syntax-errors.rs:125:11
    |
 LL |         ${count(foo)}
    |           ^^^^^
 
 error: meta-variables within meta-variable expressions must be referenced using a dollar sign
-  --> $DIR/syntax-errors.rs:128:11
+  --> $DIR/syntax-errors.rs:133:11
    |
 LL |         ${ignore(bar)}
    |           ^^^^^^
 
 error: unrecognized meta-variable expression
-  --> $DIR/syntax-errors.rs:135:33
+  --> $DIR/syntax-errors.rs:140:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
-   |                                 ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and length
+   |                                 ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and len
+
+error: expected identifier
+  --> $DIR/syntax-errors.rs:118:31
+   |
+LL |     ( $( $i:ident ),* ) => { ${ {} } };
+   |                               ^^^^^^
 
 error: `count` can not be placed inside the inner-most repetition
   --> $DIR/syntax-errors.rs:12:24
@@ -209,13 +209,13 @@ LL |     ( $i:ident ) => { ${ count($i) } };
    |                        ^^^^^^^^^^^^^
 
 error: variable 'i' is still repeating at this depth
-  --> $DIR/syntax-errors.rs:34:36
+  --> $DIR/syntax-errors.rs:37:36
    |
 LL |     ( $( $i:ident ),* ) => { count($i) };
    |                                    ^^
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:53:9
+  --> $DIR/syntax-errors.rs:57:9
    |
 LL |         ${count() a b c}
    |         ^ expected expression
@@ -226,7 +226,7 @@ LL |     extra_garbage_after_metavar!(a);
    = note: this error originates in the macro `extra_garbage_after_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:82:30
+  --> $DIR/syntax-errors.rs:86:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ index(IDX) } };
    |                              ^ expected expression
@@ -237,7 +237,7 @@ LL |     metavar_depth_is_not_literal!(a);
    = note: this error originates in the macro `metavar_depth_is_not_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:95:30
+  --> $DIR/syntax-errors.rs:99:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ ignore() } };
    |                              ^ expected expression
@@ -248,7 +248,7 @@ LL |     metavar_token_without_ident!(a);
    = note: this error originates in the macro `metavar_token_without_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:101:30
+  --> $DIR/syntax-errors.rs:105:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ index(1u32) } };
    |                              ^ expected expression
@@ -259,7 +259,7 @@ LL |     metavar_with_literal_suffix!(a);
    = note: this error originates in the macro `metavar_with_literal_suffix` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:107:30
+  --> $DIR/syntax-errors.rs:111:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ count{i} } };
    |                              ^ expected expression
@@ -270,7 +270,7 @@ LL |     metavar_without_parens!(a);
    = note: this error originates in the macro `metavar_without_parens` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:113:30
+  --> $DIR/syntax-errors.rs:118:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ {} } };
    |                              ^ expected expression
@@ -281,7 +281,7 @@ LL |     open_brackets_without_tokens!(a);
    = note: this error originates in the macro `open_brackets_without_tokens` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:120:9
+  --> $DIR/syntax-errors.rs:125:9
    |
 LL |         ${count(foo)}
    |         ^ expected expression
@@ -292,7 +292,7 @@ LL |     unknown_count_ident!(a);
    = note: this error originates in the macro `unknown_count_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:128:9
+  --> $DIR/syntax-errors.rs:133:9
    |
 LL |         ${ignore(bar)}
    |         ^ expected expression
@@ -303,7 +303,7 @@ LL |     unknown_ignore_ident!(a);
    = note: this error originates in the macro `unknown_ignore_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected expression, found `$`
-  --> $DIR/syntax-errors.rs:135:30
+  --> $DIR/syntax-errors.rs:140:30
    |
 LL |     ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
    |                              ^ expected expression
@@ -314,7 +314,7 @@ LL |     unknown_metavar!(a);
    = note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `i` in this scope
-  --> $DIR/syntax-errors.rs:22:36
+  --> $DIR/syntax-errors.rs:23:36
    |
 LL |     ( $( $i:ident ),* ) => { count(i) };
    |                                    ^ not found in this scope
@@ -325,7 +325,7 @@ LL |     no_curly__no_rhs_dollar__round!(a, b, c);
    = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `i` in this scope
-  --> $DIR/syntax-errors.rs:28:29
+  --> $DIR/syntax-errors.rs:30:29
    |
 LL |     ( $i:ident ) => { count(i) };
    |                             ^ not found in this scope
@@ -336,13 +336,13 @@ LL |     no_curly__no_rhs_dollar__no_round!(a);
    = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `a` in this scope
-  --> $DIR/syntax-errors.rs:147:37
+  --> $DIR/syntax-errors.rs:152:37
    |
 LL |     no_curly__rhs_dollar__no_round!(a);
    |                                     ^ not found in this scope
 
 error[E0425]: cannot find function `count` in this scope
-  --> $DIR/syntax-errors.rs:22:30
+  --> $DIR/syntax-errors.rs:23:30
    |
 LL |     ( $( $i:ident ),* ) => { count(i) };
    |                              ^^^^^ not found in this scope
@@ -353,7 +353,7 @@ LL |     no_curly__no_rhs_dollar__round!(a, b, c);
    = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find function `count` in this scope
-  --> $DIR/syntax-errors.rs:28:23
+  --> $DIR/syntax-errors.rs:30:23
    |
 LL |     ( $i:ident ) => { count(i) };
    |                       ^^^^^ not found in this scope
@@ -364,7 +364,7 @@ LL |     no_curly__no_rhs_dollar__no_round!(a);
    = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find function `count` in this scope
-  --> $DIR/syntax-errors.rs:39:23
+  --> $DIR/syntax-errors.rs:43:23
    |
 LL |     ( $i:ident ) => { count($i) };
    |                       ^^^^^ not found in this scope
diff --git a/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.rs b/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.rs
new file mode 100644
index 00000000000..b6bc450dcc7
--- /dev/null
+++ b/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.rs
@@ -0,0 +1,163 @@
+#![allow(non_snake_case)]
+
+// Ensures that we don't spend an unnecessary amount of compiler time building
+// suggestions for mistyped methods. This used to happen because when we had method
+// lookup failures, we would do subsequent method lookups, and those would themselves
+// do extra work that was unnecessary for the purposes of suggestions.
+// Fixed by #125100.
+
+macro_rules! traits {
+    ($($name:ident),*) => {
+        $(
+            trait $name {
+                fn $name(&self);
+            }
+        )*
+    }
+}
+
+traits!(
+    A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20,
+    A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39,
+    A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58,
+    A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75, A76, A77,
+    A78, A79, A80, A81, A82, A83, A84, A85, A86, A87, A88, A89, A90, A91, A92, A93, A94, A95, A96,
+    A97, A98, A99, A100, A101, A102, A103, A104, A105, A106, A107, A108, A109, A110, A111, A112,
+    A113, A114, A115, A116, A117, A118, A119, A120, A121, A122, A123, A124, A125, A126, A127, A128,
+    A129, A130, A131, A132, A133, A134, A135, A136, A137, A138, A139, A140, A141, A142, A143, A144,
+    A145, A146, A147, A148, A149, A150, A151, A152, A153, A154, A155, A156, A157, A158, A159, A160,
+    A161, A162, A163, A164, A165, A166, A167, A168, A169, A170, A171, A172, A173, A174, A175, A176,
+    A177, A178, A179, A180, A181, A182, A183, A184, A185, A186, A187, A188, A189, A190, A191, A192,
+    A193, A194, A195, A196, A197, A198, A199, A200, A201, A202, A203, A204, A205, A206, A207, A208,
+    A209, A210, A211, A212, A213, A214, A215, A216, A217, A218, A219, A220, A221, A222, A223, A224,
+    A225, A226, A227, A228, A229, A230, A231, A232, A233, A234, A235, A236, A237, A238, A239, A240,
+    A241, A242, A243, A244, A245, A246, A247, A248, A249, A250, A251, A252, A253, A254, A255, A256,
+    A257, A258, A259, A260, A261, A262, A263, A264, A265, A266, A267, A268, A269, A270, A271, A272,
+    A273, A274, A275, A276, A277, A278, A279, A280, A281, A282, A283, A284, A285, A286, A287, A288,
+    A289, A290, A291, A292, A293, A294, A295, A296, A297, A298, A299, A300, A301, A302, A303, A304,
+    A305, A306, A307, A308, A309, A310, A311, A312, A313, A314, A315, A316, A317, A318, A319, A320,
+    A321, A322, A323, A324, A325, A326, A327, A328, A329, A330, A331, A332, A333, A334, A335, A336,
+    A337, A338, A339, A340, A341, A342, A343, A344, A345, A346, A347, A348, A349, A350, A351, A352,
+    A353, A354, A355, A356, A357, A358, A359, A360, A361, A362, A363, A364, A365, A366, A367, A368,
+    A369, A370, A371, A372, A373, A374, A375, A376, A377, A378, A379, A380, A381, A382, A383, A384,
+    A385, A386, A387, A388, A389, A390, A391, A392, A393, A394, A395, A396, A397, A398, A399, A400,
+    A401, A402, A403, A404, A405, A406, A407, A408, A409, A410, A411, A412, A413, A414, A415, A416,
+    A417, A418, A419, A420, A421, A422, A423, A424, A425, A426, A427, A428, A429, A430, A431, A432,
+    A433, A434, A435, A436, A437, A438, A439, A440, A441, A442, A443, A444, A445, A446, A447, A448,
+    A449, A450, A451, A452, A453, A454, A455, A456, A457, A458, A459, A460, A461, A462, A463, A464,
+    A465, A466, A467, A468, A469, A470, A471, A472, A473, A474, A475, A476, A477, A478, A479, A480,
+    A481, A482, A483, A484, A485, A486, A487, A488, A489, A490, A491, A492, A493, A494, A495, A496,
+    A497, A498, A499, A500, A501, A502, A503, A504, A505, A506, A507, A508, A509, A510, A511, A512,
+    A513, A514, A515, A516, A517, A518, A519, A520, A521, A522, A523, A524, A525, A526, A527, A528,
+    A529, A530, A531, A532, A533, A534, A535, A536, A537, A538, A539, A540, A541, A542, A543, A544,
+    A545, A546, A547, A548, A549, A550, A551, A552, A553, A554, A555, A556, A557, A558, A559, A560,
+    A561, A562, A563, A564, A565, A566, A567, A568, A569, A570, A571, A572, A573, A574, A575, A576,
+    A577, A578, A579, A580, A581, A582, A583, A584, A585, A586, A587, A588, A589, A590, A591, A592,
+    A593, A594, A595, A596, A597, A598, A599, A600, A601, A602, A603, A604, A605, A606, A607, A608,
+    A609, A610, A611, A612, A613, A614, A615, A616, A617, A618, A619, A620, A621, A622, A623, A624,
+    A625, A626, A627, A628, A629, A630, A631, A632, A633, A634, A635, A636, A637, A638, A639, A640,
+    A641, A642, A643, A644, A645, A646, A647, A648, A649, A650, A651, A652, A653, A654, A655, A656,
+    A657, A658, A659, A660, A661, A662, A663, A664, A665, A666, A667, A668, A669, A670, A671, A672,
+    A673, A674, A675, A676, A677, A678, A679, A680, A681, A682, A683, A684, A685, A686, A687, A688,
+    A689, A690, A691, A692, A693, A694, A695, A696, A697, A698, A699, A700, A701, A702, A703, A704,
+    A705, A706, A707, A708, A709, A710, A711, A712, A713, A714, A715, A716, A717, A718, A719, A720,
+    A721, A722, A723, A724, A725, A726, A727, A728, A729, A730, A731, A732, A733, A734, A735, A736,
+    A737, A738, A739, A740, A741, A742, A743, A744, A745, A746, A747, A748, A749, A750, A751, A752,
+    A753, A754, A755, A756, A757, A758, A759, A760, A761, A762, A763, A764, A765, A766, A767, A768,
+    A769, A770, A771, A772, A773, A774, A775, A776, A777, A778, A779, A780, A781, A782, A783, A784,
+    A785, A786, A787, A788, A789, A790, A791, A792, A793, A794, A795, A796, A797, A798, A799, A800,
+    A801, A802, A803, A804, A805, A806, A807, A808, A809, A810, A811, A812, A813, A814, A815, A816,
+    A817, A818, A819, A820, A821, A822, A823, A824, A825, A826, A827, A828, A829, A830, A831, A832,
+    A833, A834, A835, A836, A837, A838, A839, A840, A841, A842, A843, A844, A845, A846, A847, A848,
+    A849, A850, A851, A852, A853, A854, A855, A856, A857, A858, A859, A860, A861, A862, A863, A864,
+    A865, A866, A867, A868, A869, A870, A871, A872, A873, A874, A875, A876, A877, A878, A879, A880,
+    A881, A882, A883, A884, A885, A886, A887, A888, A889, A890, A891, A892, A893, A894, A895, A896,
+    A897, A898, A899, A900, A901, A902, A903, A904, A905, A906, A907, A908, A909, A910, A911, A912,
+    A913, A914, A915, A916, A917, A918, A919, A920, A921, A922, A923, A924, A925, A926, A927, A928,
+    A929, A930, A931, A932, A933, A934, A935, A936, A937, A938, A939, A940, A941, A942, A943, A944,
+    A945, A946, A947, A948, A949, A950, A951, A952, A953, A954, A955, A956, A957, A958, A959, A960,
+    A961, A962, A963, A964, A965, A966, A967, A968, A969, A970, A971, A972, A973, A974, A975, A976,
+    A977, A978, A979, A980, A981, A982, A983, A984, A985, A986, A987, A988, A989, A990, A991, A992,
+    A993, A994, A995, A996, A997, A998, A999
+);
+
+#[derive(Default)]
+struct M0 {
+    m1: M1,
+    m2: M1,
+    m3: M1,
+    m4: M1,
+    m5: M1,
+    m6: M1,
+    m7: M1,
+    m8: M1,
+    m9: M1,
+    m10: M1,
+    m11: M1,
+    m12: M1,
+    m13: M1,
+    m14: M1,
+    m15: M1,
+}
+
+#[derive(Default)]
+struct M1 {
+    m1: M2,
+    m2: M2,
+    m3: M2,
+    m4: M2,
+    m5: M2,
+    m6: M2,
+    m7: M2,
+    m8: M2,
+    m9: M2,
+    m10: M2,
+    m11: M2,
+    m12: M2,
+    m13: M2,
+    m14: M2,
+    m15: M2,
+}
+
+#[derive(Default)]
+struct M2 {
+    m1: M3,
+    m2: M3,
+    m3: M3,
+    m4: M3,
+    m5: M3,
+    m6: M3,
+    m7: M3,
+    m8: M3,
+    m9: M3,
+    m10: M3,
+    m11: M3,
+    m12: M3,
+    m13: M3,
+    m14: M3,
+    m15: M3,
+}
+
+#[derive(Default)]
+struct M3 {}
+
+fn main() {
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+    M0::default().Au();
+    //~^ ERROR no method named `Au` found for struct `M0` in the current scope
+}
diff --git a/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.stderr b/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.stderr
new file mode 100644
index 00000000000..f5c01ef8fe0
--- /dev/null
+++ b/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.stderr
@@ -0,0 +1,84 @@
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:145:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:147:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:149:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:151:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:153:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:155:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:157:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:159:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error[E0599]: no method named `Au` found for struct `M0` in the current scope
+  --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:161:19
+   |
+LL | struct M0 {
+   | --------- method `Au` not found for this struct
+...
+LL |     M0::default().Au();
+   |                   ^^ method not found in `M0`
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/pattern/skipped-ref-pats-issue-125058.rs b/tests/ui/pattern/skipped-ref-pats-issue-125058.rs
new file mode 100644
index 00000000000..b733e5fda0a
--- /dev/null
+++ b/tests/ui/pattern/skipped-ref-pats-issue-125058.rs
@@ -0,0 +1,18 @@
+//@ run-pass
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+
+#![allow(incomplete_features)]
+#![feature(ref_pat_eat_one_layer_2024)]
+
+struct Foo;
+//~^ WARN struct `Foo` is never constructed
+
+fn main() {
+    || {
+        //~^ WARN unused closure that must be used
+        if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+            let _: u32 = x;
+        }
+    };
+}
diff --git a/tests/ui/pattern/skipped-ref-pats-issue-125058.stderr b/tests/ui/pattern/skipped-ref-pats-issue-125058.stderr
new file mode 100644
index 00000000000..cee1cc673c7
--- /dev/null
+++ b/tests/ui/pattern/skipped-ref-pats-issue-125058.stderr
@@ -0,0 +1,24 @@
+warning: struct `Foo` is never constructed
+  --> $DIR/skipped-ref-pats-issue-125058.rs:8:8
+   |
+LL | struct Foo;
+   |        ^^^
+   |
+   = note: `#[warn(dead_code)]` on by default
+
+warning: unused closure that must be used
+  --> $DIR/skipped-ref-pats-issue-125058.rs:12:5
+   |
+LL | /     || {
+LL | |
+LL | |         if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
+LL | |             let _: u32 = x;
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+   = note: closures are lazy and do nothing unless called
+   = note: `#[warn(unused_must_use)]` on by default
+
+warning: 2 warnings emitted
+
diff --git a/triagebot.toml b/triagebot.toml
index ddab6701786..80820d2f297 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -9,11 +9,14 @@ allow-unauthenticated = [
     "E-*",
     "F-*",
     "I-*",
+    "L-*",
     "NLL-*",
     "O-*",
+    "PG-*",
     "S-*",
     "T-*",
     "WG-*",
+    "-Z*",
     "beta-nominated",
     "const-hack",
     "llvm-*",