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