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