1use std::debug_assert_matches;
6
7use rustc_data_structures::fx::{FxHashMap, FxHashSet};
8use rustc_hir::def::DefKind;
9use rustc_hir::def_id::{DefId, LocalDefId};
10use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment};
11use rustc_middle::ty::{
12 self, EarlyBinder, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
13 TypeVisitableExt,
14};
15use rustc_span::{ErrorGuaranteed, Span, kw};
16
17use crate::collect::ItemCtxt;
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 delegation_parent_consts: FxHashSet<ty::ParamConst>,
26}
27
28impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
29 fn cx(&self) -> TyCtxt<'tcx> {
30 self.tcx
31 }
32
33 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
34 if !ty.has_param() {
35 return ty;
36 }
37
38 if let ty::Param(param) = ty.kind()
39 && let Some(index) = self.remap_table.get(¶m.index)
40 {
41 return Ty::new_param(self.tcx, *index, param.name);
42 }
43 ty.super_fold_with(self)
44 }
45
46 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
47 if let ty::ReEarlyParam(param) = r.kind()
48 && let Some(index) = self.remap_table.get(¶m.index).copied()
49 {
50 return ty::Region::new_early_param(
51 self.tcx,
52 ty::EarlyParamRegion { index, name: param.name },
53 );
54 }
55 r
56 }
57
58 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
59 if let ty::ConstKind::Param(param) = ct.kind()
60 && let Some(idx) = self.remap_table.get(¶m.index)
61 {
62 let param = ty::ParamConst::new(*idx, param.name);
63 return ty::Const::new_param(self.tcx, param);
64 }
65 ct.super_fold_with(self)
66 }
67}
68
69#[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)]
70enum SelfPositionKind {
71 AfterLifetimes(Option<DelegationSelfTyPropagationKind>),
72 Zero,
73 None,
74}
75
76fn create_self_position_kind(
77 tcx: TyCtxt<'_>,
78 delegation_id: LocalDefId,
79 sig_id: DefId,
80) -> SelfPositionKind {
81 match (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)) {
82 (FnKind::AssocInherentImpl, FnKind::AssocTrait)
83 | (FnKind::AssocTraitImpl, FnKind::AssocTrait)
84 | (FnKind::AssocTrait, FnKind::AssocTrait)
85 | (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero,
86
87 (FnKind::Free, FnKind::AssocTrait) => {
88 let kind = tcx.hir_delegation_info(delegation_id).self_ty_propagation_kind;
89 SelfPositionKind::AfterLifetimes(kind)
90 }
91
92 _ => SelfPositionKind::None,
93 }
94}
95
96#[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)]
97enum FnKind {
98 Free,
99 AssocInherentImpl,
100 AssocTrait,
101 AssocTraitImpl,
102}
103
104fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> FnKind {
105 let def_id = def_id.into();
106
107 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);
108
109 let parent = tcx.parent(def_id);
110 match tcx.def_kind(parent) {
111 DefKind::Trait => FnKind::AssocTrait,
112 DefKind::Impl { of_trait: true } => FnKind::AssocTraitImpl,
113 DefKind::Impl { of_trait: false } => FnKind::AssocInherentImpl,
114 _ => FnKind::Free,
115 }
116}
117
118#[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)]
121enum InheritanceKind {
122 WithParent(bool),
132 Own,
136}
137
138fn create_mapping<'tcx>(
148 tcx: TyCtxt<'tcx>,
149 sig_id: DefId,
150 def_id: LocalDefId,
151) -> FxHashMap<u32, u32> {
152 let mut mapping: FxHashMap<u32, u32> = Default::default();
153
154 let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id);
155 let is_self_at_zero = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::Zero => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::Zero);
156
157 if is_self_at_zero {
159 mapping.insert(0, 0);
160 }
161
162 let mut args_index = 0;
163
164 args_index += is_self_at_zero as usize;
165 args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id);
166
167 let sig_generics = tcx.generics_of(sig_id);
168 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);
169
170 if process_sig_parent_generics {
171 for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
172 let param = sig_generics.param_at(i, tcx);
173 if !param.kind.is_ty_or_const() {
174 mapping.insert(param.index, args_index as u32);
175 args_index += 1;
176 }
177 }
178 }
179
180 for param in &sig_generics.own_params {
181 if !param.kind.is_ty_or_const() {
182 mapping.insert(param.index, args_index as u32);
183 args_index += 1;
184 }
185 }
186
187 if #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes { .. } => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes { .. }) {
191 mapping.insert(0, args_index as u32);
192 args_index += 1;
193 }
194
195 if process_sig_parent_generics {
196 for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
197 let param = sig_generics.param_at(i, tcx);
198 if param.kind.is_ty_or_const() {
199 mapping.insert(param.index, args_index as u32);
200 args_index += 1;
201 }
202 }
203 }
204
205 for param in &sig_generics.own_params {
206 if param.kind.is_ty_or_const() {
207 mapping.insert(param.index, args_index as u32);
208 args_index += 1;
209 }
210 }
211
212 mapping
213}
214
215fn get_delegation_parent_args_count_without_self<'tcx>(
216 tcx: TyCtxt<'tcx>,
217 delegation_id: LocalDefId,
218 sig_id: DefId,
219) -> usize {
220 let delegation_parent_args_count = tcx.generics_of(delegation_id).parent_count;
221
222 match (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)) {
223 (FnKind::Free, FnKind::Free)
224 | (FnKind::Free, FnKind::AssocTrait)
225 | (FnKind::AssocTraitImpl, FnKind::AssocTrait) => 0,
226
227 (FnKind::AssocInherentImpl, FnKind::Free)
228 | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
229 delegation_parent_args_count }
231
232 (FnKind::AssocTrait, FnKind::Free) | (FnKind::AssocTrait, FnKind::AssocTrait) => {
233 delegation_parent_args_count - 1 }
235
236 (FnKind::AssocTraitImpl, _)
239 | (_, FnKind::AssocTraitImpl)
240 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
241 }
242}
243
244fn get_parent_and_inheritance_kind<'tcx>(
245 tcx: TyCtxt<'tcx>,
246 def_id: LocalDefId,
247 sig_id: DefId,
248) -> (Option<DefId>, InheritanceKind) {
249 match (fn_kind(tcx, def_id), fn_kind(tcx, sig_id)) {
250 (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
251 (None, InheritanceKind::WithParent(true))
252 }
253
254 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
255 (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::Own)
256 }
257
258 (FnKind::AssocInherentImpl, FnKind::AssocTrait)
259 | (FnKind::AssocTrait, FnKind::AssocTrait)
260 | (FnKind::AssocInherentImpl, FnKind::Free)
261 | (FnKind::AssocTrait, FnKind::Free) => {
262 (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::WithParent(false))
263 }
264
265 (FnKind::AssocTraitImpl, _)
268 | (_, FnKind::AssocTraitImpl)
269 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
270 }
271}
272
273fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) -> Option<Ty<'tcx>> {
274 let sig_id = tcx.hir_opt_delegation_sig_id(delegation_id).expect("Delegation must have sig_id");
275 let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id));
276
277 match (caller_kind, callee_kind) {
278 (FnKind::Free, FnKind::AssocTrait)
279 | (FnKind::AssocInherentImpl, FnKind::Free)
280 | (FnKind::Free, FnKind::Free)
281 | (FnKind::AssocTrait, FnKind::Free)
282 | (FnKind::AssocTrait, FnKind::AssocTrait) => {
283 match create_self_position_kind(tcx, delegation_id, sig_id) {
284 SelfPositionKind::None => None,
285 SelfPositionKind::AfterLifetimes(propagation_kind) => {
286 Some(match propagation_kind {
287 Some(kind) => match kind {
288 DelegationSelfTyPropagationKind::SelfTy(self_ty_id) => {
289 let ctx = ItemCtxt::new(tcx, delegation_id);
290 ctx.lower_ty(tcx.hir_node(self_ty_id).expect_ty())
291 }
292 DelegationSelfTyPropagationKind::SelfParam => {
293 let index = tcx.generics_of(delegation_id).own_counts().lifetimes;
294 Ty::new_param(tcx, index as u32, kw::SelfUpper)
295 }
296 },
297 None => Ty::new_error_with_message(
298 tcx,
299 tcx.def_span(delegation_id),
300 "self propagation kind must be specified for `AfterLifetimes` variant",
301 ),
302 })
303 }
304 SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)),
305 }
306 }
307
308 (FnKind::AssocTraitImpl, FnKind::AssocTrait)
309 | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => Some(
310 tcx.type_of(tcx.local_parent(delegation_id)).instantiate_identity().skip_norm_wip(),
311 ),
312
313 (FnKind::AssocTraitImpl, _)
316 | (_, FnKind::AssocTraitImpl)
317 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
318 }
319}
320
321fn create_generic_args<'tcx>(
337 tcx: TyCtxt<'tcx>,
338 sig_id: DefId,
339 delegation_id: LocalDefId,
340 mut parent_args: &[ty::GenericArg<'tcx>],
341 mut child_args: &[ty::GenericArg<'tcx>],
342) -> (Vec<ty::GenericArg<'tcx>>, &'tcx [ty::GenericArg<'tcx>]) {
343 let delegation_generics = tcx.generics_of(delegation_id);
344 let delegation_args = ty::GenericArgs::identity_for_item(tcx, delegation_id);
345
346 let real_args_count = delegation_args.len() - delegation_generics.own_synthetic_params_count();
347 let synth_args = &delegation_args[real_args_count..];
348
349 let mut delegation_parent_args =
350 &delegation_args[delegation_generics.has_self as usize..delegation_generics.parent_count];
351
352 let delegation_args = &delegation_args[delegation_generics.parent_count..];
353
354 let kinds = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id));
355 if #[allow(non_exhaustive_omitted_patterns)] match kinds {
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => true,
_ => false,
}matches!(kinds, (FnKind::AssocTraitImpl, FnKind::AssocTrait)) {
356 let parent = tcx.local_parent(delegation_id);
360
361 parent_args =
362 tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args;
363
364 child_args =
365 &delegation_args[delegation_args.len() - delegation_generics.own_params.len()..];
366
367 delegation_parent_args = &[];
368 }
369
370 let self_type = get_delegation_self_ty(tcx, delegation_id).map(|t| t.into());
371
372 if self_type.is_some() && !parent_args.is_empty() {
375 parent_args = &parent_args[1..];
376 }
377
378 let (zero_self, after_lifetimes_self) =
379 match create_self_position_kind(tcx, delegation_id, sig_id) {
380 SelfPositionKind::AfterLifetimes(_) => {
381 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
382 (None, self_type)
383 }
384 SelfPositionKind::Zero => {
385 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
386 (self_type, None)
387 }
388 SelfPositionKind::None => (None, None),
389 };
390
391 let zero_self = zero_self.as_ref().into_iter();
392 let after_lifetimes_self = after_lifetimes_self.as_ref().into_iter();
393
394 let args = zero_self
395 .chain(delegation_parent_args)
396 .chain(parent_args.iter().filter(|a| a.as_region().is_some()))
397 .chain(child_args.iter().filter(|a| a.as_region().is_some()))
398 .chain(after_lifetimes_self)
399 .chain(parent_args.iter().filter(|a| a.as_region().is_none()))
400 .chain(child_args.iter().filter(|a| a.as_region().is_none()))
401 .chain(synth_args)
402 .copied()
403 .collect::<Vec<_>>();
404
405 (args, delegation_parent_args)
406}
407
408pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
409 tcx: TyCtxt<'tcx>,
410 def_id: LocalDefId,
411 sig_id: DefId,
412) -> ty::GenericPredicates<'tcx> {
413 struct PredicatesCollector<'tcx> {
414 tcx: TyCtxt<'tcx>,
415 preds: Vec<(ty::Clause<'tcx>, Span)>,
416 args: Vec<ty::GenericArg<'tcx>>,
417 folder: ParamIndexRemapper<'tcx>,
418 filter_self_preds: bool,
419 }
420
421 impl<'tcx> PredicatesCollector<'tcx> {
422 fn with_own_preds(
423 mut self,
424 f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
425 def_id: DefId,
426 ) -> Self {
427 let preds = f(def_id);
428 let args = self.args.as_slice();
429
430 for pred in preds.predicates {
431 if self.filter_self_preds
434 && let Some(trait_pred) = pred.0.as_trait_clause()
435 && trait_pred.self_ty().skip_binder().is_param(0)
437 {
438 continue;
439 }
440
441 if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) =
469 pred.0.as_predicate().fold_with(&mut self.folder).kind().skip_binder()
470 {
471 let unnorm_const = EarlyBinder::bind(self.tcx, ct).instantiate(self.tcx, args);
472 if let ty::ConstKind::Param(param) = unnorm_const.skip_norm_wip().kind()
473 && self.folder.delegation_parent_consts.contains(¶m)
474 {
475 continue;
476 }
477 }
478
479 let new_pred = pred.0.fold_with(&mut self.folder);
480 self.preds.push((
481 EarlyBinder::bind(self.tcx, new_pred)
482 .instantiate(self.tcx, args)
483 .skip_norm_wip(),
484 pred.1,
485 ));
486 }
487
488 self
489 }
490
491 fn with_preds(
492 mut self,
493 f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
494 def_id: DefId,
495 ) -> Self {
496 let preds = f(def_id);
497 if let Some(parent_def_id) = preds.parent {
498 self = self.with_own_preds(f, parent_def_id);
499 }
500
501 self.with_own_preds(f, def_id)
502 }
503 }
504
505 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
506 let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
507 let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id);
508 let filter_self_preds = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
=> true,
_ => false,
}matches!(
509 self_pos_kind,
510 SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
511 );
512
513 let collector = PredicatesCollector { tcx, preds: ::alloc::vec::Vec::new()vec![], args, folder, filter_self_preds };
514 let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
515
516 let preds = match inh_kind {
520 InheritanceKind::WithParent(false) => {
521 collector.with_preds(|def_id| tcx.explicit_predicates_of(def_id), sig_id)
522 }
523 InheritanceKind::WithParent(true) => {
524 collector.with_preds(|def_id| tcx.predicates_of(def_id), sig_id)
525 }
526 InheritanceKind::Own => {
527 collector.with_own_preds(|def_id| tcx.predicates_of(def_id), sig_id)
528 }
529 }
530 .preds;
531
532 ty::GenericPredicates { parent, predicates: tcx.arena.alloc_from_iter(preds) }
533}
534
535fn create_folder_and_args<'tcx>(
536 tcx: TyCtxt<'tcx>,
537 def_id: LocalDefId,
538 sig_id: DefId,
539 parent_args: &'tcx [ty::GenericArg<'tcx>],
540 child_args: &'tcx [ty::GenericArg<'tcx>],
541) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
542 let (args, delegation_parent_args) =
543 create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
544
545 let remap_table = create_mapping(tcx, sig_id, def_id);
546
547 let delegation_parent_consts = delegation_parent_args
548 .iter()
549 .filter_map(|a| {
550 a.as_const().and_then(|c| {
551 if let ty::ConstKind::Param(param) = c.kind() { Some(param) } else { None }
552 })
553 })
554 .collect();
555
556 (ParamIndexRemapper { tcx, remap_table, delegation_parent_consts }, args)
557}
558
559fn check_constraints<'tcx>(
560 tcx: TyCtxt<'tcx>,
561 def_id: LocalDefId,
562 sig_id: DefId,
563) -> Result<(), ErrorGuaranteed> {
564 let mut ret = Ok(());
565
566 let mut emit = |descr| {
567 ret = Err(tcx.dcx().emit_err(crate::diagnostics::UnsupportedDelegation {
568 span: tcx.def_span(def_id),
569 descr,
570 callee_span: tcx.def_span(sig_id),
571 }));
572 };
573
574 if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic() {
575 emit("delegation to C-variadic functions is not allowed");
577 }
578
579 ret
580}
581
582pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
583 tcx: TyCtxt<'tcx>,
584 def_id: LocalDefId,
585) -> &'tcx [Ty<'tcx>] {
586 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id");
587 let caller_sig = tcx.fn_sig(sig_id);
588
589 if let Err(err) = check_constraints(tcx, def_id, sig_id) {
590 let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
591 let err_type = Ty::new_error(tcx, err);
592 return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
593 }
594
595 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
596 let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
597 let caller_sig = EarlyBinder::bind(tcx, caller_sig.skip_binder().fold_with(&mut folder));
598
599 let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder();
600 let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output()));
601 tcx.arena.alloc_from_iter(sig_iter)
602}
603
604pub(crate) fn delegation_user_specified_args<'tcx>(
609 tcx: TyCtxt<'tcx>,
610 delegation_id: LocalDefId,
611) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
612 let info = tcx.hir_delegation_info(delegation_id);
613
614 let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
615 let segment = tcx.hir_node(hir_id).expect_path_segment();
616 segment.res.opt_def_id().map(|def_id| (segment, def_id))
617 };
618
619 let ctx = ItemCtxt::new_for_delegation(tcx, delegation_id);
620 let lowerer = ctx.lowerer();
621 let parent_args = info
622 .parent_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::Trait => true,
_ => false,
}matches!(tcx.def_kind(*def_id), DefKind::Trait))
625 .map(|(segment, def_id)| {
626 let self_ty = get_delegation_self_ty(tcx, delegation_id);
627
628 lowerer
629 .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty)
630 .0
631 .as_slice()
632 });
633
634 let child_args = info
635 .child_seg_id_for_sig
636 .and_then(get_segment)
637 .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))
638 .map(|(segment, def_id)| {
639 let parent_args = if let Some(parent_args) = parent_args {
640 parent_args
641 } else {
642 let parent = tcx.parent(def_id);
643 if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(parent) {
DefKind::Trait => true,
_ => false,
}matches!(tcx.def_kind(parent), DefKind::Trait) {
644 ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
645 } else {
646 &[]
647 }
648 };
649
650 let args = lowerer
651 .lower_generic_args_of_path(segment.ident.span, def_id, parent_args, segment, None)
652 .0;
653
654 let synth_params_count = tcx.generics_of(def_id).own_synthetic_params_count();
655 &args[parent_args.len()..args.len() - synth_params_count]
656 });
657
658 (parent_args.unwrap_or_default(), child_args.unwrap_or_default())
659}