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, 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(&param.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(&param.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(&param.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/// Given the current context(caller and callee `FnKind`), it specifies
119/// the policy of predicates and generic parameters inheritance.
120#[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    /// Copying all predicates and parameters, including those of the parent
123    /// container.
124    ///
125    /// Boolean value defines whether the `Self` parameter or `Self: Trait`
126    /// predicate are copied. It's always equal to `false` except when
127    /// delegating from a free function to a trait method.
128    ///
129    /// FIXME(fn_delegation): This often leads to type inference
130    /// errors. Support providing generic arguments or restrict use sites.
131    WithParent(bool),
132    /// The trait implementation should be compatible with the original trait.
133    /// Therefore, for trait implementations only the method's own parameters
134    /// and predicates are copied.
135    Own,
136}
137
138/// Maps sig generics into generic args of delegation. Delegation generics has the following pattern:
139///
140/// [SELF | maybe self in the beginning]
141/// [PARENT | args of delegation parent]
142/// [SIG PARENT LIFETIMES]
143/// [SIG LIFETIMES]
144/// [SELF | maybe self after lifetimes, when we reuse trait fn in free context]
145/// [SIG PARENT TYPES/CONSTS]
146/// [SIG TYPES/CONSTS]
147fn 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    // Is self at zero? If so insert mapping, self in sig parent is always at 0.
158    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 self after lifetimes insert mapping, relying that self is at 0 in sig parent.
188    // If self ty is propagated (meaning there is no generic param `Self`), the specified
189    // self ty will be inserted in args in `create_generic_args`.
190    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 /* No Self in AssocInherentImpl */
230        }
231
232        (FnKind::AssocTrait, FnKind::Free) | (FnKind::AssocTrait, FnKind::AssocTrait) => {
233            delegation_parent_args_count - 1 /* Without Self */
234        }
235
236        // For trait impl's `sig_id` is always equal to the corresponding trait method.
237        // For inherent methods delegation is not yet supported.
238        (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        // For trait impl's `sig_id` is always equal to the corresponding trait method.
266        // For inherent methods delegation is not yet supported.
267        (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        // For trait impl's `sig_id` is always equal to the corresponding trait method.
314        // For inherent methods delegation is not yet supported.
315        (FnKind::AssocTraitImpl, _)
316        | (_, FnKind::AssocTraitImpl)
317        | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
318    }
319}
320
321/// Creates generic arguments for further delegation signature and predicates instantiation.
322/// Arguments can be user-specified (in this case they are in `parent_args` and `child_args`)
323/// or propagated. User can specify either both `parent_args` and `child_args`, one of them or none,
324/// that is why we firstly create generic arguments from generic params and then adjust them with
325/// user-specified args.
326///
327/// The order of produced list is important, it must be of this pattern:
328///
329/// [SELF | maybe self in the beginning]
330/// [PARENT | args of delegation parent]
331/// [SIG PARENT LIFETIMES] <- `lifetimes_end_pos`
332/// [SIG LIFETIMES]
333/// [SELF | maybe self after lifetimes, when we reuse trait fn in free context]
334/// [SIG PARENT TYPES/CONSTS]
335/// [SIG TYPES/CONSTS]
336fn 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        // Special case, as user specifies Trait args in trait impl header, we want to treat
357        // them as parent args. We always generate a function whose generics match
358        // child generics in trait.
359        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    // Remove `Self` from parent args (it is always at the `0th` index) as it is
373    // added manually.
374    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 ty is specified then there will be no generic param `Self`,
432                // so we do not need its predicates.
433                if self.filter_self_preds
434                    && let Some(trait_pred) = pred.0.as_trait_clause()
435                    // Rely that `Self` has zero index.
436                    && trait_pred.self_ty().skip_binder().is_param(0)
437                {
438                    continue;
439                }
440
441                // If we have a constant in parent or child args that came from delegation
442                // parent:
443                // ```rust
444                // trait Trait<T, const B: bool> { /* .. */}
445                // impl<const N: usize> S<N> {
446                //     reuse Trait::<S<N>, N>::foo;
447                // }
448                // ```
449                // Then if we inherit const predicate from `Trait` then we end up with
450                // two `ConstArgHasType` for `N` constant:
451                // 1) ConstArgHasType(N/#0, bool) from `Trait`
452                // 2) ConstArgHasType(N/#0, usize) from delegation parent
453                // So in case the constant came from delegation parent we will not inherit
454                // ConstArgHasType from signature.
455                // The check is so complicated because we build generic args for signature
456                // and predicates inheritance, for the example above it will be
457                // `args = [S<N/#0>, N/#0, S<N/#0>, N/#0]`, where
458                // args[0] - Self type, args[1] - delegation parent const, args[2] - first
459                // arg of callee path, args[3] - second arg of callee path.
460                // When processing predicate ConstArgHasType(B/#2, bool)
461                // from delegation signature (`Trait::foo`), we need to map `B/#2` into some
462                // arg from `args`. The mapping which is built by `create_mapping` function is:
463                // `{0: 0, 2: 3, 1: 2}`, so as `B/#2` has index `2` it is mapped into third
464                // arg from `args` - `N/#0`. After we obtained mapped const param, we check if
465                // it came from delegation parent, and if so we do not process its `ConstArgHasType`
466                // predicate.
467                // (Issue #158675).
468                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(&param)
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    // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
517    // Note: `predicates_of` query can also add inferred outlives predicates, but that
518    // is not the case here as `sig_id` is either a trait or a function.
519    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        // See issue #127443 for explanation.
576        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
604// Creates user-specified generic arguments from delegation path,
605// they will be used during delegation signature and predicates inheritance.
606// Example: reuse Trait::<'static, i32, 1>::foo::<A, B>
607// we want to extract [Self, 'static, i32, 1] for parent and [A, B] for child.
608pub(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}