1use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6use rustc_hir::def::DefKind;
7use rustc_hir::def_id::{DefId, LocalDefId};
8use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment};
9use rustc_middle::ty::{
10 self, EarlyBinder, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
11 TypeVisitableExt,
12};
13use rustc_span::{ErrorGuaranteed, Span, kw};
14
15use crate::collect::ItemCtxt;
16use crate::hir_ty_lowering::HirTyLowerer;
17
18type RemapTable = FxHashMap<u32, u32>;
19
20struct ParamIndexRemapper<'tcx> {
21 tcx: TyCtxt<'tcx>,
22 remap_table: RemapTable,
23 delegation_parent_consts: FxHashSet<ty::ParamConst>,
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
67#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SelfPositionKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
SelfPositionKind::AfterLifetimes(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"AfterLifetimes", &__self_0),
SelfPositionKind::Zero =>
::core::fmt::Formatter::write_str(f, "Zero"),
SelfPositionKind::None =>
::core::fmt::Formatter::write_str(f, "None"),
}
}
}Debug)]
68enum SelfPositionKind {
69 AfterLifetimes(Option<DelegationSelfTyPropagationKind>),
70 Zero,
71 None,
72}
73
74fn create_self_param_position_kind(
75 tcx: TyCtxt<'_>,
76 def_id: LocalDefId,
77 sig_id: DefId,
78) -> SelfPositionKind {
79 match fn_kinds(tcx, def_id, sig_id) {
80 (FnKind::Free, FnKind::AssocTrait) => {
81 let kind = tcx.hir_delegation_info(def_id).self_ty_propagation_kind;
82 SelfPositionKind::AfterLifetimes(kind)
83 }
84
85 (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
86
87 (_, FnKind::AssocTrait) | (FnKind::AssocTrait, _) => SelfPositionKind::Zero,
88
89 (FnKind::AssocTraitImpl, _) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
90
91 _ => SelfPositionKind::None,
92 }
93}
94
95#[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)]
96enum FnKind {
97 Free,
98 AssocInherentImpl,
99 AssocTrait,
100 AssocTraitImpl,
101}
102
103fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> FnKind {
104 let def_id = def_id.into();
105
106 match tcx.def_kind(def_id) {
107 DefKind::Fn => FnKind::Free,
108 DefKind::AssocFn => match tcx.def_kind(tcx.parent(def_id)) {
109 DefKind::Trait => FnKind::AssocTrait,
110 DefKind::Impl { of_trait } => match of_trait {
111 true => FnKind::AssocTraitImpl,
112 false => FnKind::AssocInherentImpl,
113 },
114 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("associated function can only be in trait or impl")));
}unreachable!("associated function can only be in trait or impl"),
115 },
116 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("delegation/signature can be either free or associated function")));
}unreachable!("delegation/signature can be either free or associated function"),
117 }
118}
119
120fn fn_kinds(tcx: TyCtxt<'_>, def_id: LocalDefId, sig_id: DefId) -> (FnKind, FnKind) {
121 let kinds = (fn_kind(tcx, def_id), fn_kind(tcx, sig_id));
122
123 if !!#[allow(non_exhaustive_omitted_patterns)] match kinds {
(_, FnKind::AssocTraitImpl) => true,
_ => false,
} {
::core::panicking::panic("assertion failed: !matches!(kinds, (_, FnKind::AssocTraitImpl))")
};assert!(!matches!(kinds, (_, FnKind::AssocTraitImpl)));
125 if !!#[allow(non_exhaustive_omitted_patterns)] match kinds {
(_, FnKind::AssocInherentImpl) => true,
_ => false,
} {
::core::panicking::panic("assertion failed: !matches!(kinds, (_, FnKind::AssocInherentImpl))")
};assert!(!matches!(kinds, (_, FnKind::AssocInherentImpl)));
127
128 kinds
129}
130
131#[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)]
134enum InheritanceKind {
135 WithParent(bool),
145 Own,
149}
150
151fn create_mapping<'tcx>(
161 tcx: TyCtxt<'tcx>,
162 sig_id: DefId,
163 def_id: LocalDefId,
164) -> FxHashMap<u32, u32> {
165 let mut mapping: FxHashMap<u32, u32> = Default::default();
166
167 let self_pos_kind = create_self_param_position_kind(tcx, def_id, sig_id);
168 let is_self_at_zero = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::Zero => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::Zero);
169
170 if is_self_at_zero {
172 mapping.insert(0, 0);
173 }
174
175 let mut args_index = 0;
176
177 args_index += is_self_at_zero as usize;
178 args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id);
179
180 let sig_generics = tcx.generics_of(sig_id);
181 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);
182
183 if process_sig_parent_generics {
184 for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
185 let param = sig_generics.param_at(i, tcx);
186 if !param.kind.is_ty_or_const() {
187 mapping.insert(param.index, args_index as u32);
188 args_index += 1;
189 }
190 }
191 }
192
193 for param in &sig_generics.own_params {
194 if !param.kind.is_ty_or_const() {
195 mapping.insert(param.index, args_index as u32);
196 args_index += 1;
197 }
198 }
199
200 if #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes { .. } => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes { .. }) {
204 mapping.insert(0, args_index as u32);
205 args_index += 1;
206 }
207
208 if process_sig_parent_generics {
209 for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
210 let param = sig_generics.param_at(i, tcx);
211 if param.kind.is_ty_or_const() {
212 mapping.insert(param.index, args_index as u32);
213 args_index += 1;
214 }
215 }
216 }
217
218 for param in &sig_generics.own_params {
219 if param.kind.is_ty_or_const() {
220 mapping.insert(param.index, args_index as u32);
221 args_index += 1;
222 }
223 }
224
225 mapping
226}
227
228fn get_delegation_parent_args_count_without_self<'tcx>(
229 tcx: TyCtxt<'tcx>,
230 def_id: LocalDefId,
231 sig_id: DefId,
232) -> usize {
233 let kinds @ (def_kind, _) = fn_kinds(tcx, def_id, sig_id);
234
235 match kinds {
236 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => 0,
237
238 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
239
240 (FnKind::Free, _) => 0,
241
242 (_, _) => {
243 let delegation_parent_args_count = tcx.generics_of(def_id).parent_count;
244 let has_self = def_kind == FnKind::AssocTrait;
245
246 delegation_parent_args_count - usize::from(has_self)
247 }
248 }
249}
250
251fn get_parent_and_inheritance_kind<'tcx>(
252 tcx: TyCtxt<'tcx>,
253 def_id: LocalDefId,
254 sig_id: DefId,
255) -> (Option<DefId>, InheritanceKind) {
256 let kinds @ (_, sig_kind) = fn_kinds(tcx, def_id, sig_id);
257
258 match kinds {
259 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
260 (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::Own)
261 }
262
263 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
264
265 (FnKind::Free, _) => {
266 let copy_self_clauses = sig_kind == FnKind::AssocTrait;
267 (None, InheritanceKind::WithParent(copy_self_clauses))
268 }
269
270 (_, _) => (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::WithParent(false)),
271 }
272}
273
274fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<Ty<'tcx>> {
275 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("processing delegation");
276 let (caller_kind, callee_kind) = fn_kinds(tcx, def_id, sig_id);
277
278 match (caller_kind, callee_kind) {
279 (FnKind::AssocTraitImpl, FnKind::AssocTrait) | (FnKind::AssocInherentImpl, _) => {
280 Some(tcx.type_of(tcx.local_parent(def_id)).instantiate_identity().skip_norm_wip())
281 }
282
283 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
285
286 (_, _) => match create_self_param_position_kind(tcx, def_id, sig_id) {
287 SelfPositionKind::None => None,
288 SelfPositionKind::AfterLifetimes(propagation_kind) => Some(match propagation_kind {
289 Some(kind) => match kind {
290 DelegationSelfTyPropagationKind::SelfTy(self_ty_id) => {
291 let ctx = ItemCtxt::new(tcx, def_id);
292 ctx.lower_ty(tcx.hir_node(self_ty_id).expect_ty())
293 }
294 DelegationSelfTyPropagationKind::SelfParam => {
295 let index = tcx.generics_of(def_id).own_counts().lifetimes;
296 Ty::new_param(tcx, index as u32, kw::SelfUpper)
297 }
298 },
299 None => Ty::new_error_with_message(
300 tcx,
301 tcx.def_span(def_id),
302 "self propagation kind must be specified for `AfterLifetimes` variant",
303 ),
304 }),
305 SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)),
306 },
307 }
308}
309
310fn create_generic_args<'tcx>(
326 tcx: TyCtxt<'tcx>,
327 sig_id: DefId,
328 def_id: LocalDefId,
329 mut parent_args: &[ty::GenericArg<'tcx>],
330 mut child_args: &[ty::GenericArg<'tcx>],
331) -> (Vec<ty::GenericArg<'tcx>>, &'tcx [ty::GenericArg<'tcx>]) {
332 let delegation_generics = tcx.generics_of(def_id);
333 let delegation_args = ty::GenericArgs::identity_for_item(tcx, def_id);
334
335 let real_args_count = delegation_args.len() - delegation_generics.own_synthetic_params_count();
336 let synth_args = &delegation_args[real_args_count..];
337
338 let mut delegation_parent_args =
339 &delegation_args[delegation_generics.has_self as usize..delegation_generics.parent_count];
340
341 let delegation_args = &delegation_args[delegation_generics.parent_count..];
342
343 let kinds = fn_kinds(tcx, def_id, sig_id);
344 if #[allow(non_exhaustive_omitted_patterns)] match kinds {
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => true,
_ => false,
}matches!(kinds, (FnKind::AssocTraitImpl, FnKind::AssocTrait)) {
345 let parent = tcx.local_parent(def_id);
349
350 parent_args =
351 tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args;
352
353 child_args =
354 &delegation_args[delegation_args.len() - delegation_generics.own_params.len()..];
355
356 delegation_parent_args = &[];
357 }
358
359 let self_type = get_delegation_self_ty(tcx, def_id).map(ty::GenericArg::from);
360
361 if self_type.is_some() && !parent_args.is_empty() {
364 parent_args = &parent_args[1..];
365 }
366
367 let (zero_self, after_lifetimes_self) =
368 match create_self_param_position_kind(tcx, def_id, sig_id) {
369 SelfPositionKind::AfterLifetimes(_) => {
370 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
371 (None, self_type)
372 }
373 SelfPositionKind::Zero => {
374 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
375 (self_type, None)
376 }
377 SelfPositionKind::None => (None, None),
378 };
379
380 let zero_self = zero_self.as_ref().into_iter();
381 let after_lifetimes_self = after_lifetimes_self.as_ref().into_iter();
382
383 let args = zero_self
384 .chain(delegation_parent_args)
385 .chain(parent_args.iter().filter(|a| a.as_region().is_some()))
386 .chain(child_args.iter().filter(|a| a.as_region().is_some()))
387 .chain(after_lifetimes_self)
388 .chain(parent_args.iter().filter(|a| a.as_region().is_none()))
389 .chain(child_args.iter().filter(|a| a.as_region().is_none()))
390 .chain(synth_args)
391 .copied()
392 .collect::<Vec<_>>();
393
394 (args, delegation_parent_args)
395}
396
397pub(crate) fn inherit_clauses_for_delegation_item<'tcx>(
398 tcx: TyCtxt<'tcx>,
399 def_id: LocalDefId,
400 sig_id: DefId,
401) -> ty::GenericClauses<'tcx> {
402 struct ClausesCollector<'tcx> {
403 tcx: TyCtxt<'tcx>,
404 clauses: Vec<(ty::Clause<'tcx>, Span)>,
405 args: Vec<ty::GenericArg<'tcx>>,
406 folder: ParamIndexRemapper<'tcx>,
407 filter_self_clauses: bool,
408 }
409
410 impl<'tcx> ClausesCollector<'tcx> {
411 fn with_own_clauses(
412 mut self,
413 f: impl Fn(DefId) -> ty::GenericClauses<'tcx>,
414 def_id: DefId,
415 ) -> Self {
416 let clauses = f(def_id);
417 let args = self.args.as_slice();
418
419 for clause in clauses.clauses {
420 if self.filter_self_clauses
423 && let Some(trait_clause) = clause.0.as_trait_clause()
424 && trait_clause.self_ty().skip_binder().is_param(0)
426 {
427 continue;
428 }
429
430 if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) =
458 clause.0.as_predicate().fold_with(&mut self.folder).kind().skip_binder()
459 {
460 let unnorm_const = EarlyBinder::bind(self.tcx, ct).instantiate(self.tcx, args);
461 if let ty::ConstKind::Param(param) = unnorm_const.skip_norm_wip().kind()
462 && self.folder.delegation_parent_consts.contains(¶m)
463 {
464 continue;
465 }
466 }
467
468 let new_clause = clause.0.fold_with(&mut self.folder);
469 self.clauses.push((
470 EarlyBinder::bind(self.tcx, new_clause)
471 .instantiate(self.tcx, args)
472 .skip_norm_wip(),
473 clause.1,
474 ));
475 }
476
477 self
478 }
479
480 fn with_clauses(
481 mut self,
482 f: impl Fn(DefId) -> ty::GenericClauses<'tcx> + Copy,
483 def_id: DefId,
484 ) -> Self {
485 let preds = f(def_id);
486 if let Some(parent_def_id) = preds.parent {
487 self = self.with_own_clauses(f, parent_def_id);
488 }
489
490 self.with_own_clauses(f, def_id)
491 }
492 }
493
494 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
495 let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
496 let self_pos_kind = create_self_param_position_kind(tcx, def_id, sig_id);
497 let filter_self_clauses = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
=> true,
_ => false,
}matches!(
498 self_pos_kind,
499 SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
500 );
501
502 let collector = ClausesCollector { tcx, clauses: ::alloc::vec::Vec::new()vec![], args, folder, filter_self_clauses };
503 let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
504
505 let clauses = match inh_kind {
509 InheritanceKind::WithParent(false) => {
510 collector.with_clauses(|def_id| tcx.explicit_clauses_of(def_id), sig_id)
511 }
512 InheritanceKind::WithParent(true) => {
513 collector.with_clauses(|def_id| tcx.clauses_of(def_id), sig_id)
514 }
515 InheritanceKind::Own => collector.with_own_clauses(|def_id| tcx.clauses_of(def_id), sig_id),
516 }
517 .clauses;
518
519 ty::GenericClauses { parent, clauses: tcx.arena.alloc_from_iter(clauses) }
520}
521
522fn create_folder_and_args<'tcx>(
523 tcx: TyCtxt<'tcx>,
524 def_id: LocalDefId,
525 sig_id: DefId,
526 parent_args: &'tcx [ty::GenericArg<'tcx>],
527 child_args: &'tcx [ty::GenericArg<'tcx>],
528) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
529 let (args, delegation_parent_args) =
530 create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
531
532 let remap_table = create_mapping(tcx, sig_id, def_id);
533
534 let delegation_parent_consts = delegation_parent_args
535 .iter()
536 .filter_map(|a| {
537 a.as_const().and_then(|c| {
538 if let ty::ConstKind::Param(param) = c.kind() { Some(param) } else { None }
539 })
540 })
541 .collect();
542
543 (ParamIndexRemapper { tcx, remap_table, delegation_parent_consts }, args)
544}
545
546fn check_constraints<'tcx>(
547 tcx: TyCtxt<'tcx>,
548 def_id: LocalDefId,
549 sig_id: DefId,
550) -> Result<(), ErrorGuaranteed> {
551 let mut ret = Ok(());
552
553 let mut emit = |descr| {
554 ret = Err(tcx.dcx().emit_err(crate::diagnostics::UnsupportedDelegation {
555 span: tcx.def_span(def_id),
556 descr,
557 callee_span: tcx.def_span(sig_id),
558 }));
559 };
560
561 if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic() {
562 emit("delegation to C-variadic functions is not allowed");
564 }
565
566 ret
567}
568
569pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
570 tcx: TyCtxt<'tcx>,
571 def_id: LocalDefId,
572) -> &'tcx [Ty<'tcx>] {
573 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id");
574 let caller_sig = tcx.fn_sig(sig_id);
575 if let Err(err) = check_constraints(tcx, def_id, sig_id) {
576 let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
577 let err_type = Ty::new_error(tcx, err);
578 return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
579 }
580
581 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
582 let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
583 let caller_sig = EarlyBinder::bind(tcx, caller_sig.skip_binder().fold_with(&mut folder));
584
585 let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder();
586 let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output()));
587 tcx.arena.alloc_from_iter(sig_iter)
588}
589
590pub(crate) fn delegation_user_specified_args<'tcx>(
595 tcx: TyCtxt<'tcx>,
596 def_id: LocalDefId,
597) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
598 let info = tcx.hir_delegation_info(def_id);
599
600 let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
601 let segment = tcx.hir_node(hir_id).expect_path_segment();
602 segment.res.opt_def_id().map(|def_id| (segment, def_id))
603 };
604
605 let ctx = ItemCtxt::new_for_delegation(tcx, def_id);
606 let lowerer = ctx.lowerer();
607 let parent_args = info
608 .parent_seg_id_for_sig
609 .and_then(get_segment)
610 .filter(|(_, def_id)| #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(*def_id) {
DefKind::Trait => true,
_ => false,
}matches!(tcx.def_kind(*def_id), DefKind::Trait))
611 .map(|(segment, def_id)| {
612 let self_ty = (tcx.def_kind(def_id) == DefKind::Trait)
613 .then(|| Ty::new_param(tcx, 0, kw::SelfUpper));
614
615 lowerer
616 .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty)
617 .0
618 .as_slice()
619 });
620
621 let child_args = info
622 .child_seg_id_for_sig
623 .and_then(get_segment)
624 .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))
625 .map(|(segment, def_id)| {
626 let parent_args = if let Some(parent_args) = parent_args {
627 parent_args
628 } else {
629 let parent = tcx.parent(def_id);
630 if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(parent) {
DefKind::Trait => true,
_ => false,
}matches!(tcx.def_kind(parent), DefKind::Trait) {
631 ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
632 } else {
633 &[]
634 }
635 };
636
637 let args = lowerer
638 .lower_generic_args_of_path(segment.ident.span, def_id, parent_args, segment, None)
639 .0;
640
641 let synth_params_count = tcx.generics_of(def_id).own_synthetic_params_count();
642 &args[parent_args.len()..args.len() - synth_params_count]
643 });
644
645 (parent_args.unwrap_or_default(), child_args.unwrap_or_default())
646}