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