Skip to main content

rustc_hir_analysis/
delegation.rs

1//! Support inheriting generic parameters and predicates for function delegation.
2//!
3//! For more information about delegation design, see the tracking issue #118212.
4
5use rustc_data_structures::debug_assert_matches;
6use rustc_data_structures::fx::FxHashMap;
7use rustc_hir::def::DefKind;
8use rustc_hir::def_id::{DefId, LocalDefId};
9use rustc_hir::{HirId, PathSegment};
10use rustc_middle::ty::{
11    self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
12};
13use rustc_span::{ErrorGuaranteed, Span, kw};
14
15use crate::collect::ItemCtxt;
16use crate::hir_ty_lowering::{GenericArgPosition, HirTyLowerer};
17
18type RemapTable = FxHashMap<u32, u32>;
19
20struct ParamIndexRemapper<'tcx> {
21    tcx: TyCtxt<'tcx>,
22    remap_table: RemapTable,
23}
24
25impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
26    fn cx(&self) -> TyCtxt<'tcx> {
27        self.tcx
28    }
29
30    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
31        if !ty.has_param() {
32            return ty;
33        }
34
35        if let ty::Param(param) = ty.kind()
36            && let Some(index) = self.remap_table.get(&param.index)
37        {
38            return Ty::new_param(self.tcx, *index, param.name);
39        }
40        ty.super_fold_with(self)
41    }
42
43    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
44        if let ty::ReEarlyParam(param) = r.kind()
45            && let Some(index) = self.remap_table.get(&param.index).copied()
46        {
47            return ty::Region::new_early_param(
48                self.tcx,
49                ty::EarlyParamRegion { index, name: param.name },
50            );
51        }
52        r
53    }
54
55    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
56        if let ty::ConstKind::Param(param) = ct.kind()
57            && let Some(idx) = self.remap_table.get(&param.index)
58        {
59            let param = ty::ParamConst::new(*idx, param.name);
60            return ty::Const::new_param(self.tcx, param);
61        }
62        ct.super_fold_with(self)
63    }
64}
65
66enum SelfPositionKind {
67    AfterLifetimes,
68    Zero,
69    None,
70}
71
72fn create_self_position_kind(caller_kind: FnKind, callee_kind: FnKind) -> SelfPositionKind {
73    match (caller_kind, callee_kind) {
74        (FnKind::AssocInherentImpl, FnKind::AssocTrait)
75        | (FnKind::AssocTraitImpl, FnKind::AssocTrait)
76        | (FnKind::AssocTrait, FnKind::AssocTrait)
77        | (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero,
78
79        (FnKind::Free, FnKind::AssocTrait) => SelfPositionKind::AfterLifetimes,
80
81        _ => SelfPositionKind::None,
82    }
83}
84
85#[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)]
86enum FnKind {
87    Free,
88    AssocInherentImpl,
89    AssocTrait,
90    AssocTraitImpl,
91}
92
93fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> FnKind {
94    let def_id = def_id.into();
95
96    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);
97
98    let parent = tcx.parent(def_id);
99    match tcx.def_kind(parent) {
100        DefKind::Trait => FnKind::AssocTrait,
101        DefKind::Impl { of_trait: true } => FnKind::AssocTraitImpl,
102        DefKind::Impl { of_trait: false } => FnKind::AssocInherentImpl,
103        _ => FnKind::Free,
104    }
105}
106
107/// Given the current context(caller and callee `FnKind`), it specifies
108/// the policy of predicates and generic parameters inheritance.
109#[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)]
110enum InheritanceKind {
111    /// Copying all predicates and parameters, including those of the parent
112    /// container.
113    ///
114    /// Boolean value defines whether the `Self` parameter or `Self: Trait`
115    /// predicate are copied. It's always equal to `false` except when
116    /// delegating from a free function to a trait method.
117    ///
118    /// FIXME(fn_delegation): This often leads to type inference
119    /// errors. Support providing generic arguments or restrict use sites.
120    WithParent(bool),
121    /// The trait implementation should be compatible with the original trait.
122    /// Therefore, for trait implementations only the method's own parameters
123    /// and predicates are copied.
124    Own,
125}
126
127/// Maps sig generics into generic args of delegation. Delegation generics has the following pattern:
128///
129/// [SELF | maybe self in the beginning]
130/// [PARENT | args of delegation parent]
131/// [SIG PARENT LIFETIMES]
132/// [SIG LIFETIMES]
133/// [SELF | maybe self after lifetimes, when we reuse trait fn in free context]
134/// [SIG PARENT TYPES/CONSTS]
135/// [SIG TYPES/CONSTS]
136fn create_mapping<'tcx>(
137    tcx: TyCtxt<'tcx>,
138    sig_id: DefId,
139    def_id: LocalDefId,
140    args: &[ty::GenericArg<'tcx>],
141) -> FxHashMap<u32, u32> {
142    let mut mapping: FxHashMap<u32, u32> = Default::default();
143
144    let (caller_kind, callee_kind) = (fn_kind(tcx, def_id), fn_kind(tcx, sig_id));
145    let self_pos_kind = create_self_position_kind(caller_kind, callee_kind);
146    let is_self_at_zero = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
    SelfPositionKind::Zero => true,
    _ => false,
}matches!(self_pos_kind, SelfPositionKind::Zero);
147
148    // Is self at zero? If so insert mapping, self in sig parent is always at 0.
149    if is_self_at_zero {
150        mapping.insert(0, 0);
151    }
152
153    let mut args_index = 0;
154
155    args_index += is_self_at_zero as usize;
156    args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id);
157
158    let sig_generics = tcx.generics_of(sig_id);
159    let process_sig_parent_generics = #[allow(non_exhaustive_omitted_patterns)] match callee_kind {
    FnKind::AssocTrait => true,
    _ => false,
}matches!(callee_kind, FnKind::AssocTrait);
160
161    if process_sig_parent_generics {
162        for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
163            let param = sig_generics.param_at(i, tcx);
164            if !param.kind.is_ty_or_const() {
165                mapping.insert(param.index, args_index as u32);
166                args_index += 1;
167            }
168        }
169    }
170
171    for param in &sig_generics.own_params {
172        if !param.kind.is_ty_or_const() {
173            mapping.insert(param.index, args_index as u32);
174            args_index += 1;
175        }
176    }
177
178    // If there are still unmapped lifetimes left and we are to map types and maybe self
179    // then skip them, now it is the case when we generated more lifetimes then needed.
180    // FIXME(fn_delegation): proper support for late bound lifetimes.
181    while args_index < args.len() && args[args_index].as_region().is_some() {
182        args_index += 1;
183    }
184
185    // If self after lifetimes insert mapping, relying that self is at 0 in sig parent.
186    if #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
    SelfPositionKind::AfterLifetimes => true,
    _ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes) {
187        mapping.insert(0, args_index as u32);
188        args_index += 1;
189    }
190
191    if process_sig_parent_generics {
192        for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
193            let param = sig_generics.param_at(i, tcx);
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
201    for param in &sig_generics.own_params {
202        if param.kind.is_ty_or_const() {
203            mapping.insert(param.index, args_index as u32);
204            args_index += 1;
205        }
206    }
207
208    mapping
209}
210
211fn get_delegation_parent_args_count_without_self<'tcx>(
212    tcx: TyCtxt<'tcx>,
213    delegation_id: LocalDefId,
214    sig_id: DefId,
215) -> usize {
216    let delegation_parent_args_count = tcx.generics_of(delegation_id).parent_count;
217
218    match (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)) {
219        (FnKind::Free, FnKind::Free)
220        | (FnKind::Free, FnKind::AssocTrait)
221        | (FnKind::AssocTraitImpl, FnKind::AssocTrait) => 0,
222
223        (FnKind::AssocInherentImpl, FnKind::Free)
224        | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
225            delegation_parent_args_count /* No Self in AssocInherentImpl */
226        }
227
228        (FnKind::AssocTrait, FnKind::Free) | (FnKind::AssocTrait, FnKind::AssocTrait) => {
229            delegation_parent_args_count - 1 /* Without Self */
230        }
231
232        // For trait impl's `sig_id` is always equal to the corresponding trait method.
233        // For inherent methods delegation is not yet supported.
234        (FnKind::AssocTraitImpl, _)
235        | (_, FnKind::AssocTraitImpl)
236        | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
237    }
238}
239
240fn get_parent_and_inheritance_kind<'tcx>(
241    tcx: TyCtxt<'tcx>,
242    def_id: LocalDefId,
243    sig_id: DefId,
244) -> (Option<DefId>, InheritanceKind) {
245    match (fn_kind(tcx, def_id), fn_kind(tcx, sig_id)) {
246        (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
247            (None, InheritanceKind::WithParent(true))
248        }
249
250        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
251            (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::Own)
252        }
253
254        (FnKind::AssocInherentImpl, FnKind::AssocTrait)
255        | (FnKind::AssocTrait, FnKind::AssocTrait)
256        | (FnKind::AssocInherentImpl, FnKind::Free)
257        | (FnKind::AssocTrait, FnKind::Free) => {
258            (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::WithParent(false))
259        }
260
261        // For trait impl's `sig_id` is always equal to the corresponding trait method.
262        // For inherent methods delegation is not yet supported.
263        (FnKind::AssocTraitImpl, _)
264        | (_, FnKind::AssocTraitImpl)
265        | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
266    }
267}
268
269fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) -> Option<Ty<'tcx>> {
270    let sig_id = tcx.hir_opt_delegation_sig_id(delegation_id).expect("Delegation must have sig_id");
271    let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id));
272
273    match (caller_kind, callee_kind) {
274        (FnKind::Free, FnKind::AssocTrait)
275        | (FnKind::AssocInherentImpl, FnKind::Free)
276        | (FnKind::Free, FnKind::Free)
277        | (FnKind::AssocTrait, FnKind::Free)
278        | (FnKind::AssocTrait, FnKind::AssocTrait) => {
279            match create_self_position_kind(caller_kind, callee_kind) {
280                SelfPositionKind::None => None,
281                SelfPositionKind::AfterLifetimes => {
282                    // Both sig parent and child lifetimes are in included in this count.
283                    Some(tcx.generics_of(delegation_id).own_counts().lifetimes)
284                }
285                SelfPositionKind::Zero => Some(0),
286            }
287            .map(|self_index| Ty::new_param(tcx, self_index as u32, kw::SelfUpper))
288        }
289
290        (FnKind::AssocTraitImpl, FnKind::AssocTrait)
291        | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
292            Some(tcx.type_of(tcx.local_parent(delegation_id)).instantiate_identity())
293        }
294
295        // For trait impl's `sig_id` is always equal to the corresponding trait method.
296        // For inherent methods delegation is not yet supported.
297        (FnKind::AssocTraitImpl, _)
298        | (_, FnKind::AssocTraitImpl)
299        | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
300    }
301}
302
303/// Creates generic arguments for further delegation signature and predicates instantiation.
304/// Arguments can be user-specified (in this case they are in `parent_args` and `child_args`)
305/// or propagated. User can specify either both `parent_args` and `child_args`, one of them or none,
306/// that is why we firstly create generic arguments from generic params and then adjust them with
307/// user-specified args.
308///
309/// The order of produced list is important, it must be of this pattern:
310///
311/// [SELF | maybe self in the beginning]
312/// [PARENT | args of delegation parent]
313/// [SIG PARENT LIFETIMES] <- `lifetimes_end_pos`
314/// [SIG LIFETIMES]
315/// [SELF | maybe self after lifetimes, when we reuse trait fn in free context]
316/// [SIG PARENT TYPES/CONSTS]
317/// [SIG TYPES/CONSTS]
318fn create_generic_args<'tcx>(
319    tcx: TyCtxt<'tcx>,
320    sig_id: DefId,
321    delegation_id: LocalDefId,
322    mut parent_args: &[ty::GenericArg<'tcx>],
323    child_args: &[ty::GenericArg<'tcx>],
324) -> Vec<ty::GenericArg<'tcx>> {
325    let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id));
326
327    let delegation_args = ty::GenericArgs::identity_for_item(tcx, delegation_id);
328    let delegation_parent_args_count = tcx.generics_of(delegation_id).parent_count;
329
330    let deleg_parent_args_without_self_count =
331        get_delegation_parent_args_count_without_self(tcx, delegation_id, sig_id);
332
333    let args = match (caller_kind, callee_kind) {
334        (FnKind::Free, FnKind::Free)
335        | (FnKind::Free, FnKind::AssocTrait)
336        | (FnKind::AssocInherentImpl, FnKind::Free)
337        | (FnKind::AssocTrait, FnKind::Free)
338        | (FnKind::AssocTrait, FnKind::AssocTrait) => delegation_args,
339
340        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
341            // Special case, as user specifies Trait args in impl trait header, we want to treat
342            // them as parent args.
343            let parent = tcx.local_parent(delegation_id);
344            parent_args = tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args;
345            tcx.mk_args(&delegation_args[delegation_parent_args_count..])
346        }
347
348        (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
349            let self_ty = tcx.type_of(tcx.local_parent(delegation_id)).instantiate_identity();
350
351            tcx.mk_args_from_iter(
352                std::iter::once(ty::GenericArg::from(self_ty)).chain(delegation_args.iter()),
353            )
354        }
355
356        // For trait impl's `sig_id` is always equal to the corresponding trait method.
357        // For inherent methods delegation is not yet supported.
358        (FnKind::AssocTraitImpl, _)
359        | (_, FnKind::AssocTraitImpl)
360        | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
361    };
362
363    let mut new_args = ::alloc::vec::Vec::new()vec![];
364
365    let self_pos_kind = create_self_position_kind(caller_kind, callee_kind);
366    let mut lifetimes_end_pos;
367
368    if !parent_args.is_empty() {
369        let parent_args_lifetimes_count =
370            parent_args.iter().filter(|a| a.as_region().is_some()).count();
371
372        match self_pos_kind {
373            SelfPositionKind::AfterLifetimes => {
374                new_args.extend(&parent_args[1..1 + parent_args_lifetimes_count]);
375
376                lifetimes_end_pos = parent_args_lifetimes_count;
377
378                new_args.push(parent_args[0]);
379
380                new_args.extend(&parent_args[1 + parent_args_lifetimes_count..]);
381            }
382            SelfPositionKind::Zero => {
383                lifetimes_end_pos = 1 /* Self */ + parent_args_lifetimes_count;
384                new_args.extend_from_slice(parent_args);
385
386                for i in 0..deleg_parent_args_without_self_count {
387                    new_args.insert(1 + i, args[1 + i]);
388                }
389
390                lifetimes_end_pos += deleg_parent_args_without_self_count;
391            }
392            // If we have parent args then we obtained them from trait, then self must be somewhere
393            SelfPositionKind::None => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
394        };
395    } else {
396        let self_impact = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
    SelfPositionKind::Zero => true,
    _ => false,
}matches!(self_pos_kind, SelfPositionKind::Zero) as usize;
397
398        lifetimes_end_pos = self_impact
399            + deleg_parent_args_without_self_count
400            + &args[self_impact + deleg_parent_args_without_self_count..]
401                .iter()
402                .filter(|a| a.as_region().is_some())
403                .count();
404
405        new_args.extend_from_slice(args);
406    }
407
408    if !child_args.is_empty() {
409        let child_lifetimes_count = child_args.iter().filter(|a| a.as_region().is_some()).count();
410
411        for i in 0..child_lifetimes_count {
412            new_args.insert(lifetimes_end_pos + i, child_args[i]);
413        }
414
415        new_args.extend_from_slice(&child_args[child_lifetimes_count..]);
416    } else if !parent_args.is_empty() {
417        let child_args = &delegation_args[delegation_parent_args_count..];
418
419        let child_lifetimes_count =
420            child_args.iter().take_while(|a| a.as_region().is_some()).count();
421
422        for i in 0..child_lifetimes_count {
423            new_args.insert(lifetimes_end_pos + i, child_args[i]);
424        }
425
426        let skip_self = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
    SelfPositionKind::AfterLifetimes => true,
    _ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes);
427        new_args.extend(&child_args[child_lifetimes_count + skip_self as usize..]);
428    }
429
430    new_args
431}
432
433pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
434    tcx: TyCtxt<'tcx>,
435    def_id: LocalDefId,
436    sig_id: DefId,
437) -> ty::GenericPredicates<'tcx> {
438    struct PredicatesCollector<'tcx> {
439        tcx: TyCtxt<'tcx>,
440        preds: Vec<(ty::Clause<'tcx>, Span)>,
441        args: Vec<ty::GenericArg<'tcx>>,
442        folder: ParamIndexRemapper<'tcx>,
443    }
444
445    impl<'tcx> PredicatesCollector<'tcx> {
446        fn with_own_preds(
447            mut self,
448            f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
449            def_id: DefId,
450        ) -> Self {
451            let preds = f(def_id);
452            let args = self.args.as_slice();
453
454            for pred in preds.predicates {
455                let new_pred = pred.0.fold_with(&mut self.folder);
456                self.preds.push((EarlyBinder::bind(new_pred).instantiate(self.tcx, args), pred.1));
457            }
458
459            self
460        }
461
462        fn with_preds(
463            mut self,
464            f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
465            def_id: DefId,
466        ) -> Self {
467            let preds = f(def_id);
468            if let Some(parent_def_id) = preds.parent {
469                self = self.with_own_preds(f, parent_def_id);
470            }
471
472            self.with_own_preds(f, def_id)
473        }
474    }
475
476    let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id);
477    let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
478    let collector = PredicatesCollector { tcx, preds: ::alloc::vec::Vec::new()vec![], args, folder };
479
480    let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
481
482    // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
483    // Note: `predicates_of` query can also add inferred outlives predicates, but that
484    // is not the case here as `sig_id` is either a trait or a function.
485    let preds = match inh_kind {
486        InheritanceKind::WithParent(false) => {
487            collector.with_preds(|def_id| tcx.explicit_predicates_of(def_id), sig_id)
488        }
489        InheritanceKind::WithParent(true) => {
490            collector.with_preds(|def_id| tcx.predicates_of(def_id), sig_id)
491        }
492        InheritanceKind::Own => {
493            collector.with_own_preds(|def_id| tcx.predicates_of(def_id), sig_id)
494        }
495    }
496    .preds;
497
498    ty::GenericPredicates { parent, predicates: tcx.arena.alloc_from_iter(preds) }
499}
500
501fn create_folder_and_args<'tcx>(
502    tcx: TyCtxt<'tcx>,
503    def_id: LocalDefId,
504    sig_id: DefId,
505    parent_args: &'tcx [ty::GenericArg<'tcx>],
506    child_args: &'tcx [ty::GenericArg<'tcx>],
507) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
508    let args = create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
509    let remap_table = create_mapping(tcx, sig_id, def_id, &args);
510
511    (ParamIndexRemapper { tcx, remap_table }, args)
512}
513
514fn check_constraints<'tcx>(
515    tcx: TyCtxt<'tcx>,
516    def_id: LocalDefId,
517    sig_id: DefId,
518) -> Result<(), ErrorGuaranteed> {
519    let mut ret = Ok(());
520
521    let mut emit = |descr| {
522        ret = Err(tcx.dcx().emit_err(crate::errors::UnsupportedDelegation {
523            span: tcx.def_span(def_id),
524            descr,
525            callee_span: tcx.def_span(sig_id),
526        }));
527    };
528
529    if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic {
530        // See issue #127443 for explanation.
531        emit("delegation to C-variadic functions is not allowed");
532    }
533
534    ret
535}
536
537pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
538    tcx: TyCtxt<'tcx>,
539    def_id: LocalDefId,
540) -> &'tcx [Ty<'tcx>] {
541    let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id");
542    let caller_sig = tcx.fn_sig(sig_id);
543
544    if let Err(err) = check_constraints(tcx, def_id, sig_id) {
545        let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
546        let err_type = Ty::new_error(tcx, err);
547        return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
548    }
549
550    let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id);
551    let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
552    let caller_sig = EarlyBinder::bind(caller_sig.skip_binder().fold_with(&mut folder));
553
554    let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder();
555    let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output()));
556    tcx.arena.alloc_from_iter(sig_iter)
557}
558
559// Creates user-specified generic arguments from delegation path,
560// they will be used during delegation signature and predicates inheritance.
561// Example: reuse Trait::<'static, i32, 1>::foo::<A, B>
562// we want to extract [Self, 'static, i32, 1] for parent and [A, B] for child.
563fn get_delegation_user_specified_args<'tcx>(
564    tcx: TyCtxt<'tcx>,
565    delegation_id: LocalDefId,
566) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
567    let info = tcx
568        .hir_node(tcx.local_def_id_to_hir_id(delegation_id))
569        .fn_sig()
570        .expect("Lowering delegation")
571        .decl
572        .opt_delegation_generics()
573        .expect("Lowering delegation");
574
575    let get_segment = |hir_id: HirId| -> (&'tcx PathSegment<'tcx>, DefId) {
576        let segment = tcx.hir_node(hir_id).expect_path_segment();
577        let def_id = segment.res.def_id();
578
579        (segment, def_id)
580    };
581
582    let ctx = ItemCtxt::new(tcx, delegation_id);
583    let lowerer = ctx.lowerer();
584
585    let parent_args = info.parent_args_segment_id.map(get_segment).map(|(segment, def_id)| {
586        let self_ty = get_delegation_self_ty(tcx, delegation_id);
587
588        lowerer
589            .lower_generic_args_of_path(
590                segment.ident.span,
591                def_id,
592                &[],
593                segment,
594                self_ty,
595                GenericArgPosition::Type,
596            )
597            .0
598            .as_slice()
599    });
600
601    let child_args = info.child_args_segment_id.map(get_segment).map(|(segment, def_id)| {
602        let parent_args = if let Some(parent_args) = parent_args {
603            parent_args
604        } else {
605            let parent = tcx.parent(def_id);
606            if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(parent) {
    DefKind::Trait => true,
    _ => false,
}matches!(tcx.def_kind(parent), DefKind::Trait) {
607                ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
608            } else {
609                &[]
610            }
611        };
612
613        let args = lowerer
614            .lower_generic_args_of_path(
615                segment.ident.span,
616                def_id,
617                parent_args,
618                segment,
619                None,
620                GenericArgPosition::Value,
621            )
622            .0;
623
624        &args[parent_args.len()..]
625    });
626
627    (parent_args.unwrap_or_default(), child_args.unwrap_or_default())
628}