diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index bddb50568d41b..727c6bc82fef9 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
>,
+ pub rename: Option,
pub path: Path,
pub body: Option>,
}
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index c4e49d7dbea44..7dbfb7c736454 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(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(
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 968d10ad4872c..d9740928f8d67 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 f4d5e71badebb..a1e5c275c189c 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> = Vec::new();
let mut args: Vec> = 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 1d52b4107d7b5..dcce54d66c2d9 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 4a0df6cf7b86f..63da27246a2af 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 cc026e349d74e..cda332aee5647 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,
/// Information about functions signatures for delegation items expansion
- pub has_self: LocalDefIdSet,
- pub fn_parameter_counts: LocalDefIdMap,
+ pub delegation_fn_sigs: LocalDefIdMap,
+}
+
+#[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 84ecd0a0de54f..ed51710564a42 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(
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index c877ae5e21f48..292af43b602e0 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 d79c638fa0789..64451030adf0f 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 b5b6d899cc58e..e07c3247d07ae 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>,
/// 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>>,
/// Amount of lifetime parameters for each item in the crate.
item_generics_num_lifetimes: FxHashMap,
- /// Amount of parameters for each function in the crate.
- fn_parameter_counts: LocalDefIdMap,
+ delegation_fn_sigs: LocalDefIdMap,
main_def: Option,
trait_impls: FxIndexMap>,
@@ -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 }
}
diff --git a/tests/ui/delegation/auxiliary/fn-header-aux.rs b/tests/ui/delegation/auxiliary/fn-header-aux.rs
new file mode 100644
index 0000000000000..d26209a4f789f
--- /dev/null
+++ b/tests/ui/delegation/auxiliary/fn-header-aux.rs
@@ -0,0 +1,9 @@
+//@ edition:2018
+
+#![feature(c_variadic)]
+
+pub unsafe fn unsafe_fn_extern() {}
+pub extern "C" fn extern_fn_extern() {}
+pub unsafe extern "C" fn variadic_fn_extern(n: usize, mut args: ...) {}
+pub const fn const_fn_extern() {}
+pub async fn async_fn_extern() {}
diff --git a/tests/ui/delegation/fn-header.rs b/tests/ui/delegation/fn-header.rs
new file mode 100644
index 0000000000000..db20e1058e061
--- /dev/null
+++ b/tests/ui/delegation/fn-header.rs
@@ -0,0 +1,57 @@
+//@ check-pass
+//@ edition:2018
+//@ aux-crate:fn_header_aux=fn-header-aux.rs
+
+#![feature(c_variadic)]
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+#![deny(unused_unsafe)]
+
+mod to_reuse {
+ pub unsafe fn unsafe_fn() {}
+ pub extern "C" fn extern_fn() {}
+ pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
+ pub const fn const_fn() {}
+ pub async fn async_fn() {}
+}
+
+reuse to_reuse::unsafe_fn;
+reuse to_reuse::extern_fn;
+reuse to_reuse::variadic_fn;
+reuse to_reuse::const_fn;
+reuse to_reuse::async_fn;
+
+reuse fn_header_aux::unsafe_fn_extern;
+reuse fn_header_aux::extern_fn_extern;
+reuse fn_header_aux::variadic_fn_extern;
+reuse fn_header_aux::const_fn_extern;
+reuse fn_header_aux::async_fn_extern;
+
+const fn const_check() {
+ const_fn();
+ const_fn_extern();
+}
+
+async fn async_check() {
+ async_fn().await;
+ async_fn_extern().await;
+}
+
+fn main() {
+ unsafe {
+ unsafe_fn();
+ unsafe_fn_extern();
+ }
+ extern_fn();
+ extern_fn_extern();
+ let _: extern "C" fn() = extern_fn;
+ let _: extern "C" fn() = extern_fn_extern;
+ unsafe {
+ variadic_fn(0);
+ variadic_fn(0, 1);
+ variadic_fn_extern(0);
+ variadic_fn_extern(0, 1);
+ }
+ let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
+ let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
+}
diff --git a/tests/ui/delegation/impl-trait.rs b/tests/ui/delegation/impl-trait.rs
new file mode 100644
index 0000000000000..13df0155485c9
--- /dev/null
+++ b/tests/ui/delegation/impl-trait.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+ pub fn foo() -> impl Clone { 0 }
+}
+
+reuse to_reuse::foo;
+
+trait Trait {
+ fn bar() -> impl Clone { 1 }
+}
+
+struct S;
+impl Trait for S {}
+
+impl S {
+ reuse to_reuse::foo;
+ reuse ::bar;
+}
+
+fn main() {
+ foo().clone();
+ ::bar().clone();
+}
diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs
index 9dccb12b57adb..5f78de97638b5 100644
--- a/tests/ui/delegation/not-supported.rs
+++ b/tests/ui/delegation/not-supported.rs
@@ -14,9 +14,9 @@ mod generics {
fn foo3<'a: 'a>(_: &'a u32) {}
reuse GenericTrait::bar;
- //~^ delegation with early bound generics is not supported yet
+ //~^ ERROR delegation with early bound generics is not supported yet
reuse GenericTrait::bar1;
- //~^ delegation with early bound generics is not supported yet
+ //~^ ERROR delegation with early bound generics is not supported yet
}
struct F;
@@ -73,26 +73,18 @@ mod opaque {
}
reuse to_reuse::opaque_arg;
//~^ ERROR delegation with early bound generics is not supported yet
- reuse to_reuse::opaque_ret;
- //~^ ERROR delegation to a function with opaque type is not supported yet
-}
-mod fn_header {
- mod to_reuse {
- pub unsafe fn unsafe_fn() {}
- pub extern "C" fn extern_fn() {}
- pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
- pub const fn const_fn() {}
+ trait ToReuse {
+ fn opaque_ret() -> impl Trait { unimplemented!() }
}
- reuse to_reuse::unsafe_fn;
- //~^ ERROR delegation to unsafe functions is not supported yet
- reuse to_reuse::extern_fn;
- //~^ ERROR delegation to non Rust ABI functions is not supported yet
- reuse to_reuse::variadic_fn;
- //~^ ERROR delegation to variadic functions is not supported yet
- reuse to_reuse::const_fn;
- //~^ ERROR delegation to const functions is not supported yet
+ // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls.
+ impl ToReuse for u8 {
+ reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type
+ }
+ impl ToReuse for u16 {
+ reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type
+ }
}
mod recursive {
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
index f6c49366899c1..e2cb04f977b1e 100644
--- a/tests/ui/delegation/not-supported.stderr
+++ b/tests/ui/delegation/not-supported.stderr
@@ -115,53 +115,46 @@ LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
LL | reuse to_reuse::opaque_arg;
| ^^^^^^^^^^
-error: delegation to a function with opaque type is not supported yet
- --> $DIR/not-supported.rs:76:21
+error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}`
+ --> $DIR/not-supported.rs:83:25
|
-LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
- | --------------------------------- callee defined here
-...
-LL | reuse to_reuse::opaque_ret;
- | ^^^^^^^^^^
-
-error: delegation to unsafe functions is not supported yet
- --> $DIR/not-supported.rs:88:21
+LL | reuse to_reuse::opaque_ret;
+ | ^^^^^^^^^^
|
-LL | pub unsafe fn unsafe_fn() {}
- | ------------------------- callee defined here
-...
-LL | reuse to_reuse::unsafe_fn;
- | ^^^^^^^^^
-
-error: delegation to non Rust ABI functions is not supported yet
- --> $DIR/not-supported.rs:90:21
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+ --> $DIR/not-supported.rs:83:25
|
-LL | pub extern "C" fn extern_fn() {}
- | ----------------------------- callee defined here
-...
-LL | reuse to_reuse::extern_fn;
- | ^^^^^^^^^
-
-error: delegation to variadic functions is not supported yet
- --> $DIR/not-supported.rs:92:21
+LL | reuse to_reuse::opaque_ret;
+ | ^^^^^^^^^^
+ = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::` is well-formed
+ --> $DIR/not-supported.rs:82:5
|
-LL | pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
- | ------------------------------------------------------------- callee defined here
-...
-LL | reuse to_reuse::variadic_fn;
- | ^^^^^^^^^^^
+LL | impl ToReuse for u8 {
+ | ^^^^^^^^^^^^^^^^^^^
+ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-error: delegation to const functions is not supported yet
- --> $DIR/not-supported.rs:94:21
+error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}`
+ --> $DIR/not-supported.rs:86:24
|
-LL | pub const fn const_fn() {}
- | ----------------------- callee defined here
-...
-LL | reuse to_reuse::const_fn;
- | ^^^^^^^^
+LL | reuse ToReuse::opaque_ret;
+ | ^^^^^^^^^^
+ |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+ --> $DIR/not-supported.rs:86:24
+ |
+LL | reuse ToReuse::opaque_ret;
+ | ^^^^^^^^^^
+ = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::` is well-formed
+ --> $DIR/not-supported.rs:85:5
+ |
+LL | impl ToReuse for u16 {
+ | ^^^^^^^^^^^^^^^^^^^^
+ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: recursive delegation is not supported yet
- --> $DIR/not-supported.rs:107:22
+ --> $DIR/not-supported.rs:99:22
|
LL | pub reuse to_reuse2::foo;
| --- callee defined here
@@ -169,7 +162,7 @@ LL | pub reuse to_reuse2::foo;
LL | reuse to_reuse1::foo;
| ^^^
-error: aborting due to 19 previous errors
+error: aborting due to 16 previous errors
-Some errors have detailed explanations: E0049, E0195.
+Some errors have detailed explanations: E0049, E0195, E0391.
For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/delegation/rename.rs b/tests/ui/delegation/rename.rs
new file mode 100644
index 0000000000000..f4b3da76c56c7
--- /dev/null
+++ b/tests/ui/delegation/rename.rs
@@ -0,0 +1,20 @@
+//@ check-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+ pub fn a() {}
+}
+
+reuse to_reuse::a as b;
+
+struct S;
+impl S {
+ reuse to_reuse::a as b;
+}
+
+fn main() {
+ b();
+ S::b();
+}