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