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