about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-24 11:57:35 +0000
committerbors <bors@rust-lang.org>2024-04-24 11:57:35 +0000
commit5557f8c9d08d7f3f680943dcf97b6d4a7eb13aea (patch)
tree846484bd65fa87e206d8a01e1d98e58efb13f430 /compiler
parente9362896e0eaaa86372b8ee2634b5761dd9e5ab7 (diff)
parent7b7c26f09bbc292da8600e8dfaa454de63ada886 (diff)
Auto merge of #122500 - petrochenkov:deleg, r=fmease
delegation: Support renaming, and async, const, extern "ABI" and C-variadic functions

Also allow delegating to functions with opaque types (`impl Trait`).
The delegation item will refer to the original opaque type from the callee, fresh opaque type won't be created, which seems like a reasonable behavior.
(Such delegation items will cause query cycles when used in trait impls, but it can be fixed later.)

Part of https://github.com/rust-lang/rust/issues/118212.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs1
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs10
-rw-r--r--compiler/rustc_ast/src/visit.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs117
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs28
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs13
-rw-r--r--compiler/rustc_parse/src/parser/item.rs10
-rw-r--r--compiler/rustc_resolve/src/late.rs14
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs7
-rw-r--r--compiler/rustc_resolve/src/lib.rs16
11 files changed, 124 insertions, 100 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index bddb50568d4..727c6bc82fe 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3112,6 +3112,7 @@ pub struct Delegation {
     /// Path resolution id.
     pub id: NodeId,
     pub qself: Option<P<QSelf>>,
+    pub rename: Option<Ident>,
     pub path: Path,
     pub body: Option<P<Block>>,
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index c4e49d7dbea..7dbfb7c7364 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1149,10 +1149,13 @@ 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 }) => {
+        ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             vis.visit_id(id);
             vis.visit_qself(qself);
             vis.visit_path(path);
+            if let Some(rename) = rename {
+                vis.visit_ident(rename);
+            }
             if let Some(body) = body {
                 vis.visit_block(body);
             }
@@ -1195,10 +1198,13 @@ 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 }) => {
+        AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             visitor.visit_id(id);
             visitor.visit_qself(qself);
             visitor.visit_path(path);
+            if let Some(rename) = rename {
+                visitor.visit_ident(rename);
+            }
             if let Some(body) = body {
                 visitor.visit_block(body);
             }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 968d10ad487..d9740928f8d 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -382,11 +382,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Resu
         }
         ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
         ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)),
-        ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             if let Some(qself) = qself {
                 try_visit!(visitor.visit_ty(&qself.ty));
             }
             try_visit!(visitor.visit_path(path, *id));
+            visit_opt!(visitor, visit_ident, *rename);
             visit_opt!(visitor, visit_block, body);
         }
     }
@@ -782,11 +783,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
         AssocItemKind::MacCall(mac) => {
             try_visit!(visitor.visit_mac_call(mac));
         }
-        AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
+        AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
             if let Some(qself) = qself {
                 try_visit!(visitor.visit_ty(&qself.ty));
             }
             try_visit!(visitor.visit_path(path, *id));
+            visit_opt!(visitor, visit_ident, *rename);
             visit_opt!(visitor, visit_block, body);
         }
     }
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index f4d5e71bade..a1e5c275c18 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -49,7 +49,7 @@ 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_middle::ty::{Asyncness, ResolverAstLowering};
 use rustc_span::{symbol::Ident, Span};
 use rustc_target::spec::abi;
 use std::iter;
@@ -67,7 +67,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             return false;
         };
         if let Some(local_sig_id) = sig_id.as_local() {
-            self.resolver.has_self.contains(&local_sig_id)
+            self.resolver.delegation_fn_sigs[&local_sig_id].has_self
         } else {
             match self.tcx.def_kind(sig_id) {
                 DefKind::Fn => false,
@@ -82,13 +82,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         delegation: &Delegation,
         item_id: NodeId,
     ) -> DelegationResults<'hir> {
-        let span = delegation.path.segments.last().unwrap().ident.span;
+        let span = self.lower_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 (param_count, c_variadic) = self.param_count(sig_id);
+                let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
+                let sig = self.lower_delegation_sig(sig_id, decl, span);
+                let body_id = self.lower_delegation_body(delegation, param_count, span);
 
                 let generics = self.lower_delegation_generics(span);
                 DelegationResults { body_id, sig, generics }
@@ -123,34 +124,47 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
+    // Function parameter count, including C variadic `...` if present.
+    fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) {
+        if let Some(local_sig_id) = sig_id.as_local() {
+            // Map may be filled incorrectly due to recursive delegation.
+            // Error will be emmited later during HIR ty lowering.
+            match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
+                Some(sig) => (sig.param_count, sig.c_variadic),
+                None => (0, false),
+            }
+        } else {
+            let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
+            (sig.inputs().len() + usize::from(sig.c_variadic), sig.c_variadic)
+        }
+    }
+
     fn lower_delegation_decl(
         &mut self,
         sig_id: DefId,
-        param_span: Span,
+        param_count: usize,
+        c_variadic: bool,
+        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 emitted later during HIR ty lowering.
-            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).map(|arg| hir::Ty {
+        // The last parameter in C variadic functions is skipped in the signature,
+        // like during regular lowering.
+        let decl_param_count = param_count - c_variadic as usize;
+        let inputs = self.arena.alloc_from_iter((0..decl_param_count).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),
+            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),
+            span,
         });
 
         self.arena.alloc(hir::FnDecl {
             inputs,
             output: hir::FnRetTy::Return(output),
-            c_variadic: false,
+            c_variadic,
             lifetime_elision_allowed: true,
             implicit_self: hir::ImplicitSelfKind::None,
         })
@@ -158,35 +172,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_delegation_sig(
         &mut self,
-        span: Span,
+        sig_id: DefId,
         decl: &'hir hir::FnDecl<'hir>,
+        span: Span,
     ) -> 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),
-        }
+        let header = if let Some(local_sig_id) = sig_id.as_local() {
+            match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
+                Some(sig) => self.lower_fn_header(sig.header),
+                None => self.generate_header_error(),
+            }
+        } else {
+            let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
+            let asyncness = match self.tcx.asyncness(sig_id) {
+                Asyncness::Yes => hir::IsAsync::Async(span),
+                Asyncness::No => hir::IsAsync::NotAsync,
+            };
+            hir::FnHeader {
+                unsafety: sig.unsafety,
+                constness: self.tcx.constness(sig_id),
+                asyncness,
+                abi: sig.abi,
+            }
+        };
+        hir::FnSig { decl, header, span }
     }
 
-    fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
+    fn generate_param(&mut self, span: Span) -> (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::BindingMode::NONE, pat_id, Ident::empty(), None),
-            span: ty.span,
+            span,
             default_binding_modes: false,
         });
 
-        (hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
+        (hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id)
     }
 
-    fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
+    fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> {
         let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
             ident: Ident::empty(),
             hir_id: self.next_id(),
@@ -195,20 +219,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
             infer_args: false,
         }));
 
-        let path =
-            self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
+        let path = self.arena.alloc(hir::Path { 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,
+            span,
         }
     }
 
     fn lower_delegation_body(
         &mut self,
-        decl: &'hir hir::FnDecl<'hir>,
         delegation: &Delegation,
+        param_count: usize,
+        span: Span,
     ) -> BodyId {
         let path = self.lower_qpath(
             delegation.id,
@@ -224,8 +248,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             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);
+            for idx in 0..param_count {
+                let (param, pat_node_id) = this.generate_param(span);
                 parameters.push(param);
 
                 let arg = if let Some(block) = block
@@ -245,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                 } else {
                     let pat_hir_id = this.lower_node_id(pat_node_id);
-                    this.generate_arg(param_ty, pat_hir_id)
+                    this.generate_arg(pat_hir_id, span)
                 };
                 args.push(arg);
             }
@@ -304,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             implicit_self: hir::ImplicitSelfKind::None,
         });
 
-        let sig = self.lower_delegation_sig(span, decl);
+        let header = self.generate_header_error();
+        let sig = hir::FnSig { decl, header, span };
+
         let body_id = self.lower_body(|this| {
             let expr =
                 hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
@@ -312,6 +338,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
         });
         DelegationResults { generics, body_id, sig }
     }
+
+    fn generate_header_error(&self) -> hir::FnHeader {
+        hir::FnHeader {
+            unsafety: hir::Unsafety::Normal,
+            constness: hir::Constness::NotConst,
+            asyncness: hir::IsAsync::NotAsync,
+            abi: abi::Abi::Rust,
+        }
+    }
 }
 
 struct SelfResolver<'a> {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 1d52b4107d7..dcce54d66c2 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1344,7 +1344,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
 
-    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+    pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
         let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
             hir::IsAsync::Async(span)
         } else {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 4a0df6cf7b8..63da27246a2 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1964,11 +1964,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             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);
@@ -1991,29 +1986,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             try_emit("delegation to a trait method from a free function");
         }
 
-        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
     }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index cc026e349d7..cda332aee56 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -45,7 +45,7 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{Diag, 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, LocalDefIdSet};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
 use rustc_index::IndexVec;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
@@ -224,8 +224,15 @@ pub struct ResolverAstLowering {
     pub lint_buffer: Steal<LintBuffer>,
 
     /// Information about functions signatures for delegation items expansion
-    pub has_self: LocalDefIdSet,
-    pub fn_parameter_counts: LocalDefIdMap<usize>,
+    pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
+}
+
+#[derive(Debug)]
+pub struct DelegationFnSig {
+    pub header: ast::FnHeader,
+    pub param_count: usize,
+    pub has_self: bool,
+    pub c_variadic: bool,
 }
 
 #[derive(Clone, Copy, Debug)]
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 84ecd0a0de5..ed51710564a 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -686,6 +686,8 @@ impl<'a> Parser<'a> {
             (None, self.parse_path(PathStyle::Expr)?)
         };
 
+        let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None };
+
         let body = if self.check(&token::OpenDelim(Delimiter::Brace)) {
             Some(self.parse_block()?)
         } else {
@@ -695,11 +697,9 @@ impl<'a> Parser<'a> {
         let span = span.to(self.prev_token.span);
         self.psess.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 })),
-        ))
+        let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
+        let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body };
+        Ok((ident, ItemKind::Delegation(Box::new(deleg))))
     }
 
     fn parse_item_list<T>(
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index c877ae5e21f..292af43b602 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -21,6 +21,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_bound_vars::Set1;
+use rustc_middle::ty::DelegationFnSig;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
 use rustc_session::lint;
@@ -4749,12 +4750,13 @@ struct ItemInfoCollector<'a, 'b, 'tcx> {
 
 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);
-        }
+        let sig = DelegationFnSig {
+            header: sig.header,
+            param_count: sig.decl.inputs.len(),
+            has_self: sig.decl.has_self(),
+            c_variadic: sig.decl.c_variadic(),
+        };
+        self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
     }
 }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index d79c638fa07..64451030adf 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2039,7 +2039,8 @@ 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)) =>
+                            if self.r.delegation_fn_sigs[&self.r.local_def_id(assoc_item.id)]
+                                .has_self =>
                         {
                             AssocSuggestion::MethodWithSelf { called }
                         }
@@ -2062,7 +2063,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 if filter_fn(res) {
                     let def_id = res.def_id();
                     let has_self = match def_id.as_local() {
-                        Some(def_id) => self.r.has_self.contains(&def_id),
+                        Some(def_id) => {
+                            self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self)
+                        }
                         None => self
                             .r
                             .tcx
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index b5b6d899cc5..e07c3247d07 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -43,7 +43,7 @@ use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::NonMacroAttrKind;
 use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{PrimTy, TraitCandidate};
 use rustc_index::IndexVec;
@@ -52,8 +52,8 @@ use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
-use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed};
-use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs};
+use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTools};
+use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
 use rustc_session::lint::LintBuffer;
@@ -992,7 +992,6 @@ pub struct Resolver<'a, 'tcx> {
     extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
 
     /// N.B., this is used only for better diagnostics, not name resolution itself.
-    has_self: LocalDefIdSet,
     field_def_ids: LocalDefIdMap<&'tcx [DefId]>,
 
     /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
@@ -1149,8 +1148,7 @@ 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>,
+    delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
 
     main_def: Option<MainDefinition>,
     trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
@@ -1399,7 +1397,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             prelude: None,
             extern_prelude,
 
-            has_self: Default::default(),
             field_def_ids: Default::default(),
             field_visibility_spans: FxHashMap::default(),
 
@@ -1508,7 +1505,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(),
+            delegation_fn_sigs: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1621,8 +1618,7 @@ 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,
+            delegation_fn_sigs: self.delegation_fn_sigs,
         };
         ResolverOutputs { global_ctxt, ast_lowering }
     }