Skip to content

Commit f0f0dae

Browse files
committed
delegation: Support async, const, extern "ABI" and C-variadic functions
Also allow `impl Trait` in delegated functions. The delegation item will refer to the original opaque type from the callee, fresh opaque type won't be created.
1 parent 78bf0c4 commit f0f0dae

File tree

11 files changed

+219
-161
lines changed

11 files changed

+219
-161
lines changed

compiler/rustc_ast_lowering/src/delegation.rs

+75-41
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use rustc_errors::ErrorGuaranteed;
4848
use rustc_hir as hir;
4949
use rustc_hir::def_id::DefId;
5050
use rustc_middle::span_bug;
51-
use rustc_middle::ty::ResolverAstLowering;
51+
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
5252
use rustc_span::{symbol::Ident, Span};
5353
use rustc_target::spec::abi;
5454
use std::iter;
@@ -66,7 +66,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
6666
return false;
6767
};
6868
if let Some(local_sig_id) = sig_id.as_local() {
69-
self.resolver.has_self.contains(&local_sig_id)
69+
self.resolver.delegation_fn_sigs[&local_sig_id].has_self
7070
} else {
7171
match self.tcx.def_kind(sig_id) {
7272
DefKind::Fn => false,
@@ -81,13 +81,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
8181
delegation: &Delegation,
8282
item_id: NodeId,
8383
) -> DelegationResults<'hir> {
84-
let span = delegation.path.segments.last().unwrap().ident.span;
84+
let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span);
8585
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
8686
match sig_id {
8787
Ok(sig_id) => {
88-
let decl = self.lower_delegation_decl(sig_id, span);
89-
let sig = self.lower_delegation_sig(span, decl);
90-
let body_id = self.lower_delegation_body(sig.decl, delegation);
88+
let (param_count, c_variadic) = self.param_count(sig_id);
89+
let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
90+
let sig = self.lower_delegation_sig(sig_id, decl, span);
91+
let body_id = self.lower_delegation_body(delegation, param_count, span);
9192

9293
let generics = self.lower_delegation_generics(span);
9394
DelegationResults { body_id, sig, generics }
@@ -122,70 +123,92 @@ impl<'hir> LoweringContext<'_, 'hir> {
122123
})
123124
}
124125

126+
fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) {
127+
if let Some(local_sig_id) = sig_id.as_local() {
128+
// Map may be filled incorrectly due to recursive delegation.
129+
// Error will be emmited later in astconv.
130+
match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
131+
Some(sig) => (sig.param_count, sig.c_variadic),
132+
None => (0, false),
133+
}
134+
} else {
135+
let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
136+
(sig.inputs().len(), sig.c_variadic)
137+
}
138+
}
139+
125140
fn lower_delegation_decl(
126141
&mut self,
127142
sig_id: DefId,
128-
param_span: Span,
143+
param_count: usize,
144+
c_variadic: bool,
145+
span: Span,
129146
) -> &'hir hir::FnDecl<'hir> {
130-
let args_count = if let Some(local_sig_id) = sig_id.as_local() {
131-
// Map may be filled incorrectly due to recursive delegation.
132-
// Error will be emmited later in astconv.
133-
self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default()
134-
} else {
135-
self.tcx.fn_arg_names(sig_id).len()
136-
};
137-
let inputs = self.arena.alloc_from_iter((0..args_count).map(|arg| hir::Ty {
147+
// The last parameter in C variadic functions is skipped in the signature,
148+
// like during regular lowering.
149+
let decl_param_count = param_count - c_variadic as usize;
150+
let inputs = self.arena.alloc_from_iter((0..decl_param_count).map(|arg| hir::Ty {
138151
hir_id: self.next_id(),
139152
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
140-
span: self.lower_span(param_span),
153+
span,
141154
}));
142155

143156
let output = self.arena.alloc(hir::Ty {
144157
hir_id: self.next_id(),
145158
kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output),
146-
span: self.lower_span(param_span),
159+
span,
147160
});
148161

149162
self.arena.alloc(hir::FnDecl {
150163
inputs,
151164
output: hir::FnRetTy::Return(output),
152-
c_variadic: false,
165+
c_variadic,
153166
lifetime_elision_allowed: true,
154167
implicit_self: hir::ImplicitSelfKind::None,
155168
})
156169
}
157170

158171
fn lower_delegation_sig(
159172
&mut self,
160-
span: Span,
173+
sig_id: DefId,
161174
decl: &'hir hir::FnDecl<'hir>,
175+
span: Span,
162176
) -> hir::FnSig<'hir> {
163-
hir::FnSig {
164-
decl,
165-
header: hir::FnHeader {
166-
unsafety: hir::Unsafety::Normal,
167-
constness: hir::Constness::NotConst,
168-
asyncness: hir::IsAsync::NotAsync,
169-
abi: abi::Abi::Rust,
170-
},
171-
span: self.lower_span(span),
172-
}
177+
let header = if let Some(local_sig_id) = sig_id.as_local() {
178+
match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
179+
Some(sig) => self.lower_fn_header(sig.header),
180+
None => self.generate_header_error(),
181+
}
182+
} else {
183+
let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder();
184+
let asyncness = match self.tcx.asyncness(sig_id) {
185+
Asyncness::Yes => hir::IsAsync::Async(span),
186+
Asyncness::No => hir::IsAsync::NotAsync,
187+
};
188+
hir::FnHeader {
189+
unsafety: sig.unsafety,
190+
constness: self.tcx.constness(sig_id),
191+
asyncness,
192+
abi: sig.abi,
193+
}
194+
};
195+
hir::FnSig { decl, header, span }
173196
}
174197

175-
fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) {
198+
fn generate_param(&mut self, span: Span) -> (hir::Param<'hir>, NodeId) {
176199
let pat_node_id = self.next_node_id();
177200
let pat_id = self.lower_node_id(pat_node_id);
178201
let pat = self.arena.alloc(hir::Pat {
179202
hir_id: pat_id,
180203
kind: hir::PatKind::Binding(hir::BindingAnnotation::NONE, pat_id, Ident::empty(), None),
181-
span: ty.span,
204+
span,
182205
default_binding_modes: false,
183206
});
184207

185-
(hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id)
208+
(hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id)
186209
}
187210

188-
fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> {
211+
fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> {
189212
let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment {
190213
ident: Ident::empty(),
191214
hir_id: self.next_id(),
@@ -194,20 +217,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
194217
infer_args: false,
195218
}));
196219

197-
let path =
198-
self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments });
220+
let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments });
199221

200222
hir::Expr {
201223
hir_id: self.next_id(),
202224
kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
203-
span: ty.span,
225+
span,
204226
}
205227
}
206228

207229
fn lower_delegation_body(
208230
&mut self,
209-
decl: &'hir hir::FnDecl<'hir>,
210231
delegation: &Delegation,
232+
param_count: usize,
233+
span: Span,
211234
) -> BodyId {
212235
let path = self.lower_qpath(
213236
delegation.id,
@@ -223,8 +246,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
223246
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
224247
let mut args: Vec<hir::Expr<'hir>> = Vec::new();
225248

226-
for (idx, param_ty) in decl.inputs.iter().enumerate() {
227-
let (param, pat_node_id) = this.generate_param(param_ty);
249+
for idx in 0..param_count {
250+
let (param, pat_node_id) = this.generate_param(span);
228251
parameters.push(param);
229252

230253
let arg = if let Some(block) = block
@@ -244,7 +267,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
244267
}
245268
} else {
246269
let pat_hir_id = this.lower_node_id(pat_node_id);
247-
this.generate_arg(param_ty, pat_hir_id)
270+
this.generate_arg(pat_hir_id, span)
248271
};
249272
args.push(arg);
250273
}
@@ -303,14 +326,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
303326
implicit_self: hir::ImplicitSelfKind::None,
304327
});
305328

306-
let sig = self.lower_delegation_sig(span, decl);
329+
let header = self.generate_header_error();
330+
let sig = hir::FnSig { decl, header, span };
331+
307332
let body_id = self.lower_body(|this| {
308333
let expr =
309334
hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
310335
(&[], expr)
311336
});
312337
DelegationResults { generics, body_id, sig }
313338
}
339+
340+
fn generate_header_error(&self) -> hir::FnHeader {
341+
hir::FnHeader {
342+
unsafety: hir::Unsafety::Normal,
343+
constness: hir::Constness::NotConst,
344+
asyncness: hir::IsAsync::NotAsync,
345+
abi: abi::Abi::Rust,
346+
}
347+
}
314348
}
315349

316350
struct SelfResolver<'a> {

compiler/rustc_ast_lowering/src/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1348,7 +1348,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13481348
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
13491349
}
13501350

1351-
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
1351+
pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
13521352
let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
13531353
hir::IsAsync::Async(span)
13541354
} else {

compiler/rustc_hir_analysis/src/astconv/mod.rs

-28
Original file line numberDiff line numberDiff line change
@@ -2281,11 +2281,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22812281
try_emit("recursive delegation");
22822282
}
22832283

2284-
let sig = self.tcx().fn_sig(sig_id).instantiate_identity();
2285-
if sig.output().has_opaque_types() {
2286-
try_emit("delegation to a function with opaque type");
2287-
}
2288-
22892284
let sig_generics = self.tcx().generics_of(sig_id);
22902285
let parent = self.tcx().parent(self.item_def_id());
22912286
let parent_generics = self.tcx().generics_of(parent);
@@ -2297,29 +2292,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22972292
try_emit("delegation with early bound generics");
22982293
}
22992294

2300-
if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes {
2301-
try_emit("delegation to async functions");
2302-
}
2303-
2304-
if self.tcx().constness(sig_id) == hir::Constness::Const {
2305-
try_emit("delegation to const functions");
2306-
}
2307-
2308-
if sig.c_variadic() {
2309-
try_emit("delegation to variadic functions");
2310-
// variadic functions are also `unsafe` and `extern "C"`.
2311-
// Do not emit same error multiple times.
2312-
return error_occured;
2313-
}
2314-
2315-
if let hir::Unsafety::Unsafe = sig.unsafety() {
2316-
try_emit("delegation to unsafe functions");
2317-
}
2318-
2319-
if abi::Abi::Rust != sig.abi() {
2320-
try_emit("delegation to non Rust ABI functions");
2321-
}
2322-
23232295
error_occured
23242296
}
23252297

compiler/rustc_middle/src/ty/mod.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use rustc_data_structures::unord::UnordMap;
4545
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
4646
use rustc_hir as hir;
4747
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
48-
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet};
48+
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
4949
use rustc_index::IndexVec;
5050
use rustc_macros::HashStable;
5151
use rustc_query_system::ich::StableHashingContext;
@@ -224,8 +224,15 @@ pub struct ResolverAstLowering {
224224
pub lint_buffer: Steal<LintBuffer>,
225225

226226
/// Information about functions signatures for delegation items expansion
227-
pub has_self: LocalDefIdSet,
228-
pub fn_parameter_counts: LocalDefIdMap<usize>,
227+
pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
228+
}
229+
230+
#[derive(Debug)]
231+
pub struct DelegationFnSig {
232+
pub header: ast::FnHeader,
233+
pub param_count: usize,
234+
pub has_self: bool,
235+
pub c_variadic: bool,
229236
}
230237

231238
#[derive(Clone, Copy, Debug)]

compiler/rustc_resolve/src/late.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par
2424
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
2525
use rustc_hir::{PrimTy, TraitCandidate};
2626
use rustc_middle::middle::resolve_bound_vars::Set1;
27+
use rustc_middle::ty::DelegationFnSig;
2728
use rustc_middle::{bug, span_bug};
2829
use rustc_session::config::{CrateType, ResolveDocLinks};
2930
use rustc_session::lint;
@@ -4680,12 +4681,13 @@ struct ItemInfoCollector<'a, 'b, 'tcx> {
46804681

46814682
impl ItemInfoCollector<'_, '_, '_> {
46824683
fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
4683-
let def_id = self.r.local_def_id(id);
4684-
self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len());
4685-
4686-
if sig.decl.has_self() {
4687-
self.r.has_self.insert(def_id);
4688-
}
4684+
let sig = DelegationFnSig {
4685+
header: sig.header,
4686+
param_count: sig.decl.inputs.len(),
4687+
has_self: sig.decl.has_self(),
4688+
c_variadic: sig.decl.c_variadic(),
4689+
};
4690+
self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
46894691
}
46904692
}
46914693

compiler/rustc_resolve/src/late/diagnostics.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -2046,7 +2046,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
20462046
ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
20472047
ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
20482048
ast::AssocItemKind::Delegation(..)
2049-
if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) =>
2049+
if self.r.delegation_fn_sigs[&self.r.local_def_id(assoc_item.id)]
2050+
.has_self =>
20502051
{
20512052
AssocSuggestion::MethodWithSelf { called }
20522053
}
@@ -2069,7 +2070,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
20692070
if filter_fn(res) {
20702071
let def_id = res.def_id();
20712072
let has_self = match def_id.as_local() {
2072-
Some(def_id) => self.r.has_self.contains(&def_id),
2073+
Some(def_id) => {
2074+
self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self)
2075+
}
20732076
None => self
20742077
.r
20752078
.tcx

0 commit comments

Comments
 (0)