1use std::debug_assert_matches;
6
7use rustc_data_structures::fx::FxHashMap;
8use rustc_hir::def::DefKind;
9use rustc_hir::def_id::{DefId, LocalDefId};
10use rustc_hir::{DelegationInfo, HirId, PathSegment};
11use rustc_middle::ty::{
12 self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
13};
14use rustc_span::{ErrorGuaranteed, Span, kw};
15
16use crate::collect::ItemCtxt;
17use crate::errors::DelegationSelfTypeNotSpecified;
18use crate::hir_ty_lowering::HirTyLowerer;
19
20type RemapTable = FxHashMap<u32, u32>;
21
22struct ParamIndexRemapper<'tcx> {
23 tcx: TyCtxt<'tcx>,
24 remap_table: RemapTable,
25}
26
27impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
28 fn cx(&self) -> TyCtxt<'tcx> {
29 self.tcx
30 }
31
32 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
33 if !ty.has_param() {
34 return ty;
35 }
36
37 if let ty::Param(param) = ty.kind()
38 && let Some(index) = self.remap_table.get(¶m.index)
39 {
40 return Ty::new_param(self.tcx, *index, param.name);
41 }
42 ty.super_fold_with(self)
43 }
44
45 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
46 if let ty::ReEarlyParam(param) = r.kind()
47 && let Some(index) = self.remap_table.get(¶m.index).copied()
48 {
49 return ty::Region::new_early_param(
50 self.tcx,
51 ty::EarlyParamRegion { index, name: param.name },
52 );
53 }
54 r
55 }
56
57 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
58 if let ty::ConstKind::Param(param) = ct.kind()
59 && let Some(idx) = self.remap_table.get(¶m.index)
60 {
61 let param = ty::ParamConst::new(*idx, param.name);
62 return ty::Const::new_param(self.tcx, param);
63 }
64 ct.super_fold_with(self)
65 }
66}
67
68enum SelfPositionKind {
69 AfterLifetimes(bool ),
70 Zero,
71 None,
72}
73
74pub fn opt_get_delegation_info(
75 tcx: TyCtxt<'_>,
76 delegation_id: LocalDefId,
77) -> Option<&DelegationInfo> {
78 tcx.hir_node(tcx.local_def_id_to_hir_id(delegation_id))
79 .fn_sig()
80 .and_then(|sig| sig.decl.opt_delegation_info())
81}
82
83fn get_delegation_info(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> &DelegationInfo {
84 opt_get_delegation_info(tcx, delegation_id).expect("processing delegation")
85}
86
87fn create_self_position_kind(
88 tcx: TyCtxt<'_>,
89 delegation_id: LocalDefId,
90 sig_id: DefId,
91) -> SelfPositionKind {
92 match (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)) {
93 (FnKind::AssocInherentImpl, FnKind::AssocTrait)
94 | (FnKind::AssocTraitImpl, FnKind::AssocTrait)
95 | (FnKind::AssocTrait, FnKind::AssocTrait)
96 | (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero,
97
98 (FnKind::Free, FnKind::AssocTrait) => {
99 let propagate_self_ty = get_delegation_info(tcx, delegation_id).propagate_self_ty;
100 SelfPositionKind::AfterLifetimes(propagate_self_ty)
101 }
102
103 _ => SelfPositionKind::None,
104 }
105}
106
107#[derive(#[automatically_derived]
impl ::core::clone::Clone for FnKind {
#[inline]
fn clone(&self) -> FnKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnKind { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for FnKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
FnKind::Free => "Free",
FnKind::AssocInherentImpl => "AssocInherentImpl",
FnKind::AssocTrait => "AssocTrait",
FnKind::AssocTraitImpl => "AssocTraitImpl",
})
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for FnKind {
#[inline]
fn eq(&self, other: &FnKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
108enum FnKind {
109 Free,
110 AssocInherentImpl,
111 AssocTrait,
112 AssocTraitImpl,
113}
114
115fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> FnKind {
116 let def_id = def_id.into();
117
118 if true {
{
match tcx.def_kind(def_id) {
DefKind::Fn | DefKind::AssocFn => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"DefKind::Fn | DefKind::AssocFn",
::core::option::Option::None);
}
}
};
};debug_assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
119
120 let parent = tcx.parent(def_id);
121 match tcx.def_kind(parent) {
122 DefKind::Trait => FnKind::AssocTrait,
123 DefKind::Impl { of_trait: true } => FnKind::AssocTraitImpl,
124 DefKind::Impl { of_trait: false } => FnKind::AssocInherentImpl,
125 _ => FnKind::Free,
126 }
127}
128
129#[derive(#[automatically_derived]
impl ::core::clone::Clone for InheritanceKind {
#[inline]
fn clone(&self) -> InheritanceKind {
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for InheritanceKind { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for InheritanceKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
InheritanceKind::WithParent(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"WithParent", &__self_0),
InheritanceKind::Own =>
::core::fmt::Formatter::write_str(f, "Own"),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for InheritanceKind {
#[inline]
fn eq(&self, other: &InheritanceKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(InheritanceKind::WithParent(__self_0),
InheritanceKind::WithParent(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq)]
132enum InheritanceKind {
133 WithParent(bool),
143 Own,
147}
148
149fn create_mapping<'tcx>(
159 tcx: TyCtxt<'tcx>,
160 sig_id: DefId,
161 def_id: LocalDefId,
162) -> FxHashMap<u32, u32> {
163 let mut mapping: FxHashMap<u32, u32> = Default::default();
164
165 let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id);
166 let is_self_at_zero = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::Zero => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::Zero);
167
168 if is_self_at_zero {
170 mapping.insert(0, 0);
171 }
172
173 let mut args_index = 0;
174
175 args_index += is_self_at_zero as usize;
176 args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id);
177
178 let sig_generics = tcx.generics_of(sig_id);
179 let process_sig_parent_generics = #[allow(non_exhaustive_omitted_patterns)] match fn_kind(tcx, sig_id) {
FnKind::AssocTrait => true,
_ => false,
}matches!(fn_kind(tcx, sig_id), FnKind::AssocTrait);
180
181 if process_sig_parent_generics {
182 for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
183 let param = sig_generics.param_at(i, tcx);
184 if !param.kind.is_ty_or_const() {
185 mapping.insert(param.index, args_index as u32);
186 args_index += 1;
187 }
188 }
189 }
190
191 for param in &sig_generics.own_params {
192 if !param.kind.is_ty_or_const() {
193 mapping.insert(param.index, args_index as u32);
194 args_index += 1;
195 }
196 }
197
198 if #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes { .. } => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes { .. }) {
202 mapping.insert(0, args_index as u32);
203 args_index += 1;
204 }
205
206 if process_sig_parent_generics {
207 for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
208 let param = sig_generics.param_at(i, tcx);
209 if param.kind.is_ty_or_const() {
210 mapping.insert(param.index, args_index as u32);
211 args_index += 1;
212 }
213 }
214 }
215
216 for param in &sig_generics.own_params {
217 if param.kind.is_ty_or_const() {
218 mapping.insert(param.index, args_index as u32);
219 args_index += 1;
220 }
221 }
222
223 mapping
224}
225
226fn get_delegation_parent_args_count_without_self<'tcx>(
227 tcx: TyCtxt<'tcx>,
228 delegation_id: LocalDefId,
229 sig_id: DefId,
230) -> usize {
231 let delegation_parent_args_count = tcx.generics_of(delegation_id).parent_count;
232
233 match (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)) {
234 (FnKind::Free, FnKind::Free)
235 | (FnKind::Free, FnKind::AssocTrait)
236 | (FnKind::AssocTraitImpl, FnKind::AssocTrait) => 0,
237
238 (FnKind::AssocInherentImpl, FnKind::Free)
239 | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
240 delegation_parent_args_count }
242
243 (FnKind::AssocTrait, FnKind::Free) | (FnKind::AssocTrait, FnKind::AssocTrait) => {
244 delegation_parent_args_count - 1 }
246
247 (FnKind::AssocTraitImpl, _)
250 | (_, FnKind::AssocTraitImpl)
251 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
252 }
253}
254
255fn get_parent_and_inheritance_kind<'tcx>(
256 tcx: TyCtxt<'tcx>,
257 def_id: LocalDefId,
258 sig_id: DefId,
259) -> (Option<DefId>, InheritanceKind) {
260 match (fn_kind(tcx, def_id), fn_kind(tcx, sig_id)) {
261 (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
262 (None, InheritanceKind::WithParent(true))
263 }
264
265 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
266 (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::Own)
267 }
268
269 (FnKind::AssocInherentImpl, FnKind::AssocTrait)
270 | (FnKind::AssocTrait, FnKind::AssocTrait)
271 | (FnKind::AssocInherentImpl, FnKind::Free)
272 | (FnKind::AssocTrait, FnKind::Free) => {
273 (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::WithParent(false))
274 }
275
276 (FnKind::AssocTraitImpl, _)
279 | (_, FnKind::AssocTraitImpl)
280 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
281 }
282}
283
284fn get_delegation_self_ty_or_err(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> Ty<'_> {
285 get_delegation_info(tcx, delegation_id)
286 .self_ty_id
287 .map(|id| {
288 let ctx = ItemCtxt::new(tcx, delegation_id);
289 ctx.lower_ty(tcx.hir_node(id).expect_ty())
290 })
291 .unwrap_or_else(|| {
292 let err = DelegationSelfTypeNotSpecified { span: tcx.def_span(delegation_id) };
296 tcx.dcx().emit_err(err);
297
298 Ty::new_error_with_message(
299 tcx,
300 tcx.def_span(delegation_id),
301 "the self type must be specified",
302 )
303 })
304}
305
306fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) -> Option<Ty<'tcx>> {
307 let sig_id = tcx.hir_opt_delegation_sig_id(delegation_id).expect("Delegation must have sig_id");
308 let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id));
309
310 match (caller_kind, callee_kind) {
311 (FnKind::Free, FnKind::AssocTrait)
312 | (FnKind::AssocInherentImpl, FnKind::Free)
313 | (FnKind::Free, FnKind::Free)
314 | (FnKind::AssocTrait, FnKind::Free)
315 | (FnKind::AssocTrait, FnKind::AssocTrait) => {
316 match create_self_position_kind(tcx, delegation_id, sig_id) {
317 SelfPositionKind::None => None,
318 SelfPositionKind::AfterLifetimes(propagate_self_ty) => {
319 if propagate_self_ty {
320 Some(get_delegation_self_ty_or_err(tcx, delegation_id))
321 } else {
322 let index = tcx.generics_of(delegation_id).own_counts().lifetimes;
324 Some(Ty::new_param(tcx, index as u32, kw::SelfUpper))
325 }
326 }
327 SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)),
328 }
329 }
330
331 (FnKind::AssocTraitImpl, FnKind::AssocTrait)
332 | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => Some(
333 tcx.type_of(tcx.local_parent(delegation_id)).instantiate_identity().skip_norm_wip(),
334 ),
335
336 (FnKind::AssocTraitImpl, _)
339 | (_, FnKind::AssocTraitImpl)
340 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
341 }
342}
343
344fn create_generic_args<'tcx>(
360 tcx: TyCtxt<'tcx>,
361 sig_id: DefId,
362 delegation_id: LocalDefId,
363 mut parent_args: &[ty::GenericArg<'tcx>],
364 child_args: &[ty::GenericArg<'tcx>],
365) -> Vec<ty::GenericArg<'tcx>> {
366 let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id));
367
368 let delegation_args = ty::GenericArgs::identity_for_item(tcx, delegation_id);
369
370 let deleg_parent_args_without_self_count =
371 get_delegation_parent_args_count_without_self(tcx, delegation_id, sig_id);
372
373 let delegation_generics = tcx.generics_of(delegation_id);
374 let real_args_count = delegation_args.len() - delegation_generics.own_synthetic_params_count();
375 let synth_args = &delegation_args[real_args_count..];
376 let delegation_args = &delegation_args[..real_args_count];
377
378 let args = match (caller_kind, callee_kind) {
379 (FnKind::Free, FnKind::Free)
380 | (FnKind::Free, FnKind::AssocTrait)
381 | (FnKind::AssocInherentImpl, FnKind::Free)
382 | (FnKind::AssocTrait, FnKind::Free)
383 | (FnKind::AssocTrait, FnKind::AssocTrait) => delegation_args,
384
385 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
386 let parent = tcx.local_parent(delegation_id);
390 parent_args =
391 tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args;
392
393 if !child_args.is_empty() {
{
::core::panicking::panic_fmt(format_args!("Child args can not be used in trait impl case"));
}
};assert!(child_args.is_empty(), "Child args can not be used in trait impl case");
394
395 tcx.mk_args(&delegation_args[delegation_generics.parent_count..])
396 }
397
398 (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
399 let self_ty =
400 tcx.type_of(tcx.local_parent(delegation_id)).instantiate_identity().skip_norm_wip();
401
402 tcx.mk_args_from_iter(
403 std::iter::once(ty::GenericArg::from(self_ty))
404 .chain(delegation_args.iter().copied()),
405 )
406 }
407
408 (FnKind::AssocTraitImpl, _)
411 | (_, FnKind::AssocTraitImpl)
412 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
413 };
414
415 let mut new_args = ::alloc::vec::Vec::new()vec![];
416
417 let self_pos_kind = create_self_position_kind(tcx, delegation_id, sig_id);
418 let mut lifetimes_end_pos;
419
420 if !parent_args.is_empty() {
421 let parent_args_lifetimes_count =
422 parent_args.iter().filter(|a| a.as_region().is_some()).count();
423
424 match self_pos_kind {
425 SelfPositionKind::AfterLifetimes { .. } => {
426 new_args.extend(&parent_args[1..1 + parent_args_lifetimes_count]);
427
428 lifetimes_end_pos = parent_args_lifetimes_count;
429
430 new_args.push(parent_args[0]);
431
432 new_args.extend(&parent_args[1 + parent_args_lifetimes_count..]);
433 }
434 SelfPositionKind::Zero => {
435 lifetimes_end_pos = 1 + parent_args_lifetimes_count;
436 new_args.extend_from_slice(parent_args);
437
438 for i in 0..deleg_parent_args_without_self_count {
439 new_args.insert(1 + i, args[1 + i]);
440 }
441
442 lifetimes_end_pos += deleg_parent_args_without_self_count;
443 }
444 SelfPositionKind::None => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
446 };
447 } else {
448 let self_impact = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::Zero => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::Zero) as usize;
449
450 lifetimes_end_pos = self_impact
451 + deleg_parent_args_without_self_count
452 + &args[self_impact + deleg_parent_args_without_self_count..]
453 .iter()
454 .filter(|a| a.as_region().is_some())
455 .count();
456
457 new_args.extend_from_slice(args);
458
459 if #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes(true) => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true)) {
462 new_args.insert(
463 lifetimes_end_pos,
464 ty::GenericArg::from(get_delegation_self_ty_or_err(tcx, delegation_id)),
465 );
466 }
467 }
468
469 if !child_args.is_empty() {
470 let child_lifetimes_count = child_args.iter().filter(|a| a.as_region().is_some()).count();
471
472 for i in 0..child_lifetimes_count {
473 new_args.insert(lifetimes_end_pos + i, child_args[i]);
474 }
475
476 new_args.extend_from_slice(&child_args[child_lifetimes_count..]);
477 } else if !parent_args.is_empty() {
478 let child_args = &delegation_args[delegation_generics.parent_count..];
479
480 let child_lifetimes_count =
481 child_args.iter().take_while(|a| a.as_region().is_some()).count();
482
483 for i in 0..child_lifetimes_count {
484 new_args.insert(lifetimes_end_pos + i, child_args[i]);
485 }
486
487 let skip_self = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes(false) => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(false));
489 new_args.extend(&child_args[child_lifetimes_count + skip_self as usize..]);
490 }
491
492 new_args.extend(synth_args);
493
494 new_args
495}
496
497pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
498 tcx: TyCtxt<'tcx>,
499 def_id: LocalDefId,
500 sig_id: DefId,
501) -> ty::GenericPredicates<'tcx> {
502 struct PredicatesCollector<'tcx> {
503 tcx: TyCtxt<'tcx>,
504 preds: Vec<(ty::Clause<'tcx>, Span)>,
505 args: Vec<ty::GenericArg<'tcx>>,
506 folder: ParamIndexRemapper<'tcx>,
507 filter_self_preds: bool,
508 }
509
510 impl<'tcx> PredicatesCollector<'tcx> {
511 fn with_own_preds(
512 mut self,
513 f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
514 def_id: DefId,
515 ) -> Self {
516 let preds = f(def_id);
517 let args = self.args.as_slice();
518
519 for pred in preds.predicates {
520 if self.filter_self_preds
523 && let Some(trait_pred) = pred.0.as_trait_clause()
524 && trait_pred.self_ty().skip_binder().is_param(0)
526 {
527 continue;
528 }
529
530 let new_pred = pred.0.fold_with(&mut self.folder);
531 self.preds.push((
532 EarlyBinder::bind(new_pred).instantiate(self.tcx, args).skip_norm_wip(),
533 pred.1,
534 ));
535 }
536
537 self
538 }
539
540 fn with_preds(
541 mut self,
542 f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
543 def_id: DefId,
544 ) -> Self {
545 let preds = f(def_id);
546 if let Some(parent_def_id) = preds.parent {
547 self = self.with_own_preds(f, parent_def_id);
548 }
549
550 self.with_own_preds(f, def_id)
551 }
552 }
553
554 let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id);
555 let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
556 let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id);
557 let filter_self_preds = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes(true) => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true));
558
559 let collector = PredicatesCollector { tcx, preds: ::alloc::vec::Vec::new()vec![], args, folder, filter_self_preds };
560 let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
561
562 let preds = match inh_kind {
566 InheritanceKind::WithParent(false) => {
567 collector.with_preds(|def_id| tcx.explicit_predicates_of(def_id), sig_id)
568 }
569 InheritanceKind::WithParent(true) => {
570 collector.with_preds(|def_id| tcx.predicates_of(def_id), sig_id)
571 }
572 InheritanceKind::Own => {
573 collector.with_own_preds(|def_id| tcx.predicates_of(def_id), sig_id)
574 }
575 }
576 .preds;
577
578 ty::GenericPredicates { parent, predicates: tcx.arena.alloc_from_iter(preds) }
579}
580
581fn create_folder_and_args<'tcx>(
582 tcx: TyCtxt<'tcx>,
583 def_id: LocalDefId,
584 sig_id: DefId,
585 parent_args: &'tcx [ty::GenericArg<'tcx>],
586 child_args: &'tcx [ty::GenericArg<'tcx>],
587) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
588 let args = create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
589 let remap_table = create_mapping(tcx, sig_id, def_id);
590
591 (ParamIndexRemapper { tcx, remap_table }, args)
592}
593
594fn check_constraints<'tcx>(
595 tcx: TyCtxt<'tcx>,
596 def_id: LocalDefId,
597 sig_id: DefId,
598) -> Result<(), ErrorGuaranteed> {
599 let mut ret = Ok(());
600
601 let mut emit = |descr| {
602 ret = Err(tcx.dcx().emit_err(crate::errors::UnsupportedDelegation {
603 span: tcx.def_span(def_id),
604 descr,
605 callee_span: tcx.def_span(sig_id),
606 }));
607 };
608
609 if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic() {
610 emit("delegation to C-variadic functions is not allowed");
612 }
613
614 ret
615}
616
617pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
618 tcx: TyCtxt<'tcx>,
619 def_id: LocalDefId,
620) -> &'tcx [Ty<'tcx>] {
621 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id");
622 let caller_sig = tcx.fn_sig(sig_id);
623
624 if let Err(err) = check_constraints(tcx, def_id, sig_id) {
625 let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
626 let err_type = Ty::new_error(tcx, err);
627 return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
628 }
629
630 let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id);
631 let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
632 let caller_sig = EarlyBinder::bind(caller_sig.skip_binder().fold_with(&mut folder));
633
634 let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder();
635 let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output()));
636 tcx.arena.alloc_from_iter(sig_iter)
637}
638
639fn get_delegation_user_specified_args<'tcx>(
644 tcx: TyCtxt<'tcx>,
645 delegation_id: LocalDefId,
646) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
647 let info = get_delegation_info(tcx, delegation_id);
648
649 let get_segment = |hir_id: HirId| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
650 let segment = tcx.hir_node(hir_id).expect_path_segment();
651 segment.res.opt_def_id().map(|def_id| (segment, def_id))
652 };
653
654 let ctx = ItemCtxt::new(tcx, delegation_id);
655 let lowerer = ctx.lowerer();
656
657 let parent_args = info.parent_args_segment_id.and_then(get_segment).map(|(segment, def_id)| {
658 let self_ty = get_delegation_self_ty(tcx, delegation_id);
659
660 lowerer
661 .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty)
662 .0
663 .as_slice()
664 });
665
666 let child_args = info
667 .child_args_segment_id
668 .and_then(get_segment)
669 .filter(|(_, def_id)| #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(*def_id) {
DefKind::Fn | DefKind::AssocFn => true,
_ => false,
}matches!(tcx.def_kind(*def_id), DefKind::Fn | DefKind::AssocFn))
670 .map(|(segment, def_id)| {
671 let parent_args = if let Some(parent_args) = parent_args {
672 parent_args
673 } else {
674 let parent = tcx.parent(def_id);
675 if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(parent) {
DefKind::Trait => true,
_ => false,
}matches!(tcx.def_kind(parent), DefKind::Trait) {
676 ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
677 } else {
678 &[]
679 }
680 };
681
682 let args = lowerer
683 .lower_generic_args_of_path(segment.ident.span, def_id, parent_args, segment, None)
684 .0;
685
686 let synth_params_count = tcx.generics_of(def_id).own_synthetic_params_count();
687 &args[parent_args.len()..args.len() - synth_params_count]
688 });
689
690 (parent_args.unwrap_or_default(), child_args.unwrap_or_default())
691}