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