about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-14 05:53:49 +0000
committerbors <bors@rust-lang.org>2024-01-14 05:53:49 +0000
commit0c8e1e6f444d28742aff75f8789df69007ca589a (patch)
tree723640d4a742437fa21727738102037a96bcd605 /compiler
parent12c0f090af379f2a6334cc35100cb6ee3f13f0ef (diff)
parent6a234be984fc9df425a7e157c05f4b2739b18f55 (diff)
downloadrust-0c8e1e6f444d28742aff75f8789df69007ca589a.tar.gz
rust-0c8e1e6f444d28742aff75f8789df69007ca589a.zip
Auto merge of #3267 - rust-lang:rustup-2024-01-14, r=saethlin
Automatic Rustup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs25
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs16
-rw-r--r--compiler/rustc_ast/src/visit.rs18
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs13
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs348
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs41
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs5
-rw-r--r--compiler/rustc_ast_passes/messages.ftl3
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs38
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs17
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs31
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs31
-rw-r--r--compiler/rustc_attr/src/builtin.rs24
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/assert_module_sources.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs6
-rw-r--r--compiler/rustc_errors/src/lib.rs64
-rw-r--r--compiler/rustc_expand/src/base.rs12
-rw-r--r--compiler/rustc_expand/src/config.rs16
-rw-r--r--compiler/rustc_expand/src/expand.rs13
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs40
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs31
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs8
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs132
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs12
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs4
-rw-r--r--compiler/rustc_infer/src/infer/at.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs4
-rw-r--r--compiler/rustc_interface/src/interface.rs9
-rw-r--r--compiler/rustc_lint/src/builtin.rs5
-rw-r--r--compiler/rustc_lint/src/levels.rs4
-rw-r--r--compiler/rustc_lint/src/lints.rs6
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs31
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs3
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs3
-rw-r--r--compiler/rustc_middle/src/traits/select.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_parse/src/parser/item.rs36
-rw-r--r--compiler/rustc_passes/src/check_attr.rs4
-rw-r--r--compiler/rustc_passes/src/check_const.rs2
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs15
-rw-r--r--compiler/rustc_passes/src/entry.rs2
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs6
-rw-r--r--compiler/rustc_passes/src/lang_items.rs43
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs38
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs17
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs3
-rw-r--r--compiler/rustc_resolve/src/ident.rs44
-rw-r--r--compiler/rustc_resolve/src/imports.rs3
-rw-r--r--compiler/rustc_resolve/src/late.rs109
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs12
-rw-r--r--compiler/rustc_resolve/src/lib.rs20
-rw-r--r--compiler/rustc_resolve/src/macros.rs10
-rw-r--r--compiler/rustc_session/messages.ftl3
-rw-r--r--compiler/rustc_session/src/config/sigpipe.rs4
-rw-r--r--compiler/rustc_session/src/errors.rs21
-rw-r--r--compiler/rustc_session/src/parse.rs31
-rw-r--r--compiler/rustc_session/src/session.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/abi/mod.rs3
-rw-r--r--compiler/rustc_target/src/spec/base/illumos.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs43
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs8
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs6
90 files changed, 1210 insertions, 442 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index e1e4e5fc567..21077c312bd 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2873,6 +2873,7 @@ impl Item {
             | ItemKind::ForeignMod(_)
             | ItemKind::GlobalAsm(_)
             | ItemKind::MacCall(_)
+            | ItemKind::Delegation(_)
             | ItemKind::MacroDef(_) => None,
             ItemKind::Static(_) => None,
             ItemKind::Const(i) => Some(&i.generics),
@@ -3020,6 +3021,15 @@ pub struct Fn {
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
+pub struct Delegation {
+    /// Path resolution id.
+    pub id: NodeId,
+    pub qself: Option<P<QSelf>>,
+    pub path: Path,
+    pub body: Option<P<Block>>,
+}
+
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct StaticItem {
     pub ty: P<Ty>,
     pub mutability: Mutability,
@@ -3104,6 +3114,11 @@ pub enum ItemKind {
 
     /// A macro definition.
     MacroDef(MacroDef),
+
+    /// A delegation item (`reuse`).
+    ///
+    /// E.g. `reuse <Type as Trait>::name { target_expr_template }`.
+    Delegation(Box<Delegation>),
 }
 
 impl ItemKind {
@@ -3111,7 +3126,8 @@ impl ItemKind {
         use ItemKind::*;
         match self {
             Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
-            | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a",
+            | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
+            | Delegation(..) => "a",
             ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
         }
     }
@@ -3135,6 +3151,7 @@ impl ItemKind {
             ItemKind::MacCall(..) => "item macro invocation",
             ItemKind::MacroDef(..) => "macro definition",
             ItemKind::Impl { .. } => "implementation",
+            ItemKind::Delegation(..) => "delegated function",
         }
     }
 
@@ -3176,6 +3193,8 @@ pub enum AssocItemKind {
     Type(Box<TyAlias>),
     /// A macro expanding to associated items.
     MacCall(P<MacCall>),
+    /// An associated delegation item.
+    Delegation(Box<Delegation>),
 }
 
 impl AssocItemKind {
@@ -3184,7 +3203,7 @@ impl AssocItemKind {
             Self::Const(box ConstItem { defaultness, .. })
             | Self::Fn(box Fn { defaultness, .. })
             | Self::Type(box TyAlias { defaultness, .. }) => defaultness,
-            Self::MacCall(..) => Defaultness::Final,
+            Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final,
         }
     }
 }
@@ -3196,6 +3215,7 @@ impl From<AssocItemKind> for ItemKind {
             AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
             AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
             AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
+            AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
         }
     }
 }
@@ -3209,6 +3229,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
             ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
             ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
             ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
+            ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
             _ => return Err(item_kind),
         })
     }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 82f28143630..450555d0cb5 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1117,6 +1117,14 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         }
         ItemKind::MacCall(m) => vis.visit_mac_call(m),
         ItemKind::MacroDef(def) => vis.visit_macro_def(def),
+        ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+            vis.visit_id(id);
+            vis.visit_qself(qself);
+            vis.visit_path(path);
+            if let Some(body) = body {
+                vis.visit_block(body);
+            }
+        }
     }
 }
 
@@ -1155,6 +1163,14 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
             visit_opt(ty, |ty| visitor.visit_ty(ty));
         }
         AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
+        AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+            visitor.visit_id(id);
+            visitor.visit_qself(qself);
+            visitor.visit_path(path);
+            if let Some(body) = body {
+                visitor.visit_block(body);
+            }
+        }
     }
     visitor.visit_span(span);
     visit_lazy_tts(tokens, visitor);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 45261ca48fc..3617df931e2 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -375,6 +375,15 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
         }
         ItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
         ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id),
+        ItemKind::Delegation(box Delegation { id: _, qself, path, body }) => {
+            if let Some(qself) = qself {
+                visitor.visit_ty(&qself.ty);
+            }
+            walk_path(visitor, path);
+            if let Some(body) = body {
+                visitor.visit_block(body);
+            }
+        }
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
 }
@@ -704,6 +713,15 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
         AssocItemKind::MacCall(mac) => {
             visitor.visit_mac_call(mac);
         }
+        AssocItemKind::Delegation(box Delegation { id: _, qself, path, body }) => {
+            if let Some(qself) = qself {
+                visitor.visit_ty(&qself.ty);
+            }
+            walk_path(visitor, path);
+            if let Some(body) = body {
+                visitor.visit_block(body);
+            }
+        }
     }
 }
 
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index a5986f2bba5..3742cf9d881 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -48,7 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             );
             if !is_stable && !self.tcx.features().asm_experimental_arch {
                 feature_err(
-                    &self.tcx.sess.parse_sess,
+                    &self.tcx.sess,
                     sym::asm_experimental_arch,
                     sp,
                     "inline assembly is not stable yet on this architecture",
@@ -63,13 +63,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             self.dcx().emit_err(AttSyntaxOnlyX86 { span: sp });
         }
         if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind {
-            feature_err(
-                &self.tcx.sess.parse_sess,
-                sym::asm_unwind,
-                sp,
-                "the `may_unwind` option is unstable",
-            )
-            .emit();
+            feature_err(&self.tcx.sess, sym::asm_unwind, sp, "the `may_unwind` option is unstable")
+                .emit();
         }
 
         let mut clobber_abis = FxIndexMap::default();
@@ -183,7 +178,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     InlineAsmOperand::Const { anon_const } => {
                         if !self.tcx.features().asm_const {
                             feature_err(
-                                &sess.parse_sess,
+                                sess,
                                 sym::asm_const,
                                 *op_sp,
                                 "const operands for inline assembly are unstable",
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
new file mode 100644
index 00000000000..6ccf39b0cb1
--- /dev/null
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -0,0 +1,348 @@
+//! This module implements expansion of delegation items with early resolved paths.
+//! It includes a delegation to a free functions:
+//!
+//! ```ignore (illustrative)
+//! reuse module::name { target_expr_template }
+//! ```
+//!
+//! And delegation to a trait methods:
+//!
+//! ```ignore (illustrative)
+//! reuse <Type as Trait>::name { target_expr_template }
+//! ```
+//!
+//! After expansion for both cases we get:
+//!
+//! ```ignore (illustrative)
+//! fn name(
+//!     arg0: InferDelegation(sig_id, Input(0)),
+//!     arg1: InferDelegation(sig_id, Input(1)),
+//!     ...,
+//!     argN: InferDelegation(sig_id, Input(N)),
+//! ) -> InferDelegation(sig_id, Output) {
+//!     callee_path(target_expr_template(arg0), arg1, ..., argN)
+//! }
+//! ```
+//!
+//! Where `callee_path` is a path in delegation item e.g. `<Type as Trait>::name`.
+//! `sig_id` is a id of item from which the signature is inherited. It may be a delegation
+//! item id (`item_id`) in case of impl trait or path resolution id (`path_id`) otherwise.
+//!
+//! Since we do not have a proper way to obtain function type information by path resolution
+//! in AST, we mark each function parameter type as `InferDelegation` and inherit it in `AstConv`.
+//!
+//! Similarly generics, predicates and header are set to the "default" values.
+//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
+//! also be emitted in `AstConv`.
+
+use crate::{ImplTraitPosition, ResolverAstLoweringExt};
+
+use super::{ImplTraitContext, LoweringContext, ParamMode};
+
+use ast::visit::Visitor;
+use hir::def::{DefKind, PartialRes, Res};
+use hir::{BodyId, HirId};
+use rustc_ast as ast;
+use rustc_ast::*;
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_middle::span_bug;
+use rustc_middle::ty::ResolverAstLowering;
+use rustc_span::{symbol::Ident, Span};
+use rustc_target::spec::abi;
+use std::iter;
+
+pub(crate) struct DelegationResults<'hir> {
+    pub body_id: hir::BodyId,
+    pub sig: hir::FnSig<'hir>,
+    pub generics: &'hir hir::Generics<'hir>,
+}
+
+impl<'hir> LoweringContext<'_, 'hir> {
+    pub(crate) fn delegation_has_self(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool {
+        let sig_id = self.get_delegation_sig_id(item_id, path_id, span);
+        let Ok(sig_id) = sig_id else {
+            return false;
+        };
+        if let Some(local_sig_id) = sig_id.as_local() {
+            self.resolver.has_self.contains(&local_sig_id)
+        } else {
+            match self.tcx.def_kind(sig_id) {
+                DefKind::Fn => false,
+                DefKind::AssocFn => self.tcx.associated_item(sig_id).fn_has_self_parameter,
+                _ => span_bug!(span, "unexpected DefKind for delegation item"),
+            }
+        }
+    }
+
+    pub(crate) fn lower_delegation(
+        &mut self,
+        delegation: &Delegation,
+        item_id: NodeId,
+    ) -> DelegationResults<'hir> {
+        let span = delegation.path.segments.last().unwrap().ident.span;
+        let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
+        match sig_id {
+            Ok(sig_id) => {
+                let decl = self.lower_delegation_decl(sig_id, span);
+                let sig = self.lower_delegation_sig(span, decl);
+                let body_id = self.lower_delegation_body(sig.decl, delegation);
+
+                let generics = self.lower_delegation_generics(span);
+                DelegationResults { body_id, sig, generics }
+            }
+            Err(err) => self.generate_delegation_error(err, span),
+        }
+    }
+
+    fn get_delegation_sig_id(
+        &self,
+        item_id: NodeId,
+        path_id: NodeId,
+        span: Span,
+    ) -> Result<DefId, ErrorGuaranteed> {
+        let sig_id = if self.is_in_trait_impl { item_id } else { path_id };
+        let sig_id = self
+            .resolver
+            .get_partial_res(sig_id)
+            .map(|r| r.expect_full_res().opt_def_id())
+            .unwrap_or(None);
+
+        sig_id.ok_or_else(|| {
+            self.tcx
+                .dcx()
+                .span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item")
+        })
+    }
+
+    fn lower_delegation_generics(&mut self, span: Span) -> &'hir hir::Generics<'hir> {
+        self.arena.alloc(hir::Generics {
+            params: &[],
+            predicates: &[],
+            has_where_clause_predicates: false,
+            where_clause_span: span,
+            span: span,
+        })
+    }
+
+    fn lower_delegation_decl(
+        &mut self,
+        sig_id: DefId,
+        param_span: Span,
+    ) -> &'hir hir::FnDecl<'hir> {
+        let args_count = if let Some(local_sig_id) = sig_id.as_local() {
+            // Map may be filled incorrectly due to recursive delegation.
+            // Error will be emmited later in astconv.
+            self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
+        } else {
+            self.tcx.fn_arg_names(sig_id).len()
+        };
+        let inputs = self.arena.alloc_from_iter((0..args_count).into_iter().map(|arg| hir::Ty {
+            hir_id: self.next_id(),
+            kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
+            span: self.lower_span(param_span),
+        }));
+
+        let output = self.arena.alloc(hir::Ty {
+            hir_id: self.next_id(),
+            kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
+            span: self.lower_span(param_span),
+        });
+
+        self.arena.alloc(hir::FnDecl {
+            inputs,
+            output: hir::FnRetTy::Return(output),
+            c_variadic: false,
+            lifetime_elision_allowed: true,
+            implicit_self: hir::ImplicitSelfKind::None,
+        })
+    }
+
+    fn lower_delegation_sig(
+        &mut self,
+        span: Span,
+        decl: &'hir hir::FnDecl<'hir>,
+    ) -> hir::FnSig<'hir> {
+        hir::FnSig {
+            decl,
+            header: hir::FnHeader {
+                unsafety: hir::Unsafety::Normal,
+                constness: hir::Constness::NotConst,
+                asyncness: hir::IsAsync::NotAsync,
+                abi: abi::Abi::Rust,
+            },
+            span: self.lower_span(span),
+        }
+    }
+
+    fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
+        let pat_node_id = self.next_node_id();
+        let pat_id = self.lower_node_id(pat_node_id);
+        let pat = self.arena.alloc(hir::Pat {
+            hir_id: pat_id,
+            kind: hir::PatKind::Binding(hir::BindingAnnotation::NONE, pat_id, Ident::empty(), None),
+            span: ty.span,
+            default_binding_modes: false,
+        });
+
+        (hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
+    }
+
+    fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
+        let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
+            ident: Ident::empty(),
+            hir_id: self.next_id(),
+            res: Res::Local(param_id),
+            args: None,
+            infer_args: false,
+        }));
+
+        let path =
+            self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
+
+        hir::Expr {
+            hir_id: self.next_id(),
+            kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
+            span: ty.span,
+        }
+    }
+
+    fn lower_delegation_body(
+        &mut self,
+        decl: &'hir hir::FnDecl<'hir>,
+        delegation: &Delegation,
+    ) -> BodyId {
+        let path = self.lower_qpath(
+            delegation.id,
+            &delegation.qself,
+            &delegation.path,
+            ParamMode::Optional,
+            &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+            None,
+        );
+        let block = delegation.body.as_deref();
+
+        self.lower_body(|this| {
+            let mut parameters: Vec<hir::Param<'_>> = Vec::new();
+            let mut args: Vec<hir::Expr<'hir>> = Vec::new();
+
+            for (idx, param_ty) in decl.inputs.iter().enumerate() {
+                let (param, pat_node_id) = this.generate_param(param_ty);
+                parameters.push(param);
+
+                let arg = if let Some(block) = block
+                    && idx == 0
+                {
+                    let mut self_resolver = SelfResolver {
+                        resolver: this.resolver,
+                        path_id: delegation.id,
+                        self_param_id: pat_node_id,
+                    };
+                    self_resolver.visit_block(block);
+                    let block = this.lower_block(block, false);
+                    hir::Expr {
+                        hir_id: this.next_id(),
+                        kind: hir::ExprKind::Block(block, None),
+                        span: block.span,
+                    }
+                } else {
+                    let pat_hir_id = this.lower_node_id(pat_node_id);
+                    this.generate_arg(param_ty, pat_hir_id)
+                };
+                args.push(arg);
+            }
+
+            let args = self.arena.alloc_from_iter(args);
+            let final_expr = this.generate_call(path, args);
+            (this.arena.alloc_from_iter(parameters), final_expr)
+        })
+    }
+
+    fn generate_call(
+        &mut self,
+        path: hir::QPath<'hir>,
+        args: &'hir [hir::Expr<'hir>],
+    ) -> hir::Expr<'hir> {
+        let callee = self.arena.alloc(hir::Expr {
+            hir_id: self.next_id(),
+            kind: hir::ExprKind::Path(path),
+            span: path.span(),
+        });
+
+        let expr = self.arena.alloc(hir::Expr {
+            hir_id: self.next_id(),
+            kind: hir::ExprKind::Call(callee, args),
+            span: path.span(),
+        });
+
+        let block = self.arena.alloc(hir::Block {
+            stmts: &[],
+            expr: Some(expr),
+            hir_id: self.next_id(),
+            rules: hir::BlockCheckMode::DefaultBlock,
+            span: path.span(),
+            targeted_by_break: false,
+        });
+
+        hir::Expr {
+            hir_id: self.next_id(),
+            kind: hir::ExprKind::Block(block, None),
+            span: path.span(),
+        }
+    }
+
+    fn generate_delegation_error(
+        &mut self,
+        err: ErrorGuaranteed,
+        span: Span,
+    ) -> DelegationResults<'hir> {
+        let generics = self.lower_delegation_generics(span);
+
+        let decl = self.arena.alloc(hir::FnDecl {
+            inputs: &[],
+            output: hir::FnRetTy::DefaultReturn(span),
+            c_variadic: false,
+            lifetime_elision_allowed: true,
+            implicit_self: hir::ImplicitSelfKind::None,
+        });
+
+        let sig = self.lower_delegation_sig(span, decl);
+        let body_id = self.lower_body(|this| {
+            let expr =
+                hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
+            (&[], expr)
+        });
+        DelegationResults { generics, body_id, sig }
+    }
+}
+
+struct SelfResolver<'a> {
+    resolver: &'a mut ResolverAstLowering,
+    path_id: NodeId,
+    self_param_id: NodeId,
+}
+
+impl<'a> SelfResolver<'a> {
+    fn try_replace_id(&mut self, id: NodeId) {
+        if let Some(res) = self.resolver.partial_res_map.get(&id)
+            && let Some(Res::Local(sig_id)) = res.full_res()
+            && sig_id == self.path_id
+        {
+            let new_res = PartialRes::new(Res::Local(self.self_param_id));
+            self.resolver.partial_res_map.insert(id, new_res);
+        }
+    }
+}
+
+impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> {
+    fn visit_path(&mut self, path: &'ast Path, id: NodeId) {
+        self.try_replace_id(id);
+        visit::walk_path(self, path);
+    }
+
+    fn visit_path_segment(&mut self, seg: &'ast PathSegment) {
+        self.try_replace_id(seg.id);
+        visit::walk_path_segment(self, seg);
+    }
+}
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 69704de105c..e0b1a10c82e 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1512,7 +1512,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             Some(hir::CoroutineKind::Coroutine(_)) => {
                 if !self.tcx.features().coroutines {
                     rustc_session::parse::feature_err(
-                        &self.tcx.sess.parse_sess,
+                        &self.tcx.sess,
                         sym::coroutines,
                         span,
                         "yield syntax is experimental",
@@ -1524,7 +1524,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             None => {
                 if !self.tcx.features().coroutines {
                     rustc_session::parse::feature_err(
-                        &self.tcx.sess.parse_sess,
+                        &self.tcx.sess,
                         sym::coroutines,
                         span,
                         "yield syntax is experimental",
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index d8de447e5b4..a3ff02f5f69 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -441,6 +441,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
                 hir::ItemKind::Macro(macro_def, macro_kind)
             }
+            ItemKind::Delegation(box delegation) => {
+                let delegation_results = self.lower_delegation(delegation, id);
+                hir::ItemKind::Fn(
+                    delegation_results.sig,
+                    delegation_results.generics,
+                    delegation_results.body_id,
+                )
+            }
             ItemKind::MacCall(..) => {
                 panic!("`TyMac` should have been expanded by now")
             }
@@ -805,6 +813,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 (generics, kind, ty.is_some())
             }
+            AssocItemKind::Delegation(box delegation) => {
+                let delegation_results = self.lower_delegation(delegation, i.id);
+                let item_kind = hir::TraitItemKind::Fn(
+                    delegation_results.sig,
+                    hir::TraitFn::Provided(delegation_results.body_id),
+                );
+                (delegation_results.generics, item_kind, true)
+            }
             AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
         };
 
@@ -826,6 +842,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::Fn(box Fn { sig, .. }) => {
                 hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
             }
+            AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
+                has_self: self.delegation_has_self(i.id, delegation.id, i.span),
+            },
             AssocItemKind::MacCall(..) => unimplemented!(),
         };
         let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
@@ -908,6 +927,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     },
                 )
             }
+            AssocItemKind::Delegation(box delegation) => {
+                let delegation_results = self.lower_delegation(delegation, i.id);
+                (
+                    delegation_results.generics,
+                    hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
+                )
+            }
             AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
         };
 
@@ -924,6 +950,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
+        let trait_item_def_id = self
+            .resolver
+            .get_partial_res(i.id)
+            .map(|r| r.expect_full_res().opt_def_id())
+            .unwrap_or(None);
+        self.is_in_trait_impl = trait_item_def_id.is_some();
+
         hir::ImplItemRef {
             id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
             ident: self.lower_ident(i.ident),
@@ -934,12 +967,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 AssocItemKind::Fn(box Fn { sig, .. }) => {
                     hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
                 }
+                AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
+                    has_self: self.delegation_has_self(i.id, delegation.id, i.span),
+                },
                 AssocItemKind::MacCall(..) => unimplemented!(),
             },
-            trait_item_def_id: self
-                .resolver
-                .get_partial_res(i.id)
-                .map(|r| r.expect_full_res().def_id()),
+            trait_item_def_id,
         }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index dc23b1dce7b..5387880b6e6 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -77,6 +77,7 @@ macro_rules! arena_vec {
 
 mod asm;
 mod block;
+mod delegation;
 mod errors;
 mod expr;
 mod format;
@@ -1042,7 +1043,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         {
                             add_feature_diagnostics(
                                 &mut err,
-                                &self.tcx.sess.parse_sess,
+                                &self.tcx.sess,
                                 sym::return_type_notation,
                             );
                         }
@@ -2309,7 +2310,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     hir::ArrayLen::Infer(self.lower_node_id(c.id), self.lower_span(c.value.span))
                 } else {
                     feature_err(
-                        &self.tcx.sess.parse_sess,
+                        &self.tcx.sess,
                         sym::generic_arg_infer,
                         c.value.span,
                         "using `_` for array lengths is unstable",
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index a10797626f1..6586ca5d36f 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -232,6 +232,9 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here
     .trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
     .trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds
     .impl = inherent impls cannot have `~const` trait bounds
+    .trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
+    .trait_impl_assoc_ty = associated types in non-const impls cannot have `~const` trait bounds
+    .inherent_assoc_ty = inherent associated types cannot have `~const` trait bounds
     .object = trait objects cannot have `~const` trait bounds
     .item = this item cannot have `~const` trait bounds
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 7f78f687055..9ea5d1ed5fa 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -37,12 +37,17 @@ enum SelfSemantic {
 }
 
 /// What is the context that prevents using `~const`?
+// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
+// almost identical. This gets rid of an abstraction layer which might be considered bad.
 enum DisallowTildeConstContext<'a> {
     TraitObject,
     Fn(FnKind<'a>),
     Trait(Span),
     TraitImpl(Span),
     Impl(Span),
+    TraitAssocTy(Span),
+    TraitImplAssocTy(Span),
+    InherentAssocTy(Span),
     Item,
 }
 
@@ -316,6 +321,7 @@ impl<'a> AstValidator<'a> {
                 constness: Const::No,
                 polarity: ImplPolarity::Positive,
                 trait_ref,
+                ..
             } = parent
         {
             Some(trait_ref.path.span.shrink_to_lo())
@@ -1286,6 +1292,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                             // suggestion for moving such bounds to the assoc const fns if available.
                             errors::TildeConstReason::Impl { span }
                         }
+                        &DisallowTildeConstContext::TraitAssocTy(span) => {
+                            errors::TildeConstReason::TraitAssocTy { span }
+                        }
+                        &DisallowTildeConstContext::TraitImplAssocTy(span) => {
+                            errors::TildeConstReason::TraitImplAssocTy { span }
+                        }
+                        &DisallowTildeConstContext::InherentAssocTy(span) => {
+                            errors::TildeConstReason::InherentAssocTy { span }
+                        }
                         DisallowTildeConstContext::TraitObject => {
                             errors::TildeConstReason::TraitObject
                         }
@@ -1483,13 +1498,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             self.check_item_named(item.ident, "const");
         }
 
+        let parent_is_const =
+            self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some();
+
         match &item.kind {
             AssocItemKind::Fn(box Fn { sig, generics, body, .. })
-                if self
-                    .outer_trait_or_trait_impl
-                    .as_ref()
-                    .and_then(TraitOrTraitImpl::constness)
-                    .is_some()
+                if parent_is_const
                     || ctxt == AssocCtxt::Trait
                     || matches!(sig.header.constness, Const::Yes(_)) =>
             {
@@ -1505,6 +1519,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 );
                 self.visit_fn(kind, item.span, item.id);
             }
+            AssocItemKind::Type(_) => {
+                let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
+                    Some(TraitOrTraitImpl::Trait { .. }) => {
+                        DisallowTildeConstContext::TraitAssocTy(item.span)
+                    }
+                    Some(TraitOrTraitImpl::TraitImpl { .. }) => {
+                        DisallowTildeConstContext::TraitImplAssocTy(item.span)
+                    }
+                    None => DisallowTildeConstContext::InherentAssocTy(item.span),
+                });
+                self.with_tilde_const(disallowed, |this| {
+                    this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
+                })
+            }
             _ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
         }
     }
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index fcf19ce52ec..e2b8e64b115 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -565,6 +565,8 @@ pub struct ConstBoundTraitObject {
     pub span: Span,
 }
 
+// FIXME(effects): Consider making the note/reason the message of the diagnostic.
+// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
 #[derive(Diagnostic)]
 #[diag(ast_passes_tilde_const_disallowed)]
 pub struct TildeConstDisallowed {
@@ -598,6 +600,21 @@ pub enum TildeConstReason {
         #[primary_span]
         span: Span,
     },
+    #[note(ast_passes_trait_assoc_ty)]
+    TraitAssocTy {
+        #[primary_span]
+        span: Span,
+    },
+    #[note(ast_passes_trait_impl_assoc_ty)]
+    TraitImplAssocTy {
+        #[primary_span]
+        span: Span,
+    },
+    #[note(ast_passes_inherent_assoc_ty)]
+    InherentAssocTy {
+        #[primary_span]
+        span: Span,
+    },
     #[note(ast_passes_object)]
     TraitObject,
     #[note(ast_passes_item)]
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 737e81eb6ec..192e458775a 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -17,14 +17,12 @@ use crate::errors;
 macro_rules! gate {
     ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
         if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
-            feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain).emit();
+            feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
         }
     }};
     ($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
         if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
-            feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
-                .with_help($help)
-                .emit();
+            feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit();
         }
     }};
 }
@@ -33,7 +31,7 @@ macro_rules! gate {
 macro_rules! gate_alt {
     ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
         if !$has_feature && !$span.allows_unstable($name) {
-            feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit();
+            feature_err(&$visitor.sess, $name, $span, $explain).emit();
         }
     }};
 }
@@ -45,7 +43,7 @@ macro_rules! gate_multi {
             let spans: Vec<_> =
                 $spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
             if !spans.is_empty() {
-                feature_err(&$visitor.sess.parse_sess, sym::$feature, spans, $explain).emit();
+                feature_err(&$visitor.sess, sym::$feature, spans, $explain).emit();
             }
         }
     }};
@@ -55,7 +53,7 @@ macro_rules! gate_multi {
 macro_rules! gate_legacy {
     ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
         if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
-            feature_warn(&$visitor.sess.parse_sess, sym::$feature, $span, $explain);
+            feature_warn(&$visitor.sess, sym::$feature, $span, $explain);
         }
     }};
 }
@@ -91,14 +89,7 @@ impl<'a> PostExpansionVisitor<'a> {
         match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) {
             Ok(()) => (),
             Err(abi::AbiDisabled::Unstable { feature, explain }) => {
-                feature_err_issue(
-                    &self.sess.parse_sess,
-                    feature,
-                    span,
-                    GateIssue::Language,
-                    explain,
-                )
-                .emit();
+                feature_err_issue(&self.sess, feature, span, GateIssue::Language, explain).emit();
             }
             Err(abi::AbiDisabled::Unrecognized) => {
                 if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
@@ -556,6 +547,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(explicit_tail_calls, "`become` expression is experimental");
     gate_all!(generic_const_items, "generic const items are experimental");
     gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
+    gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
 
     if !visitor.features.never_patterns {
         if let Some(spans) = spans.get(&sym::never_patterns) {
@@ -570,13 +562,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
                 if let Ok(snippet) = sm.span_to_snippet(span)
                     && snippet == "!"
                 {
-                    feature_err(
-                        &sess.parse_sess,
-                        sym::never_patterns,
-                        span,
-                        "`!` patterns are experimental",
-                    )
-                    .emit();
+                    feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
+                        .emit();
                 } else {
                     let suggestion = span.shrink_to_hi();
                     sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion });
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 43561a1c020..584f01e16c2 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -376,6 +376,9 @@ impl<'a> State<'a> {
                     state.print_visibility(&item.vis)
                 });
             }
+            ast::ItemKind::Delegation(box delegation) => {
+                self.print_delegation(delegation, &item.vis, &item.attrs)
+            }
         }
         self.ann.post(self, AnnNode::Item(item))
     }
@@ -554,10 +557,38 @@ impl<'a> State<'a> {
                     self.word(";");
                 }
             }
+            ast::AssocItemKind::Delegation(box delegation) => {
+                self.print_delegation(delegation, vis, &item.attrs)
+            }
         }
         self.ann.post(self, AnnNode::SubItem(id))
     }
 
+    pub(crate) fn print_delegation(
+        &mut self,
+        delegation: &ast::Delegation,
+        vis: &ast::Visibility,
+        attrs: &[ast::Attribute],
+    ) {
+        if delegation.body.is_some() {
+            self.head("");
+        }
+        self.print_visibility(vis);
+        self.word_space("reuse");
+
+        if let Some(qself) = &delegation.qself {
+            self.print_qpath(&delegation.path, qself, false);
+        } else {
+            self.print_path(&delegation.path, false, 0);
+        }
+        if let Some(body) = &delegation.body {
+            self.nbsp();
+            self.print_block_with_attrs(body, attrs);
+        } else {
+            self.word(";");
+        }
+    }
+
     fn print_fn_full(
         &mut self,
         sig: &ast::FnSig,
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index b3f601b7595..6b903be6e5e 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -9,7 +9,7 @@ use rustc_macros::HashStable_Generic;
 use rustc_session::config::ExpectedValues;
 use rustc_session::lint::builtin::UNEXPECTED_CFGS;
 use rustc_session::lint::BuiltinLintDiagnostics;
-use rustc_session::parse::{feature_err, ParseSess};
+use rustc_session::parse::feature_err;
 use rustc_session::{RustcVersion, Session};
 use rustc_span::hygiene::Transparency;
 use rustc_span::{symbol::sym, symbol::Symbol, Span};
@@ -518,15 +518,15 @@ pub struct Condition {
 /// Tests if a cfg-pattern matches the cfg set
 pub fn cfg_matches(
     cfg: &ast::MetaItem,
-    sess: &ParseSess,
+    sess: &Session,
     lint_node_id: NodeId,
     features: Option<&Features>,
 ) -> bool {
     eval_condition(cfg, sess, features, &mut |cfg| {
         try_gate_cfg(cfg.name, cfg.span, sess, features);
-        match sess.check_config.expecteds.get(&cfg.name) {
+        match sess.parse_sess.check_config.expecteds.get(&cfg.name) {
             Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
-                sess.buffer_lint_with_diagnostic(
+                sess.parse_sess.buffer_lint_with_diagnostic(
                     UNEXPECTED_CFGS,
                     cfg.span,
                     lint_node_id,
@@ -541,8 +541,8 @@ pub fn cfg_matches(
                     ),
                 );
             }
-            None if sess.check_config.exhaustive_names => {
-                sess.buffer_lint_with_diagnostic(
+            None if sess.parse_sess.check_config.exhaustive_names => {
+                sess.parse_sess.buffer_lint_with_diagnostic(
                     UNEXPECTED_CFGS,
                     cfg.span,
                     lint_node_id,
@@ -555,18 +555,18 @@ pub fn cfg_matches(
             }
             _ => { /* not unexpected */ }
         }
-        sess.config.contains(&(cfg.name, cfg.value))
+        sess.parse_sess.config.contains(&(cfg.name, cfg.value))
     })
 }
 
-fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) {
+fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
     let gate = find_gated_cfg(|sym| sym == name);
     if let (Some(feats), Some(gated_cfg)) = (features, gate) {
         gate_cfg(gated_cfg, span, sess, feats);
     }
 }
 
-fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) {
+fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
     let (cfg, feature, has_feature) = gated_cfg;
     if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
         let explain = format!("`cfg({cfg})` is experimental and subject to change");
@@ -594,11 +594,11 @@ fn parse_version(s: Symbol) -> Option<RustcVersion> {
 /// evaluate individual items.
 pub fn eval_condition(
     cfg: &ast::MetaItem,
-    sess: &ParseSess,
+    sess: &Session,
     features: Option<&Features>,
     eval: &mut impl FnMut(Condition) -> bool,
 ) -> bool {
-    let dcx = &sess.dcx;
+    let dcx = &sess.parse_sess.dcx;
     match &cfg.kind {
         ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
             try_gate_cfg(sym::version, cfg.span, sess, features);
@@ -626,7 +626,7 @@ pub fn eval_condition(
             };
 
             // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
-            if sess.assume_incomplete_release {
+            if sess.parse_sess.assume_incomplete_release {
                 RustcVersion::CURRENT > min_version
             } else {
                 RustcVersion::CURRENT >= min_version
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 1bc2512a7b0..581d390992a 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -22,7 +22,7 @@ pub fn expand_cfg(
         Ok(cfg) => {
             let matches_cfg = attr::cfg_matches(
                 &cfg,
-                &cx.sess.parse_sess,
+                &cx.sess,
                 cx.current_expansion.lint_node_id,
                 Some(cx.ecfg.features),
             );
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index e7d7b4a7012..43d13569d1e 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -107,7 +107,7 @@ pub fn expand_include<'cx>(
         return DummyResult::any(sp);
     };
     // The file will be added to the code map by the parser
-    let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
+    let file = match resolve_path(&cx.sess, file.as_str(), sp) {
         Ok(f) => f,
         Err(err) => {
             err.emit();
@@ -179,7 +179,7 @@ pub fn expand_include_str(
     let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else {
         return DummyResult::any(sp);
     };
-    let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
+    let file = match resolve_path(&cx.sess, file.as_str(), sp) {
         Ok(f) => f,
         Err(err) => {
             err.emit();
@@ -213,7 +213,7 @@ pub fn expand_include_bytes(
     let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else {
         return DummyResult::any(sp);
     };
-    let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) {
+    let file = match resolve_path(&cx.sess, file.as_str(), sp) {
         Ok(f) => f,
         Err(err) => {
             err.emit();
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
index 094a61d6e0d..a1daadce958 100644
--- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
+++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
@@ -267,9 +267,12 @@ impl CguReuseTracker {
 
     fn check_expected_reuse(&self, sess: &Session) {
         if let Some(ref data) = self.data {
-            for (cgu_name, &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind)) in
-                &data.expected_reuse
-            {
+            let mut keys = data.expected_reuse.keys().collect::<Vec<_>>();
+            keys.sort_unstable();
+            for cgu_name in keys {
+                let &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind) =
+                    data.expected_reuse.get(cgu_name).unwrap();
+
                 if let Some(&actual_reuse) = data.actual_reuse.get(cgu_name) {
                     let (error, at_least) = match comparison_kind {
                         ComparisonKind::Exact => (expected_reuse != actual_reuse, false),
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index ace356ab153..959653c9326 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -554,6 +554,11 @@ fn link_staticlib<'a>(
             archive_builder_builder
                 .extract_bundled_libs(path, tempdir.as_ref(), &relevant_libs)
                 .unwrap_or_else(|e| sess.dcx().emit_fatal(e));
+
+            // We sort the libraries below
+            #[allow(rustc::potential_query_instability)]
+            let mut relevant_libs: Vec<Symbol> = relevant_libs.into_iter().collect();
+            relevant_libs.sort_unstable();
             for filename in relevant_libs {
                 let joined = tempdir.as_ref().join(filename.as_str());
                 let path = joined.as_path();
@@ -2201,14 +2206,19 @@ fn linker_with_args<'a>(
         .iter()
         .find(|(ty, _)| *ty == crate_type)
         .expect("failed to find crate type in dependency format list");
-    let native_libraries_from_nonstatics = codegen_results
+
+    // We sort the libraries below
+    #[allow(rustc::potential_query_instability)]
+    let mut native_libraries_from_nonstatics = codegen_results
         .crate_info
         .native_libraries
         .iter()
         .filter_map(|(cnum, libraries)| {
             (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries)
         })
-        .flatten();
+        .flatten()
+        .collect::<Vec<_>>();
+    native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
     for (raw_dylib_name, raw_dylib_imports) in
         collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
     {
@@ -2860,7 +2870,7 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
 
 fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
     match lib.cfg {
-        Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
+        Some(ref cfg) => rustc_attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
         None => true,
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index cae7c40c5ad..2dba04e0bb7 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -319,6 +319,8 @@ fn exported_symbols_provider_local(
 
         let (_, cgus) = tcx.collect_and_partition_mono_items(());
 
+        // The symbols created in this loop are sorted below it
+        #[allow(rustc::potential_query_instability)]
         for (mono_item, data) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
             if data.linkage != Linkage::External {
                 // We can only re-use things with external linkage, otherwise
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 0ad4af968db..098ea1b793c 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -912,17 +912,22 @@ impl CrateInfo {
                 })
                 .collect();
             let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" };
+
+            // This loop only adds new items to values of the hash map, so the order in which we
+            // iterate over the values is not important.
+            #[allow(rustc::potential_query_instability)]
             info.linked_symbols
                 .iter_mut()
                 .filter(|(crate_type, _)| {
                     !matches!(crate_type, CrateType::Rlib | CrateType::Staticlib)
                 })
                 .for_each(|(_, linked_symbols)| {
-                    linked_symbols.extend(
-                        missing_weak_lang_items
-                            .iter()
-                            .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)),
-                    );
+                    let mut symbols = missing_weak_lang_items
+                        .iter()
+                        .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text))
+                        .collect::<Vec<_>>();
+                    symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0));
+                    linked_symbols.extend(symbols);
                     if tcx.allocator_kind(()).is_some() {
                         // At least one crate needs a global allocator. This crate may be placed
                         // after the crate that defines it in the linker order, in which case some
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 36d7234a6ea..198b7ac4170 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -155,7 +155,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     Some([item]) if item.has_name(sym::linker) => {
                         if !tcx.features().used_with_arg {
                             feature_err(
-                                &tcx.sess.parse_sess,
+                                &tcx.sess,
                                 sym::used_with_arg,
                                 attr.span,
                                 "`#[used(linker)]` is currently unstable",
@@ -167,7 +167,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     Some([item]) if item.has_name(sym::compiler) => {
                         if !tcx.features().used_with_arg {
                             feature_err(
-                                &tcx.sess.parse_sess,
+                                &tcx.sess,
                                 sym::used_with_arg,
                                 attr.span,
                                 "`#[used(compiler)]` is currently unstable",
@@ -251,7 +251,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     && !attr.span.allows_unstable(sym::closure_track_caller)
                 {
                     feature_err(
-                        &tcx.sess.parse_sess,
+                        &tcx.sess,
                         sym::closure_track_caller,
                         attr.span,
                         "`#[track_caller]` on closures is currently unstable",
@@ -304,7 +304,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         // `#[target_feature]` on `main` and `start`.
                     } else if !tcx.features().target_feature_11 {
                         feature_err(
-                            &tcx.sess.parse_sess,
+                            &tcx.sess,
                             sym::target_feature_11,
                             attr.span,
                             "`#[target_feature(..)]` can only be applied to `unsafe` functions",
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 99280fdba7c..8f5421823a3 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -11,7 +11,6 @@
 #![feature(strict_provenance)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
 
 //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
 //! The backend-agnostic functions of this crate use functions defined in various traits that
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 0fef6bc110e..3694e41a0e0 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -82,7 +82,7 @@ pub fn from_target_feature(
             };
             if !allowed {
                 feature_err(
-                    &tcx.sess.parse_sess,
+                    &tcx.sess,
                     feature_gate.unwrap(),
                     item.span(),
                     format!("the target feature `{feature}` is currently unstable"),
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 02952872a93..327c91731bf 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -64,7 +64,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
 
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
         feature_err(
-            &ccx.tcx.sess.parse_sess,
+            &ccx.tcx.sess,
             sym::const_fn_floating_point_arithmetic,
             span,
             format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()),
@@ -553,7 +553,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
 
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
         feature_err(
-            &ccx.tcx.sess.parse_sess,
+            &ccx.tcx.sess,
             sym::const_mut_refs,
             span,
             format!("dereferencing raw mutable pointers in {}s is unstable", ccx.const_kind(),),
@@ -624,7 +624,7 @@ pub mod ty {
 
         fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
             feature_err(
-                &ccx.tcx.sess.parse_sess,
+                &ccx.tcx.sess,
                 sym::const_mut_refs,
                 span,
                 format!("mutable references are not allowed in {}s", ccx.const_kind()),
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 8c2752af659..63391a0faa6 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -865,10 +865,6 @@ impl DiagCtxt {
     /// directly).
     #[track_caller]
     pub fn delayed_bug(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
-        let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug();
-        if treat_next_err_as_bug {
-            self.bug(msg);
-        }
         DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
             .emit()
     }
@@ -883,10 +879,6 @@ impl DiagCtxt {
         sp: impl Into<MultiSpan>,
         msg: impl Into<DiagnosticMessage>,
     ) -> ErrorGuaranteed {
-        let treat_next_err_as_bug = self.inner.borrow().treat_next_err_as_bug();
-        if treat_next_err_as_bug {
-            self.span_bug(sp, msg);
-        }
         DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
             .with_span(sp)
             .emit()
@@ -1259,10 +1251,6 @@ impl DiagCtxtInner {
     }
 
     fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
-        if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() {
-            diagnostic.level = Bug;
-        }
-
         // The `LintExpectationId` can be stable or unstable depending on when it was created.
         // Diagnostics created before the definition of `HirId`s are unstable and can not yet
         // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
@@ -1298,6 +1286,12 @@ impl DiagCtxtInner {
             _ => {}
         }
 
+        // This must come after the possible promotion of `DelayedBug` to
+        // `Error` above.
+        if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() {
+            diagnostic.level = Bug;
+        }
+
         if diagnostic.has_future_breakage() {
             // Future breakages aren't emitted if they're Level::Allow,
             // but they still need to be constructed and stashed below,
@@ -1387,20 +1381,14 @@ impl DiagCtxtInner {
     }
 
     fn treat_err_as_bug(&self) -> bool {
-        self.flags.treat_err_as_bug.is_some_and(|c| {
-            self.err_count + self.lint_err_count + self.delayed_bug_count() >= c.get()
-        })
+        self.flags.treat_err_as_bug.is_some_and(|c| self.err_count + self.lint_err_count >= c.get())
     }
 
     // Use this one before incrementing `err_count`.
     fn treat_next_err_as_bug(&self) -> bool {
-        self.flags.treat_err_as_bug.is_some_and(|c| {
-            self.err_count + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get()
-        })
-    }
-
-    fn delayed_bug_count(&self) -> usize {
-        self.span_delayed_bugs.len() + self.good_path_delayed_bugs.len()
+        self.flags
+            .treat_err_as_bug
+            .is_some_and(|c| self.err_count + self.lint_err_count + 1 >= c.get())
     }
 
     fn has_errors(&self) -> bool {
@@ -1412,7 +1400,7 @@ impl DiagCtxtInner {
     }
 
     fn flush_delayed(&mut self, kind: DelayedBugKind) {
-        let (bugs, explanation) = match kind {
+        let (bugs, note1) = match kind {
             DelayedBugKind::Normal => (
                 std::mem::take(&mut self.span_delayed_bugs),
                 "no errors encountered even though `span_delayed_bug` issued",
@@ -1422,6 +1410,7 @@ impl DiagCtxtInner {
                 "no warnings or errors encountered even though `good_path_delayed_bugs` issued",
             ),
         };
+        let note2 = "those delayed bugs will now be shown as internal compiler errors";
 
         if bugs.is_empty() {
             return;
@@ -1447,8 +1436,11 @@ impl DiagCtxtInner {
 
             if i == 0 {
                 // Put the overall explanation before the `DelayedBug`s, to
-                // frame them better (e.g. separate warnings from them).
-                self.emit_diagnostic(Diagnostic::new(Bug, explanation));
+                // frame them better (e.g. separate warnings from them). Also,
+                // make it a note so it doesn't count as an error, because that
+                // could trigger `-Ztreat-err-as-bug`, which we don't want.
+                self.emit_diagnostic(Diagnostic::new(Note, note1));
+                self.emit_diagnostic(Diagnostic::new(Note, note2));
             }
 
             let mut bug =
@@ -1474,22 +1466,12 @@ impl DiagCtxtInner {
 
     fn panic_if_treat_err_as_bug(&self) {
         if self.treat_err_as_bug() {
-            match (
-                self.err_count + self.lint_err_count,
-                self.delayed_bug_count(),
-                self.flags.treat_err_as_bug.map(|c| c.get()).unwrap(),
-            ) {
-                (1, 0, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"),
-                (0, 1, 1) => panic!("aborting due delayed bug with `-Z treat-err-as-bug=1`"),
-                (count, delayed_count, val) => {
-                    if delayed_count > 0 {
-                        panic!(
-                            "aborting after {count} errors and {delayed_count} delayed bugs due to `-Z treat-err-as-bug={val}`",
-                        )
-                    } else {
-                        panic!("aborting after {count} errors due to `-Z treat-err-as-bug={val}`")
-                    }
-                }
+            let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
+            assert_eq!(n, self.err_count + self.lint_err_count);
+            if n == 1 {
+                panic!("aborting due to `-Z treat-err-as-bug=1`");
+            } else {
+                panic!("aborting after {n} errors due to `-Z treat-err-as-bug={n}`");
             }
         }
     }
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index e87f2306bc7..0a1c4430397 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1150,7 +1150,7 @@ impl<'a> ExtCtxt<'a> {
 ///
 /// This unifies the logic used for resolving `include_X!`.
 pub fn resolve_path(
-    parse_sess: &ParseSess,
+    parse_sess: &Session,
     path: impl Into<PathBuf>,
     span: Span,
 ) -> PResult<'_, PathBuf> {
@@ -1166,7 +1166,7 @@ pub fn resolve_path(
                 .expect("attempting to resolve a file path in an external file"),
             FileName::DocTest(path, _) => path,
             other => {
-                return Err(parse_sess.dcx.create_err(errors::ResolveRelativePath {
+                return Err(parse_sess.dcx().create_err(errors::ResolveRelativePath {
                     span,
                     path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
                 }));
@@ -1390,7 +1390,7 @@ pub fn parse_macro_name_and_helper_attrs(
 /// asserts in old versions of those crates and their wide use in the ecosystem.
 /// See issue #73345 for more details.
 /// FIXME(#73933): Remove this eventually.
-fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
+fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool {
     let name = item.ident.name;
     if name == sym::ProceduralMasqueradeDummyType {
         if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
@@ -1418,7 +1418,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
                             };
 
                             if crate_matches {
-                                sess.buffer_lint_with_diagnostic(
+                                sess.parse_sess.buffer_lint_with_diagnostic(
                                         PROC_MACRO_BACK_COMPAT,
                                         item.ident.span,
                                         ast::CRATE_NODE_ID,
@@ -1439,7 +1439,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
     false
 }
 
-pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &ParseSess) -> bool {
+pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) -> bool {
     let item = match ann {
         Annotatable::Item(item) => item,
         Annotatable::Stmt(stmt) => match &stmt.kind {
@@ -1451,7 +1451,7 @@ pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &P
     pretty_printing_compatibility_hack(item, sess)
 }
 
-pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseSess) -> bool {
+pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) -> bool {
     let item = match nt {
         Nonterminal::NtItem(item) => item,
         Nonterminal::NtStmt(stmt) => match &stmt.kind {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index d015d779963..f574e81e905 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -256,12 +256,7 @@ impl<'a> StripUnconfigured<'a> {
             );
         }
 
-        if !attr::cfg_matches(
-            &cfg_predicate,
-            &self.sess.parse_sess,
-            self.lint_node_id,
-            self.features,
-        ) {
+        if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) {
             return vec![];
         }
 
@@ -369,12 +364,7 @@ impl<'a> StripUnconfigured<'a> {
         };
         (
             parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| {
-                attr::cfg_matches(
-                    meta_item,
-                    &self.sess.parse_sess,
-                    self.lint_node_id,
-                    self.features,
-                )
+                attr::cfg_matches(meta_item, &self.sess, self.lint_node_id, self.features)
             }),
             Some(meta_item),
         )
@@ -385,7 +375,7 @@ impl<'a> StripUnconfigured<'a> {
     pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
         if self.features.is_some_and(|features| !features.stmt_expr_attributes) {
             let mut err = feature_err(
-                &self.sess.parse_sess,
+                &self.sess,
                 sym::stmt_expr_attributes,
                 attr.span,
                 "attributes on expressions are experimental",
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index c39a3dce34e..9c411be9ff9 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -30,8 +30,8 @@ use rustc_parse::parser::{
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
-use rustc_session::parse::{feature_err, ParseSess};
-use rustc_session::Limit;
+use rustc_session::parse::feature_err;
+use rustc_session::{Limit, Session};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{FileName, LocalExpnId, Span};
 
@@ -800,7 +800,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             return;
         }
         feature_err(
-            &self.cx.sess.parse_sess,
+            &self.cx.sess,
             sym::proc_macro_hygiene,
             span,
             format!("custom attributes cannot be applied to {kind}"),
@@ -810,7 +810,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
     fn gate_proc_macro_input(&self, annotatable: &Annotatable) {
         struct GateProcMacroInput<'a> {
-            parse_sess: &'a ParseSess,
+            sess: &'a Session,
         }
 
         impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
@@ -820,7 +820,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
                     {
                         feature_err(
-                            self.parse_sess,
+                            self.sess,
                             sym::proc_macro_hygiene,
                             item.span,
                             "non-inline modules in proc macro input are unstable",
@@ -835,8 +835,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         }
 
         if !self.cx.ecfg.features.proc_macro_hygiene {
-            annotatable
-                .visit_with(&mut GateProcMacroInput { parse_sess: &self.cx.sess.parse_sess });
+            annotatable.visit_with(&mut GateProcMacroInput { sess: &self.cx.sess });
         }
     }
 
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index a56c980791a..363b52aef8a 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -477,14 +477,14 @@ pub fn compile_declarative_macro(
                     let tt = mbe::quoted::parse(
                         &TokenStream::new(vec![tt.clone()]),
                         true,
-                        &sess.parse_sess,
+                        sess,
                         def.id,
                         features,
                         edition,
                     )
                     .pop()
                     .unwrap();
-                    valid &= check_lhs_nt_follows(&sess.parse_sess, def, &tt);
+                    valid &= check_lhs_nt_follows(sess, def, &tt);
                     return tt;
                 }
                 sess.dcx().span_bug(def.span, "wrong-structured lhs")
@@ -501,7 +501,7 @@ pub fn compile_declarative_macro(
                     return mbe::quoted::parse(
                         &TokenStream::new(vec![tt.clone()]),
                         false,
-                        &sess.parse_sess,
+                        sess,
                         def.id,
                         features,
                         edition,
@@ -516,12 +516,12 @@ pub fn compile_declarative_macro(
     };
 
     for rhs in &rhses {
-        valid &= check_rhs(&sess.parse_sess, rhs);
+        valid &= check_rhs(sess, rhs);
     }
 
     // don't abort iteration early, so that errors for multiple lhses can be reported
     for lhs in &lhses {
-        valid &= check_lhs_no_empty_seq(&sess.parse_sess, slice::from_ref(lhs));
+        valid &= check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
     }
 
     valid &= macro_check::check_meta_variables(&sess.parse_sess, def.id, def.span, &lhses, &rhses);
@@ -588,21 +588,21 @@ pub fn compile_declarative_macro(
     (mk_syn_ext(expander), rule_spans)
 }
 
-fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
+fn check_lhs_nt_follows(sess: &Session, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
     // lhs is going to be like TokenTree::Delimited(...), where the
     // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
     if let mbe::TokenTree::Delimited(.., delimited) = lhs {
         check_matcher(sess, def, &delimited.tts)
     } else {
         let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
-        sess.dcx.span_err(lhs.span(), msg);
+        sess.dcx().span_err(lhs.span(), msg);
         false
     }
     // we don't abort on errors on rejection, the driver will do that for us
     // after parsing/expansion. we can report every error in every macro this way.
 }
 
-fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool {
+fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool {
     if seq.separator.is_some() {
         false
     } else {
@@ -621,7 +621,7 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool
                         iter.next();
                     }
                     let span = t.span.to(now.span);
-                    sess.dcx.span_note(span, "doc comments are ignored in matcher position");
+                    sess.dcx().span_note(span, "doc comments are ignored in matcher position");
                 }
                 mbe::TokenTree::Sequence(_, sub_seq)
                     if (sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore
@@ -635,7 +635,7 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool
 
 /// Checks that the lhs contains no repetition which could match an empty token
 /// tree, because then the matcher would hang indefinitely.
-fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
+fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> bool {
     use mbe::TokenTree;
     for tt in tts {
         match tt {
@@ -651,7 +651,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
             TokenTree::Sequence(span, seq) => {
                 if is_empty_token_tree(sess, seq) {
                     let sp = span.entire();
-                    sess.dcx.span_err(sp, "repetition matches empty token tree");
+                    sess.dcx().span_err(sp, "repetition matches empty token tree");
                     return false;
                 }
                 if !check_lhs_no_empty_seq(sess, &seq.tts) {
@@ -664,22 +664,22 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
     true
 }
 
-fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool {
+fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> bool {
     match *rhs {
         mbe::TokenTree::Delimited(..) => return true,
         _ => {
-            sess.dcx.span_err(rhs.span(), "macro rhs must be delimited");
+            sess.dcx().span_err(rhs.span(), "macro rhs must be delimited");
         }
     }
     false
 }
 
-fn check_matcher(sess: &ParseSess, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool {
+fn check_matcher(sess: &Session, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool {
     let first_sets = FirstSets::new(matcher);
     let empty_suffix = TokenSet::empty();
-    let err = sess.dcx.err_count();
+    let err = sess.dcx().err_count();
     check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix);
-    err == sess.dcx.err_count()
+    err == sess.dcx().err_count()
 }
 
 fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool {
@@ -1014,7 +1014,7 @@ impl<'tt> TokenSet<'tt> {
 // Requires that `first_sets` is pre-computed for `matcher`;
 // see `FirstSets::new`.
 fn check_matcher_core<'tt>(
-    sess: &ParseSess,
+    sess: &Session,
     def: &ast::Item,
     first_sets: &FirstSets<'tt>,
     matcher: &'tt [mbe::TokenTree],
@@ -1139,7 +1139,7 @@ fn check_matcher_core<'tt>(
                             name,
                             Some(NonterminalKind::PatParam { inferred: false }),
                         ));
-                        sess.buffer_lint_with_diagnostic(
+                        sess.parse_sess.buffer_lint_with_diagnostic(
                             RUST_2021_INCOMPATIBLE_OR_PATTERNS,
                             span,
                             ast::CRATE_NODE_ID,
@@ -1158,7 +1158,7 @@ fn check_matcher_core<'tt>(
                             };
 
                             let sp = next_token.span();
-                            let mut err = sess.dcx.struct_span_err(
+                            let mut err = sess.dcx().struct_span_err(
                                 sp,
                                 format!(
                                     "`${name}:{frag}` {may_be} followed by `{next}`, which \
@@ -1172,7 +1172,7 @@ fn check_matcher_core<'tt>(
                             err.span_label(sp, format!("not allowed after `{kind}` fragments"));
 
                             if kind == NonterminalKind::PatWithOr
-                                && sess.edition.at_least_rust_2021()
+                                && sess.parse_sess.edition.at_least_rust_2021()
                                 && next_token.is_token(&BinOp(token::BinOpToken::Or))
                             {
                                 let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 889f43ed203..4824b67d277 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -5,7 +5,8 @@ use rustc_ast::token::{self, Delimiter, Token};
 use rustc_ast::{tokenstream, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_feature::Features;
-use rustc_session::parse::{feature_err, ParseSess};
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
 use rustc_span::symbol::{kw, sym, Ident};
 
 use rustc_span::edition::Edition;
@@ -38,7 +39,7 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
 pub(super) fn parse(
     input: &tokenstream::TokenStream,
     parsing_patterns: bool,
-    sess: &ParseSess,
+    sess: &Session,
     node_id: NodeId,
     features: &Features,
     edition: Edition,
@@ -84,7 +85,7 @@ pub(super) fn parse(
                                                     "invalid fragment specifier `{}`",
                                                     frag.name
                                                 );
-                                                sess.dcx
+                                                sess.dcx()
                                                     .struct_span_err(span, msg)
                                                     .with_help(VALID_FRAGMENT_NAMES_MSG)
                                                     .emit();
@@ -113,7 +114,7 @@ pub(super) fn parse(
 }
 
 /// Asks for the `macro_metavar_expr` feature if it is not already declared
-fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess, span: Span) {
+fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, span: Span) {
     if !features.macro_metavar_expr {
         let msg = "meta-variable expressions are unstable";
         feature_err(sess, sym::macro_metavar_expr, span, msg).emit();
@@ -138,7 +139,7 @@ fn parse_tree<'a>(
     tree: &'a tokenstream::TokenTree,
     outer_trees: &mut impl Iterator<Item = &'a tokenstream::TokenTree>,
     parsing_patterns: bool,
-    sess: &ParseSess,
+    sess: &Session,
     node_id: NodeId,
     features: &Features,
     edition: Edition,
@@ -174,7 +175,8 @@ fn parse_tree<'a>(
                                 // The delimiter is `{`. This indicates the beginning
                                 // of a meta-variable expression (e.g. `${count(ident)}`).
                                 // Try to parse the meta-variable expression.
-                                match MetaVarExpr::parse(tts, delim_span.entire(), sess) {
+                                match MetaVarExpr::parse(tts, delim_span.entire(), &sess.parse_sess)
+                                {
                                     Err(err) => {
                                         err.emit();
                                         // Returns early the same read `$` to avoid spanning
@@ -195,7 +197,7 @@ fn parse_tree<'a>(
                             _ => {
                                 let tok = pprust::token_kind_to_string(&token::OpenDelim(delim));
                                 let msg = format!("expected `(` or `{{`, found `{tok}`");
-                                sess.dcx.span_err(delim_span.entire(), msg);
+                                sess.dcx().span_err(delim_span.entire(), msg);
                             }
                         }
                     }
@@ -244,7 +246,7 @@ fn parse_tree<'a>(
                 Some(tokenstream::TokenTree::Token(token, _)) => {
                     let msg =
                         format!("expected identifier, found `{}`", pprust::token_to_string(token),);
-                    sess.dcx.span_err(token.span, msg);
+                    sess.dcx().span_err(token.span, msg);
                     TokenTree::MetaVar(token.span, Ident::empty())
                 }
 
@@ -313,7 +315,7 @@ fn parse_kleene_op<'a>(
 fn parse_sep_and_kleene_op<'a>(
     input: &mut impl Iterator<Item = &'a tokenstream::TokenTree>,
     span: Span,
-    sess: &ParseSess,
+    sess: &Session,
 ) -> (Option<Token>, KleeneToken) {
     // We basically look at two token trees here, denoted as #1 and #2 below
     let span = match parse_kleene_op(input, span) {
@@ -325,7 +327,7 @@ fn parse_sep_and_kleene_op<'a>(
             // #2 is the `?` Kleene op, which does not take a separator (error)
             Ok(Ok((KleeneOp::ZeroOrOne, span))) => {
                 // Error!
-                sess.dcx.span_err(
+                sess.dcx().span_err(
                     token.span,
                     "the `?` macro repetition operator does not take a separator",
                 );
@@ -346,7 +348,7 @@ fn parse_sep_and_kleene_op<'a>(
     };
 
     // If we ever get to this point, we have experienced an "unexpected token" error
-    sess.dcx.span_err(span, "expected one of: `*`, `+`, or `?`");
+    sess.dcx().span_err(span, "expected one of: `*`, `+`, or `?`");
 
     // Return a dummy
     (None, KleeneToken::new(KleeneOp::ZeroOrMore, span))
@@ -355,9 +357,10 @@ 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()} ) => {} }`
-fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &ParseSess, token: &Token) {
-    sess.dcx.span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token)));
-    sess.dcx.span_note(
+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)));
+    sess.dcx().span_note(
         token.span,
         "`$$` and meta-variable expressions are not allowed inside macro parameter definitions",
     );
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index a1d21361957..2233cad2e63 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -119,7 +119,7 @@ impl MultiItemModifier for DeriveProcMacro {
         // We need special handling for statement items
         // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
         let is_stmt = matches!(item, Annotatable::Stmt(..));
-        let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess);
+        let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess);
         let input = if hack {
             let nt = match item {
                 Annotatable::Item(item) => token::NtItem(item),
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 6392894fea2..3a78bd94505 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -258,7 +258,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                     // represented as a delimited group.
                     // FIXME: It needs to be removed, but there are some
                     // compatibility issues (see #73345).
-                    if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.sess()) {
+                    if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.ecx.sess) {
                         trees.extend(Self::from_internal((stream, rustc)));
                     } else {
                         trees.push(TokenTree::Group(Group {
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 58ac9668da5..6b347f7035a 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2571,9 +2571,17 @@ pub enum OpaqueTyOrigin {
     },
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
+pub enum InferDelegationKind {
+    Input(usize),
+    Output,
+}
+
 /// The various kinds of types recognized by the compiler.
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum TyKind<'hir> {
+    /// Actual type should be inherited from `DefId` signature
+    InferDelegation(DefId, InferDelegationKind),
     /// A variable length slice (i.e., `[T]`).
     Slice(&'hir Ty<'hir>),
     /// A fixed length array (i.e., `[T; n]`).
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index dd3633b6b4f..adc09025809 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -856,7 +856,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
             visitor.visit_lifetime(lifetime);
         }
         TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
-        TyKind::Infer | TyKind::Err(_) => {}
+        TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {}
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 6a17668ad17..432c9c12cbf 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -263,6 +263,10 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
 
 hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
 
+hir_analysis_not_supported_delegation =
+    {$descr} is not supported yet
+    .label = callee defined here
+
 hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types
 
 hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 7b23b74f829..bfe88df4e1a 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -59,7 +59,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
                 // For now, require that parenthetical notation be used only with `Fn()` etc.
                 feature_err(
-                    &self.tcx().sess.parse_sess,
+                    &self.tcx().sess,
                     sym::unboxed_closures,
                     span,
                     "parenthetical notation is only stable when used with `Fn`-family traits",
@@ -75,7 +75,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar {
             // For now, require that parenthetical notation be used only with `Fn()` etc.
             let mut err = feature_err(
-                &sess.parse_sess,
+                sess,
                 sym::unboxed_closures,
                 span,
                 "the precise format of `Fn`-family traits' type parameters is subject to change",
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 2886ec21320..9f4f1413650 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -29,10 +29,9 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
-use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{
-    self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Ty, TyCtxt,
-    TypeVisitableExt,
+    self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty,
+    TyCtxt, TypeVisitableExt,
 };
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc_span::edit_distance::find_best_match_for_name;
@@ -2322,6 +2321,114 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self.ast_ty_to_ty_inner(ast_ty, false, true)
     }
 
+    fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool {
+        let mut error_occured = false;
+        let sig_span = self.tcx().def_span(sig_id);
+        let mut try_emit = |descr| {
+            if emit {
+                self.tcx().dcx().emit_err(crate::errors::NotSupportedDelegation {
+                    span,
+                    descr,
+                    callee_span: sig_span,
+                });
+            }
+            error_occured = true;
+        };
+
+        if let Some(node) = self.tcx().hir().get_if_local(sig_id)
+            && let Some(decl) = node.fn_decl()
+            && let hir::FnRetTy::Return(ty) = decl.output
+            && let hir::TyKind::InferDelegation(_, _) = ty.kind
+        {
+            try_emit("recursive delegation");
+        }
+
+        let sig = self.tcx().fn_sig(sig_id).instantiate_identity();
+        if sig.output().has_opaque_types() {
+            try_emit("delegation to a function with opaque type");
+        }
+
+        let sig_generics = self.tcx().generics_of(sig_id);
+        let parent = self.tcx().parent(self.item_def_id());
+        let parent_generics = self.tcx().generics_of(parent);
+
+        let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize;
+        let sig_has_self = sig_generics.has_self as usize;
+
+        if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait {
+            try_emit("delegation with early bound generics");
+        }
+
+        if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes {
+            try_emit("delegation to async functions");
+        }
+
+        if self.tcx().constness(sig_id) == hir::Constness::Const {
+            try_emit("delegation to const functions");
+        }
+
+        if sig.c_variadic() {
+            try_emit("delegation to variadic functions");
+            // variadic functions are also `unsafe` and `extern "C"`.
+            // Do not emit same error multiple times.
+            return error_occured;
+        }
+
+        if let hir::Unsafety::Unsafe = sig.unsafety() {
+            try_emit("delegation to unsafe functions");
+        }
+
+        if abi::Abi::Rust != sig.abi() {
+            try_emit("delegation to non Rust ABI functions");
+        }
+
+        error_occured
+    }
+
+    fn ty_from_delegation(
+        &self,
+        sig_id: DefId,
+        idx: hir::InferDelegationKind,
+        span: Span,
+    ) -> Ty<'tcx> {
+        if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output)
+        {
+            let e = self.tcx().dcx().span_delayed_bug(span, "not supported delegation case");
+            self.set_tainted_by_errors(e);
+            return Ty::new_error(self.tcx(), e);
+        };
+        let sig = self.tcx().fn_sig(sig_id);
+        let sig_generics = self.tcx().generics_of(sig_id);
+
+        let parent = self.tcx().parent(self.item_def_id());
+        let parent_def_kind = self.tcx().def_kind(parent);
+
+        let sig = if let DefKind::Impl { .. } = parent_def_kind
+            && sig_generics.has_self
+        {
+            // Generic params can't be here except the trait self type.
+            // They are not supported yet.
+            assert_eq!(sig_generics.count(), 1);
+            assert_eq!(self.tcx().generics_of(parent).count(), 0);
+
+            let self_ty = self.tcx().type_of(parent).instantiate_identity();
+            let generic_self_ty = ty::GenericArg::from(self_ty);
+            let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
+            sig.instantiate(self.tcx(), substs)
+        } else {
+            sig.instantiate_identity()
+        };
+
+        // Bound vars are also inherited from `sig_id`. They will be
+        // rebinded later in `ty_of_fn`.
+        let sig = sig.skip_binder();
+
+        match idx {
+            hir::InferDelegationKind::Input(id) => sig.inputs()[id],
+            hir::InferDelegationKind::Output => sig.output(),
+        }
+    }
+
     /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
     /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
     #[instrument(level = "debug", skip(self), ret)]
@@ -2329,6 +2436,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let tcx = self.tcx();
 
         let result_ty = match &ast_ty.kind {
+            hir::TyKind::InferDelegation(sig_id, idx) => {
+                self.ty_from_delegation(*sig_id, *idx, ast_ty.span)
+            }
             hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.ast_ty_to_ty(ty)),
             hir::TyKind::Ptr(mt) => {
                 Ty::new_ptr(tcx, ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl })
@@ -2520,7 +2630,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         hir_ty: Option<&hir::Ty<'_>>,
     ) -> ty::PolyFnSig<'tcx> {
         let tcx = self.tcx();
-        let bound_vars = tcx.late_bound_vars(hir_id);
+        let bound_vars = if let hir::FnRetTy::Return(ret_ty) = decl.output
+            && let hir::TyKind::InferDelegation(sig_id, _) = ret_ty.kind
+        {
+            tcx.fn_sig(sig_id).skip_binder().bound_vars()
+        } else {
+            tcx.late_bound_vars(hir_id)
+        };
         debug!(?bound_vars);
 
         // We proactively collect all the inferred type params to emit a single error per fn def.
@@ -2543,7 +2659,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
                     {
                         infer_replacements.push((a.span, suggested_ty.to_string()));
-                        return suggested_ty;
+                        return Ty::new_error_with_message(
+                            self.tcx(),
+                            a.span,
+                            suggested_ty.to_string(),
+                        );
                     }
                 }
 
@@ -2561,7 +2681,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
                 {
                     infer_replacements.push((output.span, suggested_ty.to_string()));
-                    suggested_ty
+                    Ty::new_error_with_message(self.tcx(), output.span, suggested_ty.to_string())
                 } else {
                     visitor.visit_ty(output);
                     self.ast_ty_to_ty(output)
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 6265ddafef0..77914802bf7 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -996,7 +996,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
 
     if adt.is_union() && !tcx.features().transparent_unions {
         feature_err(
-            &tcx.sess.parse_sess,
+            &tcx.sess,
             sym::transparent_unions,
             tcx.def_span(adt.did()),
             "transparent unions are unstable",
@@ -1128,7 +1128,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
         if !tcx.features().repr128 {
             feature_err(
-                &tcx.sess.parse_sess,
+                &tcx.sess,
                 sym::repr128,
                 tcx.def_span(def_id),
                 "repr with 128-bit type is unstable",
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 3b05eaedf34..28c8f846c23 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -293,7 +293,7 @@ fn default_body_is_unstable(
 
     rustc_session::parse::add_feature_diagnostics_for_issue(
         &mut err,
-        &tcx.sess.parse_sess,
+        &tcx.sess,
         feature,
         rustc_feature::GateIssue::Library(issue),
         false,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 59c72227144..4772bae58c4 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1591,7 +1591,7 @@ fn check_method_receiver<'tcx>(
             return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
                 // Report error; would have worked with `arbitrary_self_types`.
                 feature_err(
-                    &tcx.sess.parse_sess,
+                    &tcx.sess,
                     sym::arbitrary_self_types,
                     span,
                     format!(
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 3d8390d1946..4f049f699e6 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1189,12 +1189,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
                         && !self.tcx.features().anonymous_lifetime_in_impl_trait
                     {
-                        let mut diag = rustc_session::parse::feature_err(
-                            &self.tcx.sess.parse_sess,
-                            sym::anonymous_lifetime_in_impl_trait,
-                            lifetime_ref.ident.span,
-                            "anonymous lifetimes in `impl Trait` are unstable",
-                        );
+                        let mut diag: rustc_errors::DiagnosticBuilder<'_> =
+                            rustc_session::parse::feature_err(
+                                &self.tcx.sess,
+                                sym::anonymous_lifetime_in_impl_trait,
+                                lifetime_ref.ident.span,
+                                "anonymous lifetimes in `impl Trait` are unstable",
+                            );
 
                         if let Some(generics) =
                             self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id)
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index b936b0c0805..bfa9dc42422 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -639,7 +639,7 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
         use rustc_session::parse::feature_err;
         use rustc_span::symbol::sym;
         feature_err(
-            &tcx.sess.parse_sess,
+            &tcx.sess,
             sym::inherent_associated_types,
             span,
             "inherent associated types are unstable",
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 4f22da4ba3b..f14390b77c6 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1501,3 +1501,13 @@ pub enum RefOfMutStaticSugg {
         var: String,
     },
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_not_supported_delegation)]
+pub struct NotSupportedDelegation<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub descr: &'a str,
+    #[label]
+    pub callee_span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index dfc54ac5b23..f5abb7261c0 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -116,7 +116,8 @@ use rustc_hir::def::DefKind;
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
-    const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi`";
+    const CONVENTIONS_UNSTABLE: &str =
+        "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`";
     const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
     const UNSTABLE_EXPLAIN: &str =
         "using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
@@ -133,13 +134,8 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
         // Using this ABI would be ok, if the feature for additional ABI support was enabled.
         // Return CONVENTIONS_STABLE, because we want the other error to look the same.
         (false, true) => {
-            feature_err(
-                &tcx.sess.parse_sess,
-                sym::extended_varargs_abi_support,
-                span,
-                UNSTABLE_EXPLAIN,
-            )
-            .emit();
+            feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN)
+                .emit();
             CONVENTIONS_STABLE
         }
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 1eaec997053..d36e0892d19 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -320,7 +320,7 @@ impl<'a> State<'a> {
                 self.word("/*ERROR*/");
                 self.pclose();
             }
-            hir::TyKind::Infer => {
+            hir::TyKind::Infer | hir::TyKind::InferDelegation(..) => {
                 self.word("_");
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 0b266202b26..e9d373119fa 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -704,7 +704,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
             feature_err(
-                &self.tcx.sess.parse_sess,
+                &self.tcx.sess,
                 sym::unsized_tuple_coercion,
                 self.cause.span,
                 "unsized tuple coercion is not stable enough for use and is subject to change",
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index fdad998c451..af47455c16d 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1865,7 +1865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt);
                     if self.tcx.sess.is_nightly_build() && same_adt {
                         feature_err(
-                            &self.tcx.sess.parse_sess,
+                            &self.tcx.sess,
                             sym::type_changing_struct_update,
                             base_expr.span,
                             "type changing struct updating is experimental",
@@ -3262,7 +3262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     if !self.tcx.features().offset_of_enum {
                         rustc_session::parse::feature_err(
-                            &self.tcx.sess.parse_sess,
+                            &self.tcx.sess,
                             sym::offset_of_enum,
                             ident.span,
                             "using enums in offset_of is experimental",
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 09313cd9738..e60e3ffeaa7 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -84,7 +84,7 @@ impl<'tcx> InferCtxt<'tcx> {
             selection_cache: self.selection_cache.clone(),
             evaluation_cache: self.evaluation_cache.clone(),
             reported_trait_errors: self.reported_trait_errors.clone(),
-            reported_closure_mismatch: self.reported_closure_mismatch.clone(),
+            reported_signature_mismatch: self.reported_signature_mismatch.clone(),
             tainted_by_errors: self.tainted_by_errors.clone(),
             err_count_on_creation: self.err_count_on_creation,
             universe: self.universe.clone(),
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index fcc94687ed2..e164041c599 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -278,7 +278,7 @@ pub struct InferCtxt<'tcx> {
     /// avoid reporting the same error twice.
     pub reported_trait_errors: RefCell<FxIndexMap<Span, Vec<ty::Predicate<'tcx>>>>,
 
-    pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
+    pub reported_signature_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
 
     /// When an error occurs, we want to avoid reporting "derived"
     /// errors that are due to this original failure. Normally, we
@@ -702,7 +702,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             selection_cache: Default::default(),
             evaluation_cache: Default::default(),
             reported_trait_errors: Default::default(),
-            reported_closure_mismatch: Default::default(),
+            reported_signature_mismatch: Default::default(),
             tainted_by_errors: Cell::new(None),
             err_count_on_creation: tcx.dcx().err_count(),
             universe: Cell::new(ty::UniverseIndex::ROOT),
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 03335996c03..32fba6ade88 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -202,8 +202,15 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
                         if !args.is_empty() {
                             error!("`any()` must be empty");
                         }
+                    } else if arg.has_name(sym::none)
+                        && let Some(args) = arg.meta_item_list()
+                    {
+                        values.insert(None);
+                        if !args.is_empty() {
+                            error!("`none()` must be empty");
+                        }
                     } else {
-                        error!("`values()` arguments must be string literals or `any()`");
+                        error!("`values()` arguments must be string literals, `none()` or `any()`");
                     }
                 }
             } else {
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 8d2f2aaca55..5e1f2ed11ac 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1306,10 +1306,7 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
             cx.emit_spanned_lint(
                 UNGATED_ASYNC_FN_TRACK_CALLER,
                 attr.span,
-                BuiltinUngatedAsyncFnTrackCaller {
-                    label: span,
-                    parse_sess: &cx.tcx.sess.parse_sess,
-                },
+                BuiltinUngatedAsyncFnTrackCaller { label: span, session: &cx.tcx.sess },
             );
         }
     }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 3c2d0c7b205..b98b1a2935c 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -786,7 +786,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                             if let ast::LitKind::Str(rationale, _) = name_value.kind {
                                 if !self.features.lint_reasons {
                                     feature_err(
-                                        &self.sess.parse_sess,
+                                        &self.sess,
                                         sym::lint_reasons,
                                         item.span,
                                         "lint reasons are experimental",
@@ -1074,7 +1074,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                             lint.note(fluent::lint_note);
                             rustc_session::parse::add_feature_diagnostics_for_issue(
                                 lint,
-                                &self.sess.parse_sess,
+                                &self.sess,
                                 feature,
                                 GateIssue::Language,
                                 lint_from_cli,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index f370c4392b3..73db5790c2b 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -13,7 +13,7 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{
     inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
 };
-use rustc_session::parse::ParseSess;
+use rustc_session::Session;
 use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
 
 use crate::{
@@ -235,7 +235,7 @@ pub struct BuiltinUnstableFeatures;
 // lint_ungated_async_fn_track_caller
 pub struct BuiltinUngatedAsyncFnTrackCaller<'a> {
     pub label: Span,
-    pub parse_sess: &'a ParseSess,
+    pub session: &'a Session,
 }
 
 impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
@@ -243,7 +243,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
         diag.span_label(self.label, fluent::lint_label);
         rustc_session::parse::add_feature_diagnostics(
             diag,
-            self.parse_sess,
+            self.session,
             sym::async_fn_track_caller,
         );
     }
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index a639a887544..5e20a03bbc0 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -82,7 +82,7 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib>
 
 pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
     match lib.cfg {
-        Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
+        Some(ref cfg) => attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
         None => true,
     }
 }
@@ -163,7 +163,7 @@ impl<'tcx> Collector<'tcx> {
                             "link-arg" => {
                                 if !features.link_arg_attribute {
                                     feature_err(
-                                        &sess.parse_sess,
+                                        sess,
                                         sym::link_arg_attribute,
                                         span,
                                         "link kind `link-arg` is unstable",
@@ -206,13 +206,8 @@ impl<'tcx> Collector<'tcx> {
                             continue;
                         };
                         if !features.link_cfg {
-                            feature_err(
-                                &sess.parse_sess,
-                                sym::link_cfg,
-                                item.span(),
-                                "link cfg is unstable",
-                            )
-                            .emit();
+                            feature_err(sess, sym::link_cfg, item.span(), "link cfg is unstable")
+                                .emit();
                         }
                         cfg = Some(link_cfg.clone());
                     }
@@ -277,7 +272,7 @@ impl<'tcx> Collector<'tcx> {
                     macro report_unstable_modifier($feature: ident) {
                         if !features.$feature {
                             feature_err(
-                                &sess.parse_sess,
+                                sess,
                                 sym::$feature,
                                 span,
                                 format!("linking modifier `{modifier}` is unstable"),
@@ -520,11 +515,23 @@ impl<'tcx> Collector<'tcx> {
     ) -> DllImport {
         let span = self.tcx.def_span(item);
 
+        // this logic is similar to `Target::adjust_abi` (in rustc_target/src/spec/mod.rs) but errors on unsupported inputs
         let calling_convention = if self.tcx.sess.target.arch == "x86" {
             match abi {
                 Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C,
-                Abi::Stdcall { .. } | Abi::System { .. } => {
-                    DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
+                Abi::Stdcall { .. } => DllCallingConvention::Stdcall(self.i686_arg_list_size(item)),
+                // On Windows, `extern "system"` behaves like msvc's `__stdcall`.
+                // `__stdcall` only applies on x86 and on non-variadic functions:
+                // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
+                Abi::System { .. } => {
+                    let c_variadic =
+                        self.tcx.type_of(item).instantiate_identity().fn_sig(self.tcx).c_variadic();
+
+                    if c_variadic {
+                        DllCallingConvention::C
+                    } else {
+                        DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
+                    }
                 }
                 Abi::Fastcall { .. } => {
                     DllCallingConvention::Fastcall(self.i686_arg_list_size(item))
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 90b479cf2f4..efe7bdfa06d 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -116,8 +116,7 @@ pub fn report_unstable(
     if is_soft {
         soft_handler(SOFT_UNSTABLE, span, msg)
     } else {
-        let mut err =
-            feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), msg);
+        let mut err = feature_err_issue(sess, feature, span, GateIssue::Library(issue), msg);
         if let Some((inner_types, msg, sugg, applicability)) = suggestion {
             err.span_suggestion(inner_types, msg, sugg, applicability);
         }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index af601a0d702..bebee8df10e 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -611,9 +611,6 @@ pub enum SelectionError<'tcx> {
     NotConstEvaluatable(NotConstEvaluatable),
     /// Exceeded the recursion depth during type projection.
     Overflow(OverflowError),
-    /// Signaling that an error has already been emitted, to avoid
-    /// multiple errors being shown.
-    ErrorReporting,
     /// Computing an opaque type's hidden type caused an error (e.g. a cycle error).
     /// We can thus not know whether the hidden type implements an auto trait, so
     /// we should not presume anything about it.
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 734c2b61c07..64f4af08e12 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -302,7 +302,6 @@ impl EvaluationResult {
 pub enum OverflowError {
     Error(ErrorGuaranteed),
     Canonical,
-    ErrorReporting,
 }
 
 impl From<ErrorGuaranteed> for OverflowError {
@@ -318,7 +317,6 @@ impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
         match overflow_error {
             OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)),
             OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical),
-            OverflowError::ErrorReporting => SelectionError::ErrorReporting,
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 9e8d7c2ef3e..ad9296a4cc8 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -42,7 +42,7 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet};
 use rustc_index::IndexVec;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
@@ -202,6 +202,10 @@ pub struct ResolverAstLowering {
 
     /// Lints that were emitted by the resolver and early lints.
     pub lint_buffer: Steal<LintBuffer>,
+
+    /// Information about functions signatures for delegation items expansion
+    pub has_self: LocalDefIdSet,
+    pub fn_parameter_counts: LocalDefIdMap<usize>,
 }
 
 #[derive(Clone, Copy, Debug)]
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index bcff820da79..3bd8ae02586 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -252,6 +252,8 @@ impl<'a> Parser<'a> {
         {
             // IMPL ITEM
             self.parse_item_impl(attrs, def_())?
+        } else if self.is_reuse_path_item() {
+            self.parse_item_delegation()?
         } else if self.check_keyword(kw::Mod)
             || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Mod])
         {
@@ -349,11 +351,18 @@ impl<'a> Parser<'a> {
     /// When parsing a statement, would the start of a path be an item?
     pub(super) fn is_path_start_item(&mut self) -> bool {
         self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }`
+        || self.is_reuse_path_item()
         || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }`
         || self.is_async_fn() // no(2015): `async::b`, yes: `async fn`
         || matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac`
     }
 
+    fn is_reuse_path_item(&mut self) -> bool {
+        // no: `reuse ::path` for compatibility reasons with macro invocations
+        self.token.is_keyword(kw::Reuse)
+            && self.look_ahead(1, |t| t.is_path_start() && t.kind != token::ModSep)
+    }
+
     /// Are we sure this could not possibly be a macro invocation?
     fn isnt_macro_invocation(&mut self) -> bool {
         self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::ModSep)
@@ -655,6 +664,33 @@ impl<'a> Parser<'a> {
         Ok((Ident::empty(), item_kind))
     }
 
+    fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
+        let span = self.token.span;
+        self.expect_keyword(kw::Reuse)?;
+
+        let (qself, path) = if self.eat_lt() {
+            let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
+            (Some(qself), path)
+        } else {
+            (None, self.parse_path(PathStyle::Expr)?)
+        };
+
+        let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
+            Some(self.parse_block()?)
+        } else {
+            self.expect(&token::Semi)?;
+            None
+        };
+        let span = span.to(self.prev_token.span);
+        self.sess.gated_spans.gate(sym::fn_delegation, span);
+
+        let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty());
+        Ok((
+            ident,
+            ItemKind::Delegation(Box::new(Delegation { id: DUMMY_NODE_ID, qself, path, body })),
+        ))
+    }
+
     fn parse_item_list<T>(
         &mut self,
         attrs: &mut AttrVec,
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index e4bbc9eeaf7..20ed2573e3a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1170,7 +1170,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         sym::rust_logo => {
                             if !self.tcx.features().rustdoc_internals {
                                 feature_err(
-                                    &self.tcx.sess.parse_sess,
+                                    &self.tcx.sess,
                                     sym::rustdoc_internals,
                                     meta.span(),
                                     "the `#[doc(rust_logo)]` attribute is used for Rust branding",
@@ -1815,7 +1815,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         (target, self.tcx.features().fn_align)
                     {
                         feature_err(
-                            &self.tcx.sess.parse_sess,
+                            &self.tcx.sess,
                             sym::fn_align,
                             hint.span(),
                             "`repr(align)` attributes on functions are unstable",
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 3e3f2771f5f..3676eb92a3f 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -147,7 +147,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
             [missing_primary, ref missing_secondary @ ..] => {
                 let msg =
                     format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name());
-                let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, msg);
+                let mut err = feature_err(&tcx.sess, *missing_primary, span, msg);
 
                 // If multiple feature gates would be required to enable this expression, include
                 // them as help messages. Don't emit a separate error for each missing feature gate.
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 42e929bde2c..4bfe6be5493 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -45,14 +45,13 @@ impl DebuggerVisualizerCollector<'_> {
                     }
                 };
 
-            let file =
-                match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) {
-                    Ok(file) => file,
-                    Err(err) => {
-                        err.emit();
-                        return;
-                    }
-                };
+            let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) {
+                Ok(file) => file,
+                Err(err) => {
+                    err.emit();
+                    return;
+                }
+            };
 
             match std::fs::read(&file) {
                 Ok(contents) => {
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index ed26b45a936..a9d0e0d2dd3 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -135,7 +135,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
             if main_def.is_import && !tcx.features().imported_main {
                 let span = main_def.span;
                 feature_err(
-                    &tcx.sess.parse_sess,
+                    &tcx.sess,
                     sym::imported_main,
                     span,
                     "using an imported function as entry point `main` is experimental",
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index c2392620cb2..ff29fc5929c 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -341,6 +341,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         record_variants!(
             (self, t, t.kind, Id::Node(t.hir_id), hir, Ty, TyKind),
             [
+                InferDelegation,
                 Slice,
                 Array,
                 Ptr,
@@ -521,7 +522,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
                 TraitAlias,
                 Impl,
                 MacCall,
-                MacroDef
+                MacroDef,
+                Delegation
             ]
         );
         ast_visit::walk_item(self, i)
@@ -645,7 +647,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]
+            [Const, Fn, Type, MacCall, Delegation]
         );
         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 647f4d0e084..6aeaa8945fb 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -271,7 +271,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
             ast::ItemKind::Use(_) => Target::Use,
             ast::ItemKind::Static(_) => Target::Static,
             ast::ItemKind::Const(_) => Target::Const,
-            ast::ItemKind::Fn(_) => Target::Fn,
+            ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn,
             ast::ItemKind::Mod(_, _) => Target::Mod,
             ast::ItemKind::ForeignMod(_) => Target::ForeignFn,
             ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm,
@@ -315,24 +315,29 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
 
     fn visit_assoc_item(&mut self, i: &'ast ast::AssocItem, ctxt: visit::AssocCtxt) {
         let (target, generics) = match &i.kind {
-            ast::AssocItemKind::Fn(fun) => (
-                match &self.parent_item.unwrap().kind {
-                    ast::ItemKind::Impl(i) => {
-                        if i.of_trait.is_some() {
-                            Target::Method(MethodKind::Trait { body: fun.body.is_some() })
-                        } else {
-                            Target::Method(MethodKind::Inherent)
+            ast::AssocItemKind::Fn(..) | ast::AssocItemKind::Delegation(..) => {
+                let (body, generics) = if let ast::AssocItemKind::Fn(fun) = &i.kind {
+                    (fun.body.is_some(), Some(&fun.generics))
+                } else {
+                    (true, None)
+                };
+                (
+                    match &self.parent_item.unwrap().kind {
+                        ast::ItemKind::Impl(i) => {
+                            if i.of_trait.is_some() {
+                                Target::Method(MethodKind::Trait { body })
+                            } else {
+                                Target::Method(MethodKind::Inherent)
+                            }
                         }
-                    }
-                    ast::ItemKind::Trait(_) => {
-                        Target::Method(MethodKind::Trait { body: fun.body.is_some() })
-                    }
-                    _ => unreachable!(),
-                },
-                &fun.generics,
-            ),
-            ast::AssocItemKind::Const(ct) => (Target::AssocConst, &ct.generics),
-            ast::AssocItemKind::Type(ty) => (Target::AssocTy, &ty.generics),
+                        ast::ItemKind::Trait(_) => Target::Method(MethodKind::Trait { body }),
+                        _ => unreachable!(),
+                    },
+                    generics,
+                )
+            }
+            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"),
         };
 
@@ -341,7 +346,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
             self.resolver.node_id_to_def_id[&i.id],
             &i.attrs,
             i.span,
-            Some(generics),
+            generics,
         );
 
         visit::walk_assoc_item(self, i, ctxt);
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 9ccfde5e3c6..a4e2f9e3ff8 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -16,7 +16,7 @@ use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
-use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
+use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
 use rustc_attr as attr;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{struct_span_code_err, Applicability};
@@ -686,10 +686,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
 
             // These items live in the value namespace.
-            ItemKind::Static(..) => {
-                self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
-            }
-            ItemKind::Const(..) => {
+            ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => {
                 self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
             }
             ItemKind::Fn(..) => {
@@ -701,11 +698,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
 
             // These items live in the type namespace.
-            ItemKind::TyAlias(..) => {
+            ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => {
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
             }
 
-            ItemKind::Enum(_, _) => {
+            ItemKind::Enum(_, _) | ItemKind::Trait(..) => {
                 let module = self.r.new_module(
                     Some(parent),
                     ModuleKind::Def(def_kind, def_id, ident.name),
@@ -717,10 +714,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 self.parent_scope.module = module;
             }
 
-            ItemKind::TraitAlias(..) => {
-                self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
-            }
-
             // These items live in both the type and value namespaces.
             ItemKind::Struct(ref vdata, _) => {
                 // Define a name in the type namespace.
@@ -778,19 +771,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 self.insert_field_visibilities_local(def_id, vdata);
             }
 
-            ItemKind::Trait(..) => {
-                // Add all the items within to a new module.
-                let module = self.r.new_module(
-                    Some(parent),
-                    ModuleKind::Def(def_kind, def_id, ident.name),
-                    expansion.to_expn_id(),
-                    item.span,
-                    parent.no_implicit_prelude,
-                );
-                self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
-                self.parent_scope.module = module;
-            }
-
             // These items do not add names to modules.
             ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => {
                 self.r.trait_impl_items.insert(local_def_id);
@@ -1358,13 +1338,9 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
         if ctxt == AssocCtxt::Trait {
             let ns = match item.kind {
-                AssocItemKind::Const(..) => ValueNS,
-                AssocItemKind::Fn(box Fn { ref sig, .. }) => {
-                    if sig.decl.has_self() {
-                        self.r.has_self.insert(local_def_id);
-                    }
-                    ValueNS
-                }
+                AssocItemKind::Const(..)
+                | AssocItemKind::Delegation(..)
+                | AssocItemKind::Fn(..) => ValueNS,
                 AssocItemKind::Type(..) => TypeNS,
                 AssocItemKind::MacCall(_) => bug!(), // handled above
             };
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 02553d50071..b77102c085c 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -111,7 +111,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             ItemKind::TyAlias(..) => DefKind::TyAlias,
             ItemKind::Static(s) => DefKind::Static(s.mutability),
             ItemKind::Const(..) => DefKind::Const,
-            ItemKind::Fn(..) => DefKind::Fn,
+            ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
             ItemKind::MacroDef(..) => {
                 let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
                 let macro_kind = macro_data.ext.macro_kind();
@@ -259,7 +259,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
         let def_kind = match &i.kind {
-            AssocItemKind::Fn(..) => DefKind::AssocFn,
+            AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn,
             AssocItemKind::Const(..) => DefKind::AssocConst,
             AssocItemKind::Type(..) => DefKind::AssocTy,
             AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 0d744238eeb..b5700661385 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -786,7 +786,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
                 self.dcx().create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
             }
-            ResolutionError::FailedToResolve { last_segment, label, suggestion, module } => {
+            ResolutionError::FailedToResolve { segment, label, suggestion, module } => {
                 let mut err =
                     struct_span_code_err!(self.dcx(), span, E0433, "failed to resolve: {}", &label);
                 err.span_label(span, label);
@@ -801,9 +801,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
                 if let Some(ModuleOrUniformRoot::Module(module)) = module
                     && let Some(module) = module.opt_def_id()
-                    && let Some(last_segment) = last_segment
+                    && let Some(segment) = segment
                 {
-                    self.find_cfg_stripped(&mut err, &last_segment, module);
+                    self.find_cfg_stripped(&mut err, &segment, module);
                 }
 
                 err
@@ -981,12 +981,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
             VisResolutionError::FailedToResolve(span, label, suggestion) => self.into_struct_error(
                 span,
-                ResolutionError::FailedToResolve {
-                    last_segment: None,
-                    label,
-                    suggestion,
-                    module: None,
-                },
+                ResolutionError::FailedToResolve { segment: None, label, suggestion, module: None },
             ),
             VisResolutionError::ExpectedFound(span, path_str, res) => {
                 self.dcx().create_err(errs::ExpectedFound { span, res, path_str })
@@ -2450,7 +2445,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     pub(crate) fn find_cfg_stripped(
         &mut self,
         err: &mut Diagnostic,
-        last_segment: &Symbol,
+        segment: &Symbol,
         module: DefId,
     ) {
         let local_items;
@@ -2469,7 +2464,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         };
 
         for &StrippedCfgItem { parent_module, name, ref cfg } in symbols {
-            if parent_module != module || name.name != *last_segment {
+            if parent_module != module || name.name != *segment {
                 continue;
             }
 
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 50352169221..3443bbe6e11 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -277,7 +277,8 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't
             | ast::ItemKind::TraitAlias(..)
             | ast::ItemKind::MacroDef(..)
             | ast::ItemKind::ForeignMod(..)
-            | ast::ItemKind::Fn(..) => return,
+            | ast::ItemKind::Fn(..)
+            | ast::ItemKind::Delegation(..) => return,
         }
     }
 }
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 3a31addb109..7fb9db16e9c 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1381,13 +1381,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             continue;
                         }
                     }
-                    return PathResult::failed(
-                        ident.span,
-                        false,
-                        finalize.is_some(),
-                        module,
-                        || ("there are too many leading `super` keywords".to_string(), None),
-                    );
+                    return PathResult::failed(ident, false, finalize.is_some(), module, || {
+                        ("there are too many leading `super` keywords".to_string(), None)
+                    });
                 }
                 if segment_idx == 0 {
                     if name == kw::SelfLower {
@@ -1419,7 +1415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             // Report special messages for path segment keywords in wrong positions.
             if ident.is_path_segment_keyword() && segment_idx != 0 {
-                return PathResult::failed(ident.span, false, finalize.is_some(), module, || {
+                return PathResult::failed(ident, false, finalize.is_some(), module, || {
                     let name_str = if name == kw::PathRoot {
                         "crate root".to_string()
                     } else {
@@ -1515,7 +1511,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         ));
                     } else {
                         return PathResult::failed(
-                            ident.span,
+                            ident,
                             is_last,
                             finalize.is_some(),
                             module,
@@ -1541,24 +1537,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         }
                     }
 
-                    return PathResult::failed(
-                        ident.span,
-                        is_last,
-                        finalize.is_some(),
-                        module,
-                        || {
-                            self.report_path_resolution_error(
-                                path,
-                                opt_ns,
-                                parent_scope,
-                                ribs,
-                                ignore_binding,
-                                module,
-                                segment_idx,
-                                ident,
-                            )
-                        },
-                    );
+                    return PathResult::failed(ident, is_last, finalize.is_some(), module, || {
+                        self.report_path_resolution_error(
+                            path,
+                            opt_ns,
+                            parent_scope,
+                            ribs,
+                            ignore_binding,
+                            module,
+                            segment_idx,
+                            ident,
+                        )
+                    });
                 }
             }
         }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 2ebf4c20562..f846dbec2c6 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -886,6 +886,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             PathResult::Failed {
                 is_error_from_last_segment: false,
                 span,
+                segment_name,
                 label,
                 suggestion,
                 module,
@@ -895,7 +896,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     self.report_error(
                         span,
                         ResolutionError::FailedToResolve {
-                            last_segment: None,
+                            segment: Some(segment_name),
                             label,
                             suggestion,
                             module,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 4a3c8dfe3d7..82f50227911 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -394,13 +394,18 @@ pub(crate) enum PathSource<'a> {
     TupleStruct(Span, &'a [Span]),
     // `m::A::B` in `<T as m::A>::B::C`.
     TraitItem(Namespace),
+    // Paths in delegation item
+    Delegation,
 }
 
 impl<'a> PathSource<'a> {
     fn namespace(self) -> Namespace {
         match self {
             PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
-            PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(..) => ValueNS,
+            PathSource::Expr(..)
+            | PathSource::Pat
+            | PathSource::TupleStruct(..)
+            | PathSource::Delegation => ValueNS,
             PathSource::TraitItem(ns) => ns,
         }
     }
@@ -412,7 +417,7 @@ impl<'a> PathSource<'a> {
             | PathSource::Pat
             | PathSource::Struct
             | PathSource::TupleStruct(..) => true,
-            PathSource::Trait(_) | PathSource::TraitItem(..) => false,
+            PathSource::Trait(_) | PathSource::TraitItem(..) | PathSource::Delegation => false,
         }
     }
 
@@ -454,6 +459,7 @@ impl<'a> PathSource<'a> {
                 },
                 _ => "value",
             },
+            PathSource::Delegation => "function",
         }
     }
 
@@ -521,6 +527,7 @@ impl<'a> PathSource<'a> {
                 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
                 _ => false,
             },
+            PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
         }
     }
 
@@ -533,8 +540,8 @@ impl<'a> PathSource<'a> {
             (PathSource::Type, false) => error_code!(E0412),
             (PathSource::Struct, true) => error_code!(E0574),
             (PathSource::Struct, false) => error_code!(E0422),
-            (PathSource::Expr(..), true) => error_code!(E0423),
-            (PathSource::Expr(..), false) => error_code!(E0425),
+            (PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423),
+            (PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425),
             (PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532),
             (PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531),
             (PathSource::TraitItem(..), true) => error_code!(E0575),
@@ -1805,7 +1812,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 PathSource::Expr(..)
                 | PathSource::Pat
                 | PathSource::Struct
-                | PathSource::TupleStruct(..) => true,
+                | PathSource::TupleStruct(..)
+                | PathSource::Delegation => true,
             };
             if inferred {
                 // Do not create a parameter for patterns and expressions: type checking can infer
@@ -2514,6 +2522,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 visit::walk_item(self, item);
             }
 
+            ItemKind::Delegation(ref delegation) => {
+                self.resolve_delegation(delegation);
+            }
+
             ItemKind::ExternCrate(..) => {}
 
             ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
@@ -2790,6 +2802,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 AssocItemKind::Fn(box Fn { generics, .. }) => {
                     walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
                 }
+                AssocItemKind::Delegation(delegation) => {
+                    self.resolve_delegation(delegation);
+                }
                 AssocItemKind::Type(box TyAlias { generics, .. }) => self
                     .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
                         walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
@@ -3036,6 +3051,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     },
                 );
             }
+            AssocItemKind::Delegation(box delegation) => {
+                debug!("resolve_implementation AssocItemKind::Delegation");
+                self.check_trait_item(
+                    item.id,
+                    item.ident,
+                    &item.kind,
+                    ValueNS,
+                    item.span,
+                    seen_trait_items,
+                    |i, s, c| MethodNotMemberOfTrait(i, s, c),
+                );
+                self.resolve_delegation(delegation);
+            }
             AssocItemKind::MacCall(_) => {
                 panic!("unexpanded macro in resolve!")
             }
@@ -3123,7 +3151,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         match (def_kind, kind) {
             (DefKind::AssocTy, AssocItemKind::Type(..))
             | (DefKind::AssocFn, AssocItemKind::Fn(..))
-            | (DefKind::AssocConst, AssocItemKind::Const(..)) => {
+            | (DefKind::AssocConst, AssocItemKind::Const(..))
+            | (DefKind::AssocFn, AssocItemKind::Delegation(..)) => {
                 self.r.record_partial_res(id, PartialRes::new(res));
                 return;
             }
@@ -3136,6 +3165,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"),
             AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"),
             AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"),
+            AssocItemKind::Delegation(..) => (rustc_errors::error_code!(E0324), "method"),
             AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
         };
         let trait_path = path_names_to_string(path);
@@ -3159,6 +3189,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         })
     }
 
+    fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
+        self.smart_resolve_path(
+            delegation.id,
+            &delegation.qself,
+            &delegation.path,
+            PathSource::Delegation,
+        );
+        if let Some(qself) = &delegation.qself {
+            self.visit_ty(&qself.ty);
+        }
+        self.visit_path(&delegation.path, delegation.id);
+        if let Some(body) = &delegation.body {
+            // `PatBoundCtx` is not necessary in this context
+            let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
+
+            let span = delegation.path.segments.last().unwrap().ident.span;
+            self.fresh_binding(
+                Ident::new(kw::SelfLower, span),
+                delegation.id,
+                PatternSource::FnParam,
+                &mut bindings,
+            );
+            self.visit_block(body);
+        }
+    }
+
     fn resolve_params(&mut self, params: &'ast [Param]) {
         let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
         self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
@@ -3998,11 +4054,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 label,
                 suggestion,
                 module,
+                segment_name,
             } => {
                 return Err(respan(
                     span,
                     ResolutionError::FailedToResolve {
-                        last_segment: None,
+                        segment: Some(segment_name),
                         label,
                         suggestion,
                         module,
@@ -4551,13 +4608,24 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     }
 }
 
-struct LifetimeCountVisitor<'a, 'b, 'tcx> {
+/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
+/// lifetime generic parameters and function parameters.
+struct ItemInfoCollector<'a, 'b, 'tcx> {
     r: &'b mut Resolver<'a, 'tcx>,
 }
 
-/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
-/// lifetime generic parameters.
-impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
+impl ItemInfoCollector<'_, '_, '_> {
+    fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
+        let def_id = self.r.local_def_id(id);
+        self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len());
+
+        if sig.decl.has_self() {
+            self.r.has_self.insert(def_id);
+        }
+    }
+}
+
+impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
     fn visit_item(&mut self, item: &'ast Item) {
         match &item.kind {
             ItemKind::TyAlias(box TyAlias { ref generics, .. })
@@ -4569,6 +4637,10 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
             | ItemKind::Impl(box Impl { ref generics, .. })
             | ItemKind::Trait(box Trait { ref generics, .. })
             | ItemKind::TraitAlias(ref generics, _) => {
+                if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
+                    self.collect_fn_info(sig, item.id);
+                }
+
                 let def_id = self.r.local_def_id(item.id);
                 let count = generics
                     .params
@@ -4586,14 +4658,27 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
             | ItemKind::MacroDef(..)
             | ItemKind::GlobalAsm(..)
             | ItemKind::MacCall(..) => {}
+            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,
+                // it means there will be a panic when retrieving the count,
+                // but for delegation items we are never actually retrieving that count in practice.
+            }
         }
         visit::walk_item(self, item)
     }
+
+    fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
+        if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
+            self.collect_fn_info(sig, item.id);
+        }
+        visit::walk_assoc_item(self, item, ctxt);
+    }
 }
 
 impl<'a, 'tcx> Resolver<'a, 'tcx> {
     pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
-        visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate);
+        visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
         let mut late_resolution_visitor = LateResolutionVisitor::new(self);
         late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
         visit::walk_crate(&mut late_resolution_visitor, krate);
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 2f476ae6cbc..58ff4d8c793 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -656,7 +656,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         let typo_sugg = self
             .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
             .to_opt_suggestion();
-        if path.len() == 1 && self.self_type_is_available() {
+        if path.len() == 1
+            && !matches!(source, PathSource::Delegation)
+            && self.self_type_is_available()
+        {
             if let Some(candidate) =
                 self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call())
             {
@@ -1899,6 +1902,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 (AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true,
                 (AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true,
                 (AssocItemKind::Type(..), Res::Def(DefKind::AssocTy, _)) => true,
+                (AssocItemKind::Delegation(_), Res::Def(DefKind::AssocFn, _)) => true,
                 _ => false,
             })
             .map(|(key, _)| key.ident.name)
@@ -1960,6 +1964,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         }
                         ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
                         ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
+                        ast::AssocItemKind::Delegation(..)
+                            if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) =>
+                        {
+                            AssocSuggestion::MethodWithSelf { called }
+                        }
+                        ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called },
                         ast::AssocItemKind::MacCall(_) => continue,
                     });
                 }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index a14f3d494fb..90aa7d79bf0 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -213,7 +213,7 @@ enum ResolutionError<'a> {
     SelfImportOnlyInImportListWithNonEmptyPrefix,
     /// Error E0433: failed to resolve.
     FailedToResolve {
-        last_segment: Option<Symbol>,
+        segment: Option<Symbol>,
         label: String,
         suggestion: Option<Suggestion>,
         module: Option<ModuleOrUniformRoot<'a>>,
@@ -396,12 +396,14 @@ enum PathResult<'a> {
         suggestion: Option<Suggestion>,
         is_error_from_last_segment: bool,
         module: Option<ModuleOrUniformRoot<'a>>,
+        /// The segment name of target
+        segment_name: Symbol,
     },
 }
 
 impl<'a> PathResult<'a> {
     fn failed(
-        span: Span,
+        ident: Ident,
         is_error_from_last_segment: bool,
         finalize: bool,
         module: Option<ModuleOrUniformRoot<'a>>,
@@ -409,7 +411,14 @@ impl<'a> PathResult<'a> {
     ) -> PathResult<'a> {
         let (label, suggestion) =
             if finalize { label_and_suggestion() } else { (String::new(), None) };
-        PathResult::Failed { span, label, suggestion, is_error_from_last_segment, module }
+        PathResult::Failed {
+            span: ident.span,
+            segment_name: ident.name,
+            label,
+            suggestion,
+            is_error_from_last_segment,
+            module,
+        }
     }
 }
 
@@ -1101,6 +1110,8 @@ pub struct Resolver<'a, 'tcx> {
     legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
     /// Amount of lifetime parameters for each item in the crate.
     item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
+    /// Amount of parameters for each function in the crate.
+    fn_parameter_counts: LocalDefIdMap<usize>,
 
     main_def: Option<MainDefinition>,
     trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
@@ -1439,6 +1450,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             doc_link_resolutions: Default::default(),
             doc_link_traits_in_scope: Default::default(),
             all_macro_rules: Default::default(),
+            fn_parameter_counts: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1542,6 +1554,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             trait_map: self.trait_map,
             lifetime_elision_allowed: self.lifetime_elision_allowed,
             lint_buffer: Steal::new(self.lint_buffer),
+            has_self: self.has_self,
+            fn_parameter_counts: self.fn_parameter_counts,
         };
         ResolverOutputs { global_ctxt, ast_lowering }
     }
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 66ecaeb4449..1c085ddf57b 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -594,13 +594,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             if soft_custom_inner_attributes_gate {
                 self.tcx.sess.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
             } else {
-                feature_err(
-                    &self.tcx.sess.parse_sess,
-                    sym::custom_inner_attributes,
-                    path.span,
-                    msg,
-                )
-                .emit();
+                feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit();
             }
         }
 
@@ -779,7 +773,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     self.report_error(
                         span,
                         ResolutionError::FailedToResolve {
-                            last_segment: path.last().map(|segment| segment.ident.name),
+                            segment: path.last().map(|segment| segment.ident.name),
                             label,
                             suggestion,
                             module,
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index f2e646c70f5..53bdef6dfa0 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -24,6 +24,9 @@ session_feature_diagnostic_for_issue =
 session_feature_diagnostic_help =
     add `#![feature({$feature})]` to the crate attributes to enable
 
+session_feature_suggest_upgrade_compiler =
+    this compiler was built on {$date}; consider upgrading it if it is out of date
+
 session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
 
 session_file_write_fail = failed to write `{$path}` due to error `{$err}`
diff --git a/compiler/rustc_session/src/config/sigpipe.rs b/compiler/rustc_session/src/config/sigpipe.rs
index 53692ad7cc9..1fadc75cfd0 100644
--- a/compiler/rustc_session/src/config/sigpipe.rs
+++ b/compiler/rustc_session/src/config/sigpipe.rs
@@ -1,7 +1,7 @@
-//! NOTE: Keep these constants in sync with `library/std/src/sys/unix/mod.rs`!
+//! NOTE: Keep these constants in sync with `library/std/src/sys/pal/unix/mod.rs`!
 
 /// The default value if `#[unix_sigpipe]` is not specified. This resolves
-/// to `SIG_IGN` in `library/std/src/sys/unix/mod.rs`.
+/// to `SIG_IGN` in `library/std/src/sys/pal/unix/mod.rs`.
 ///
 /// Note that `SIG_IGN` has been the Rust default since 2014. See
 /// <https://github.com/rust-lang/rust/issues/62569>.
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index b672e760feb..21a206798af 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -1,6 +1,5 @@
 use std::num::NonZeroU32;
 
-use crate::parse::ParseSess;
 use rustc_ast::token;
 use rustc_ast::util::literal::LitError;
 use rustc_errors::{
@@ -10,6 +9,8 @@ use rustc_macros::Diagnostic;
 use rustc_span::{BytePos, Span, Symbol};
 use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
 
+use crate::parse::ParseSess;
+
 pub struct FeatureGateError {
     pub span: MultiSpan,
     pub explain: DiagnosticMessage,
@@ -31,6 +32,24 @@ pub struct FeatureDiagnosticForIssue {
 }
 
 #[derive(Subdiagnostic)]
+#[note(session_feature_suggest_upgrade_compiler)]
+pub struct SuggestUpgradeCompiler {
+    date: &'static str,
+}
+
+impl SuggestUpgradeCompiler {
+    pub fn ui_testing() -> Self {
+        Self { date: "YYYY-MM-DD" }
+    }
+
+    pub fn new() -> Option<Self> {
+        let date = option_env!("CFG_VER_DATE")?;
+
+        Some(Self { date })
+    }
+}
+
+#[derive(Subdiagnostic)]
 #[help(session_feature_diagnostic_help)]
 pub struct FeatureDiagnosticHelp {
     pub feature: Symbol,
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 598178c3c2a..c629c9884c8 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -4,10 +4,12 @@
 use crate::config::{Cfg, CheckCfg};
 use crate::errors::{
     CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError,
+    SuggestUpgradeCompiler,
 };
 use crate::lint::{
     builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
 };
+use crate::Session;
 use rustc_ast::node_id::NodeId;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
@@ -75,11 +77,12 @@ impl SymbolGallery {
     }
 }
 
+// todo: this function now accepts `Session` instead of `ParseSess` and should be relocated
 /// Construct a diagnostic for a language feature error due to the given `span`.
 /// The `feature`'s `Symbol` is the one you used in `unstable.rs` and `rustc_span::symbols`.
 #[track_caller]
 pub fn feature_err(
-    sess: &ParseSess,
+    sess: &Session,
     feature: Symbol,
     span: impl Into<MultiSpan>,
     explain: impl Into<DiagnosticMessage>,
@@ -93,7 +96,7 @@ pub fn feature_err(
 /// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
 #[track_caller]
 pub fn feature_err_issue(
-    sess: &ParseSess,
+    sess: &Session,
     feature: Symbol,
     span: impl Into<MultiSpan>,
     issue: GateIssue,
@@ -103,12 +106,14 @@ pub fn feature_err_issue(
 
     // Cancel an earlier warning for this same error, if it exists.
     if let Some(span) = span.primary_span() {
-        if let Some(err) = sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning) {
+        if let Some(err) = sess.parse_sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning)
+        {
             err.cancel()
         }
     }
 
-    let mut err = sess.dcx.create_err(FeatureGateError { span, explain: explain.into() });
+    let mut err =
+        sess.parse_sess.dcx.create_err(FeatureGateError { span, explain: explain.into() });
     add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
     err
 }
@@ -117,7 +122,7 @@ pub fn feature_err_issue(
 ///
 /// This diagnostic is only a warning and *does not cause compilation to fail*.
 #[track_caller]
-pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) {
+pub fn feature_warn(sess: &Session, feature: Symbol, span: Span, explain: &'static str) {
     feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
 }
 
@@ -131,13 +136,13 @@ pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'st
 #[allow(rustc::untranslatable_diagnostic)]
 #[track_caller]
 pub fn feature_warn_issue(
-    sess: &ParseSess,
+    sess: &Session,
     feature: Symbol,
     span: Span,
     issue: GateIssue,
     explain: &'static str,
 ) {
-    let mut err = sess.dcx.struct_span_warn(span, explain);
+    let mut err = sess.parse_sess.dcx.struct_span_warn(span, explain);
     add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
 
     // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
@@ -152,7 +157,7 @@ pub fn feature_warn_issue(
 }
 
 /// Adds the diagnostics for a feature to an existing error.
-pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature: Symbol) {
+pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &Session, feature: Symbol) {
     add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false);
 }
 
@@ -163,7 +168,7 @@ pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature:
 /// `add_feature_diagnostics`.
 pub fn add_feature_diagnostics_for_issue(
     err: &mut Diagnostic,
-    sess: &ParseSess,
+    sess: &Session,
     feature: Symbol,
     issue: GateIssue,
     feature_from_cli: bool,
@@ -173,12 +178,18 @@ pub fn add_feature_diagnostics_for_issue(
     }
 
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
-    if sess.unstable_features.is_nightly_build() {
+    if sess.parse_sess.unstable_features.is_nightly_build() {
         if feature_from_cli {
             err.subdiagnostic(CliFeatureDiagnosticHelp { feature });
         } else {
             err.subdiagnostic(FeatureDiagnosticHelp { feature });
         }
+
+        if sess.opts.unstable_opts.ui_testing {
+            err.subdiagnostic(SuggestUpgradeCompiler::ui_testing());
+        } else if let Some(suggestion) = SuggestUpgradeCompiler::new() {
+            err.subdiagnostic(suggestion);
+        }
     }
 }
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 210dc9e0145..1c3d5a3cb88 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -318,7 +318,7 @@ impl Session {
         if err.code.is_none() {
             err.code(error_code!(E0658));
         }
-        add_feature_diagnostics(&mut err, &self.parse_sess, feature);
+        add_feature_diagnostics(&mut err, self, feature);
         err
     }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8ed1255c010..72b62a795fc 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -102,6 +102,7 @@ symbols! {
         Gen:                "gen",
         MacroRules:         "macro_rules",
         Raw:                "raw",
+        Reuse:              "reuse",
         Union:              "union",
         Yeet:               "yeet",
     }
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index fafc10e7163..1c83039047e 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -840,7 +840,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "sparc" => sparc::compute_abi_info(cx, self),
             "sparc64" => sparc64::compute_abi_info(cx, self),
             "nvptx64" => {
-                if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::PtxKernel {
+                if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::PtxKernel {
                     nvptx64::compute_ptx_kernel_abi_info(cx, self)
                 } else {
                     nvptx64::compute_abi_info(self)
@@ -849,7 +849,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "hexagon" => hexagon::compute_abi_info(self),
             "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
             "wasm32" | "wasm64" => {
-                if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm {
+                if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::Wasm {
                     wasm::compute_wasm_abi_info(self)
                 } else {
                     wasm::compute_c_abi_info(cx, self)
diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs
index 4c1f0c01a04..1a0aa6f0c4a 100644
--- a/compiler/rustc_target/src/spec/abi/mod.rs
+++ b/compiler/rustc_target/src/spec/abi/mod.rs
@@ -70,15 +70,16 @@ impl Abi {
         // * C and Cdecl obviously support varargs.
         // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs.
         // * EfiApi is based on Win64 or C, so it also supports it.
+        // * System falls back to C for functions with varargs.
         //
         // * Stdcall does not, because it would be impossible for the callee to clean
         //   up the arguments. (callee doesn't know how many arguments are there)
         // * Same for Fastcall, Vectorcall and Thiscall.
-        // * System can become Stdcall, so is also a no-no.
         // * Other calling conventions are related to hardware or the compiler itself.
         match self {
             Self::C { .. }
             | Self::Cdecl { .. }
+            | Self::System { .. }
             | Self::Aapcs { .. }
             | Self::Win64 { .. }
             | Self::SysV64 { .. }
diff --git a/compiler/rustc_target/src/spec/base/illumos.rs b/compiler/rustc_target/src/spec/base/illumos.rs
index e63e789752b..f0a648b93ad 100644
--- a/compiler/rustc_target/src/spec/base/illumos.rs
+++ b/compiler/rustc_target/src/spec/base/illumos.rs
@@ -39,7 +39,7 @@ pub fn opts() -> TargetOptions {
         // While we support ELF TLS, rust requires a way to register
         // cleanup handlers (in C, this would be something along the lines of:
         // void register_callback(void (*fn)(void *), void *arg);
-        // (see src/libstd/sys/unix/fast_thread_local.rs) that is currently
+        // (see src/libstd/sys/pal/unix/fast_thread_local.rs) that is currently
         // missing in illumos. For now at least, we must fallback to using
         // pthread_{get,set}specific.
         //has_thread_local: true,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index da8706ea715..5d74ebebdf3 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2401,10 +2401,14 @@ impl DerefMut for Target {
 
 impl Target {
     /// Given a function ABI, turn it into the correct ABI for this target.
-    pub fn adjust_abi(&self, abi: Abi) -> Abi {
+    pub fn adjust_abi(&self, abi: Abi, c_variadic: bool) -> Abi {
         match abi {
             Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi),
-            Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => {
+
+            // On Windows, `extern "system"` behaves like msvc's `__stdcall`.
+            // `__stdcall` only applies on x86 and on non-variadic functions:
+            // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
+            Abi::System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => {
                 Abi::Stdcall { unwind }
             }
             Abi::System { unwind } => Abi::C { unwind },
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 100c9a70aaa..532e2cb36e3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -408,7 +408,7 @@ impl<'tcx> OnUnimplementedDirective {
                 .ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))?
                 .meta_item()
                 .ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
-            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
+            attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| {
                 if let Some(value) = cfg.value
                     && let Err(guar) = parse_value(value, cfg.span)
                 {
@@ -682,31 +682,22 @@ impl<'tcx> OnUnimplementedDirective {
 
         for command in self.subcommands.iter().chain(Some(self)).rev() {
             if let Some(ref condition) = command.condition
-                && !attr::eval_condition(
-                    condition,
-                    &tcx.sess.parse_sess,
-                    Some(tcx.features()),
-                    &mut |cfg| {
-                        let value = cfg.value.map(|v| {
-                            // `with_no_visible_paths` is also used when generating the options,
-                            // so we need to match it here.
-                            ty::print::with_no_visible_paths!(
-                                OnUnimplementedFormatString {
-                                    symbol: v,
-                                    span: cfg.span,
-                                    is_diagnostic_namespace_variant: false
-                                }
-                                .format(
-                                    tcx,
-                                    trait_ref,
-                                    &options_map
-                                )
-                            )
-                        });
-
-                        options.contains(&(cfg.name, value))
-                    },
-                )
+                && !attr::eval_condition(condition, &tcx.sess, Some(tcx.features()), &mut |cfg| {
+                    let value = cfg.value.map(|v| {
+                        // `with_no_visible_paths` is also used when generating the options,
+                        // so we need to match it here.
+                        ty::print::with_no_visible_paths!(
+                            OnUnimplementedFormatString {
+                                symbol: v,
+                                span: cfg.span,
+                                is_diagnostic_namespace_variant: false
+                            }
+                            .format(tcx, trait_ref, &options_map)
+                        )
+                    });
+
+                    options.contains(&(cfg.name, value))
+                })
             {
                 debug!("evaluate: skipping {:?} due to condition", command);
                 continue;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 47a700805fa..b970ec7f726 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -947,9 +947,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             Overflow(_) => {
                 bug!("overflow should be handled before the `report_selection_error` path");
             }
-            SelectionError::ErrorReporting => {
-                bug!("ErrorReporting Overflow should not reach `report_selection_err` call")
-            }
         };
 
         self.note_obligation_cause(&mut err, &obligation);
@@ -3459,14 +3456,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
         let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
 
-        if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
+        if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) {
             // We check closures twice, with obligations flowing in different directions,
             // but we want to complain about them only once.
             return None;
         }
 
-        self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
-
         let mut not_tupled = false;
 
         let found = match found_trait_ref.skip_binder().args.type_at(1).kind() {
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index 31e34096fb0..4c0c57377e0 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -116,11 +116,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
                             r,
                         )
                     }
-                    OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr,
                     OverflowError::Error(_) => EvaluationResult::EvaluatedToErr,
                 })
             }
-            Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr,
             Err(OverflowError::Error(_)) => EvaluationResult::EvaluatedToErr,
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 61fe2c8efe3..6a6adcbb680 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -14,9 +14,9 @@ use super::util;
 use super::util::closure_trait_ref_and_return_type;
 use super::wf;
 use super::{
-    ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation,
-    ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation,
-    Selection, SelectionError, SelectionResult, TraitQueryMode,
+    ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation, ObligationCause,
+    ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, Selection,
+    SelectionError, SelectionResult, TraitQueryMode,
 };
 
 use crate::infer::{InferCtxt, InferOk, TypeFreshener};
@@ -496,7 +496,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 }
                 Ok(_) => Ok(None),
                 Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)),
-                Err(OverflowError::ErrorReporting) => Err(ErrorReporting),
                 Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))),
             })
             .flat_map(Result::transpose)
@@ -1233,7 +1232,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             Ok(Some(c)) => self.evaluate_candidate(stack, &c),
             Ok(None) => Ok(EvaluatedToAmbig),
             Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
-            Err(ErrorReporting) => Err(OverflowError::ErrorReporting),
             Err(..) => Ok(EvaluatedToErr),
         }
     }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 2772831e731..6e8293dac31 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -228,9 +228,9 @@ fn fn_sig_for_fn_abi<'tcx>(
 }
 
 #[inline]
-fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
+fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv {
     use rustc_target::spec::abi::Abi::*;
-    match tcx.sess.target.adjust_abi(abi) {
+    match tcx.sess.target.adjust_abi(abi, c_variadic) {
         RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust,
 
         // This is intentionally not using `Conv::Cold`, as that has to preserve
@@ -488,7 +488,7 @@ fn fn_abi_new_uncached<'tcx>(
 ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
     let sig = cx.tcx.normalize_erasing_late_bound_regions(cx.param_env, sig);
 
-    let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
+    let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);
 
     let mut inputs = sig.inputs();
     let extra_args = if sig.abi == RustCall {