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::assert_matches;
6
7use rustc_data_structures::fx::{FxHashMap, FxHashSet};
8use rustc_hir::def::DefKind;
9use rustc_hir::def_id::{DefId, LocalDefId};
10use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment};
11use rustc_middle::ty::{
12    self, ConstKind, EarlyBinder, GenericArg, GenericArgKind, RegionKind, Ty, TyCtxt, TypeFoldable,
13    TypeFolder, TypeSuperFoldable, TypeVisitableExt,
14};
15use rustc_span::{ErrorGuaranteed, Span, kw};
16
17use crate::collect::ItemCtxt;
18use crate::hir_ty_lowering::HirTyLowerer;
19
20type RemapTable = FxHashMap<u32, u32>;
21
22struct ParamIndexRemapper<'tcx> {
23    tcx: TyCtxt<'tcx>,
24    remap_table: RemapTable,
25    delegation_parent_consts: FxHashSet<ty::ParamConst>,
26}
27
28impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
29    fn cx(&self) -> TyCtxt<'tcx> {
30        self.tcx
31    }
32
33    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
34        if !ty.has_param() {
35            return ty;
36        }
37
38        if let ty::Param(param) = ty.kind()
39            && let Some(index) = self.remap_table.get(&param.index)
40        {
41            return Ty::new_param(self.tcx, *index, param.name);
42        }
43        ty.super_fold_with(self)
44    }
45
46    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
47        if let ty::ReEarlyParam(param) = r.kind()
48            && let Some(index) = self.remap_table.get(&param.index).copied()
49        {
50            return ty::Region::new_early_param(
51                self.tcx,
52                ty::EarlyParamRegion { index, name: param.name },
53            );
54        }
55        r
56    }
57
58    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
59        if let ty::ConstKind::Param(param) = ct.kind()
60            && let Some(idx) = self.remap_table.get(&param.index)
61        {
62            let param = ty::ParamConst::new(*idx, param.name);
63            return ty::Const::new_param(self.tcx, param);
64        }
65        ct.super_fold_with(self)
66    }
67}
68
69#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SelfPositionKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            SelfPositionKind::AfterLifetimes(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "AfterLifetimes", &__self_0),
            SelfPositionKind::Zero =>
                ::core::fmt::Formatter::write_str(f, "Zero"),
            SelfPositionKind::None =>
                ::core::fmt::Formatter::write_str(f, "None"),
        }
    }
}Debug)]
70enum SelfPositionKind {
71    AfterLifetimes(Option<DelegationSelfTyPropagationKind>),
72    Zero,
73    None,
74}
75
76fn create_self_param_position_kind(
77    tcx: TyCtxt<'_>,
78    def_id: LocalDefId,
79    sig_id: DefId,
80) -> SelfPositionKind {
81    match fn_kinds(tcx, def_id, sig_id) {
82        (FnKind::Free, FnKind::AssocTrait) => {
83            let kind = tcx.hir_delegation_info(def_id).self_ty_propagation_kind;
84            SelfPositionKind::AfterLifetimes(kind)
85        }
86
87        (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
88
89        (_, FnKind::AssocTrait) | (FnKind::AssocTrait, _) => SelfPositionKind::Zero,
90
91        (FnKind::AssocTraitImpl, _) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
92
93        _ => SelfPositionKind::None,
94    }
95}
96
97#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for FnKind { }
#[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::marker::StructuralPartialEq for FnKind { }
#[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)]
98enum FnKind {
99    Free,
100    AssocInherentImpl,
101    AssocTrait,
102    AssocTraitImpl,
103}
104
105fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> FnKind {
106    let def_id = def_id.into();
107
108    match tcx.def_kind(def_id) {
109        DefKind::Fn => FnKind::Free,
110        DefKind::AssocFn => match tcx.def_kind(tcx.parent(def_id)) {
111            DefKind::Trait => FnKind::AssocTrait,
112            DefKind::Impl { of_trait } => match of_trait {
113                true => FnKind::AssocTraitImpl,
114                false => FnKind::AssocInherentImpl,
115            },
116            _ => {
    ::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"),
117        },
118        _ => {
    ::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"),
119    }
120}
121
122fn fn_kinds(tcx: TyCtxt<'_>, def_id: LocalDefId, sig_id: DefId) -> (FnKind, FnKind) {
123    let kinds = (fn_kind(tcx, def_id), fn_kind(tcx, sig_id));
124
125    // For trait impl's `sig_id` is always equal to the corresponding trait method.
126    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)));
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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for InheritanceKind { }
#[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::marker::StructuralPartialEq for InheritanceKind { }
#[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 parent_kind = fn_kind(tcx, sig_id);
181    let process_parent = #[allow(non_exhaustive_omitted_patterns)] match parent_kind {
    FnKind::AssocTrait | FnKind::AssocInherentImpl => true,
    _ => false,
}matches!(parent_kind, FnKind::AssocTrait | FnKind::AssocInherentImpl);
182    let parent_generics = process_parent.then(|| tcx.generics_of(tcx.parent(sig_id)));
183
184    // In case of delegations to inherent impls indices of generic params which are passed
185    // to ADT can be random numbers not from range 0..parent_params_count, so we need to
186    // use original indices in mapping:
187    // impl<'a, 'b, 'c, A: 'a, const C: usize> S<'a, A, C> {
188    //      fn foo_static<'d: 'd, 'e, T, const B: bool>() {}
189    //      fn foo_self<'d: 'd, 'e, T, const B: bool>(self) {}
190    // },
191    // 'a has index 0, A index 3, C index 4. If we encounter not a generic param as generic arg,
192    // then we do not need to map it (i.e. consts like `1`, `2`, `3`; `'static`, etc.).
193    let parent_params = match parent_kind {
194        FnKind::AssocInherentImpl => {
195            let ty::Adt(_, args) = tcx.type_of(tcx.parent(sig_id)).skip_binder().kind() else {
196                {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("parent of inherent function in delegation can be only struct or enum")));
}unreachable!("parent of inherent function in delegation can be only struct or enum")
197            };
198
199            let opt_param_info = |arg: GenericArg<'_>| match arg.kind() {
200                GenericArgKind::Lifetime(r) => (
201                    match r.kind() {
202                        RegionKind::ReEarlyParam(p) => Some(p.index),
203                        _ => None,
204                    },
205                    false,
206                ),
207                GenericArgKind::Type(t) => (
208                    match t.kind() {
209                        ty::Param(p) => Some(p.index),
210                        _ => None,
211                    },
212                    true,
213                ),
214                GenericArgKind::Const(c) => (
215                    match c.kind() {
216                        ConstKind::Param(p) => Some(p.index),
217                        _ => None,
218                    },
219                    true,
220                ),
221            };
222
223            args.iter().map(opt_param_info).collect::<Vec<_>>()
224        }
225        FnKind::AssocTrait => parent_generics
226            .expect("trait must have generics")
227            .own_params
228            .iter()
229            .map(|p| (Some(p.index as u32), p.kind.is_ty_or_const()))
230            .collect::<Vec<_>>(),
231        _ => ::alloc::vec::Vec::new()vec![],
232    };
233
234    let has_self = match parent_kind {
235        FnKind::AssocTrait => parent_generics.expect("trait must have generics").has_self,
236        _ => false,
237    };
238
239    if process_parent {
240        for i in (has_self as usize)..parent_params.len() {
241            let (index, is_ty_or_const) = parent_params[i];
242            if !is_ty_or_const {
243                if let Some(index) = index {
244                    mapping.insert(index, args_index as u32);
245                }
246
247                args_index += 1;
248            }
249        }
250    }
251
252    let child_generics = tcx.generics_of(sig_id);
253    for param in &child_generics.own_params {
254        if !param.kind.is_ty_or_const() {
255            mapping.insert(param.index, args_index as u32);
256            args_index += 1;
257        }
258    }
259
260    // If self after lifetimes insert mapping, relying that self is at 0 in sig parent.
261    // If self ty is propagated (meaning there is no generic param `Self`), the specified
262    // self ty will be inserted in args in `create_generic_args`.
263    if #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
    SelfPositionKind::AfterLifetimes { .. } => true,
    _ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes { .. }) {
264        mapping.insert(0, args_index as u32);
265        args_index += 1;
266    }
267
268    if process_parent {
269        for i in (has_self as usize)..parent_params.len() {
270            let (index, is_ty_or_const) = parent_params[i];
271            if is_ty_or_const {
272                if let Some(index) = index {
273                    mapping.insert(index, args_index as u32);
274                }
275
276                args_index += 1;
277            }
278        }
279    }
280
281    for param in &child_generics.own_params {
282        if param.kind.is_ty_or_const() {
283            mapping.insert(param.index, args_index as u32);
284            args_index += 1;
285        }
286    }
287
288    mapping
289}
290
291fn get_delegation_parent_args_count_without_self<'tcx>(
292    tcx: TyCtxt<'tcx>,
293    def_id: LocalDefId,
294    sig_id: DefId,
295) -> usize {
296    let kinds @ (def_kind, _) = fn_kinds(tcx, def_id, sig_id);
297
298    match kinds {
299        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => 0,
300
301        (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
302
303        (FnKind::Free, _) => 0,
304
305        (_, _) => {
306            let delegation_parent_args_count = tcx.generics_of(def_id).parent_count;
307            let has_self = def_kind == FnKind::AssocTrait;
308
309            delegation_parent_args_count - usize::from(has_self)
310        }
311    }
312}
313
314fn get_parent_and_inheritance_kind<'tcx>(
315    tcx: TyCtxt<'tcx>,
316    def_id: LocalDefId,
317    sig_id: DefId,
318) -> (Option<DefId>, InheritanceKind) {
319    let kinds @ (_, sig_kind) = fn_kinds(tcx, def_id, sig_id);
320
321    match kinds {
322        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
323            (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::Own)
324        }
325
326        (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
327
328        (FnKind::Free, _) => {
329            let copy_self_clauses = sig_kind == FnKind::AssocTrait;
330            (None, InheritanceKind::WithParent(copy_self_clauses))
331        }
332
333        (_, _) => (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::WithParent(false)),
334    }
335}
336
337fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<Ty<'tcx>> {
338    let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("processing delegation");
339    let (caller_kind, callee_kind) = fn_kinds(tcx, def_id, sig_id);
340
341    match (caller_kind, callee_kind) {
342        (FnKind::AssocTraitImpl, FnKind::AssocTrait) | (FnKind::AssocInherentImpl, _) => {
343            Some(tcx.type_of(tcx.local_parent(def_id)).instantiate_identity().skip_norm_wip())
344        }
345
346        // For trait impl's `sig_id` is always equal to the corresponding trait method.
347        (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
348
349        (_, _) => match create_self_param_position_kind(tcx, def_id, sig_id) {
350            SelfPositionKind::None => None,
351            SelfPositionKind::AfterLifetimes(propagation_kind) => Some(match propagation_kind {
352                Some(kind) => match kind {
353                    DelegationSelfTyPropagationKind::SelfTy(self_ty_id) => {
354                        let ctx = ItemCtxt::new(tcx, def_id);
355                        ctx.lower_ty(tcx.hir_node(self_ty_id).expect_ty())
356                    }
357                    DelegationSelfTyPropagationKind::SelfParam => {
358                        let index = tcx.generics_of(def_id).own_counts().lifetimes;
359                        Ty::new_param(tcx, index as u32, kw::SelfUpper)
360                    }
361                },
362                None => Ty::new_error_with_message(
363                    tcx,
364                    tcx.def_span(def_id),
365                    "self propagation kind must be specified for `AfterLifetimes` variant",
366                ),
367            }),
368            SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)),
369        },
370    }
371}
372
373/// Creates generic arguments for further delegation signature and predicates instantiation.
374/// Arguments can be user-specified (in this case they are in `parent_args` and `child_args`)
375/// or propagated. User can specify either both `parent_args` and `child_args`, one of them or none,
376/// that is why we firstly create generic arguments from generic params and then adjust them with
377/// user-specified args.
378///
379/// The order of produced list is important, it must be of this pattern:
380///
381/// [SELF | maybe self in the beginning]
382/// [PARENT | args of delegation parent]
383/// [SIG PARENT LIFETIMES] <- `lifetimes_end_pos`
384/// [SIG LIFETIMES]
385/// [SELF | maybe self after lifetimes, when we reuse trait fn in free context]
386/// [SIG PARENT TYPES/CONSTS]
387/// [SIG TYPES/CONSTS]
388fn create_generic_args<'tcx>(
389    tcx: TyCtxt<'tcx>,
390    sig_id: DefId,
391    def_id: LocalDefId,
392    mut parent_args: &[ty::GenericArg<'tcx>],
393    mut child_args: &[ty::GenericArg<'tcx>],
394) -> (Vec<ty::GenericArg<'tcx>>, &'tcx [ty::GenericArg<'tcx>]) {
395    let delegation_generics = tcx.generics_of(def_id);
396    let delegation_args = ty::GenericArgs::identity_for_item(tcx, def_id);
397
398    let real_args_count = delegation_args.len() - delegation_generics.own_synthetic_params_count();
399    let synth_args = &delegation_args[real_args_count..];
400
401    let mut delegation_parent_args =
402        &delegation_args[delegation_generics.has_self as usize..delegation_generics.parent_count];
403
404    let delegation_args = &delegation_args[delegation_generics.parent_count..];
405
406    let kinds @ (_, parent_kind) = fn_kinds(tcx, def_id, sig_id);
407    if #[allow(non_exhaustive_omitted_patterns)] match kinds {
    (FnKind::AssocTraitImpl, FnKind::AssocTrait) => true,
    _ => false,
}matches!(kinds, (FnKind::AssocTraitImpl, FnKind::AssocTrait)) {
408        // Special case, as user specifies Trait args in trait impl header, we want to treat
409        // them as parent args. We always generate a function whose generics match
410        // child generics in trait.
411        let parent = tcx.local_parent(def_id);
412
413        parent_args =
414            tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args;
415
416        child_args =
417            &delegation_args[delegation_args.len() - delegation_generics.own_params.len()..];
418
419        delegation_parent_args = &[];
420    }
421
422    let self_type = get_delegation_self_ty(tcx, def_id).map(ty::GenericArg::from);
423
424    if self_type.is_some() && !parent_args.is_empty() {
425        parent_args = match parent_kind {
426            FnKind::AssocInherentImpl => parent_args,
427            // Remove `Self` from parent args (it is always at the `0th` index) as it is
428            // added manually.
429            FnKind::AssocTrait => &parent_args[1..],
430            _ => {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("if parent args are non-empty then the parent must exist")));
}unreachable!("if parent args are non-empty then the parent must exist"),
431        }
432    }
433
434    let (zero_self, after_lifetimes_self) =
435        match create_self_param_position_kind(tcx, def_id, sig_id) {
436            SelfPositionKind::AfterLifetimes(_) => {
437                if !self_type.is_some() {
    ::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
438                (None, self_type)
439            }
440            SelfPositionKind::Zero => {
441                if !self_type.is_some() {
    ::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
442                (self_type, None)
443            }
444            SelfPositionKind::None => (None, None),
445        };
446
447    let zero_self = zero_self.as_ref().into_iter();
448    let after_lifetimes_self = after_lifetimes_self.as_ref().into_iter();
449
450    let args = zero_self
451        .chain(delegation_parent_args)
452        .chain(parent_args.iter().filter(|a| a.as_region().is_some()))
453        .chain(child_args.iter().filter(|a| a.as_region().is_some()))
454        .chain(after_lifetimes_self)
455        .chain(parent_args.iter().filter(|a| a.as_region().is_none()))
456        .chain(child_args.iter().filter(|a| a.as_region().is_none()))
457        .chain(synth_args)
458        .copied()
459        .collect::<Vec<_>>();
460
461    (args, delegation_parent_args)
462}
463
464pub(crate) fn inherit_clauses_for_delegation_item<'tcx>(
465    tcx: TyCtxt<'tcx>,
466    def_id: LocalDefId,
467    sig_id: DefId,
468) -> ty::GenericClauses<'tcx> {
469    struct ClausesCollector<'tcx> {
470        tcx: TyCtxt<'tcx>,
471        clauses: Vec<(ty::Clause<'tcx>, Span)>,
472        args: Vec<ty::GenericArg<'tcx>>,
473        folder: ParamIndexRemapper<'tcx>,
474        filter_self_clauses: bool,
475    }
476
477    impl<'tcx> ClausesCollector<'tcx> {
478        fn with_own_clauses(
479            mut self,
480            f: impl Fn(DefId) -> ty::GenericClauses<'tcx>,
481            def_id: DefId,
482        ) -> Self {
483            let clauses = f(def_id);
484            let args = self.args.as_slice();
485
486            for clause in clauses.clauses {
487                // If self ty is specified then there will be no generic param `Self`,
488                // so we do not need its clauses.
489                if self.filter_self_clauses
490                    && let Some(trait_clause) = clause.0.as_trait_clause()
491                    // Rely that `Self` has zero index.
492                    && trait_clause.self_ty().skip_binder().is_param(0)
493                {
494                    continue;
495                }
496
497                // If we have a constant in parent or child args that came from delegation
498                // parent:
499                // ```rust
500                // trait Trait<T, const B: bool> { /* .. */}
501                // impl<const N: usize> S<N> {
502                //     reuse Trait::<S<N>, N>::foo;
503                // }
504                // ```
505                // Then if we inherit const clause from `Trait` then we end up with
506                // two `ConstArgHasType` for `N` constant:
507                // 1) ConstArgHasType(N/#0, bool) from `Trait`
508                // 2) ConstArgHasType(N/#0, usize) from delegation parent
509                // So in case the constant came from delegation parent we will not inherit
510                // ConstArgHasType from signature.
511                // The check is so complicated because we build generic args for signature
512                // and clauses inheritance, for the example above it will be
513                // `args = [S<N/#0>, N/#0, S<N/#0>, N/#0]`, where
514                // args[0] - Self type, args[1] - delegation parent const, args[2] - first
515                // arg of callee path, args[3] - second arg of callee path.
516                // When processing clause ConstArgHasType(B/#2, bool)
517                // from delegation signature (`Trait::foo`), we need to map `B/#2` into some
518                // arg from `args`. The mapping which is built by `create_mapping` function is:
519                // `{0: 0, 2: 3, 1: 2}`, so as `B/#2` has index `2` it is mapped into third
520                // arg from `args` - `N/#0`. After we obtained mapped const param, we check if
521                // it came from delegation parent, and if so we do not process its `ConstArgHasType`
522                // clause.
523                // (Issue #158675).
524                if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) =
525                    clause.0.as_predicate().fold_with(&mut self.folder).kind().skip_binder()
526                {
527                    let unnorm_const = EarlyBinder::bind(self.tcx, ct).instantiate(self.tcx, args);
528                    if let ty::ConstKind::Param(param) = unnorm_const.skip_norm_wip().kind()
529                        && self.folder.delegation_parent_consts.contains(&param)
530                    {
531                        continue;
532                    }
533                }
534
535                let new_clause = clause.0.fold_with(&mut self.folder);
536                self.clauses.push((
537                    EarlyBinder::bind(self.tcx, new_clause)
538                        .instantiate(self.tcx, args)
539                        .skip_norm_wip(),
540                    clause.1,
541                ));
542            }
543
544            self
545        }
546
547        fn with_clauses(
548            mut self,
549            f: impl Fn(DefId) -> ty::GenericClauses<'tcx> + Copy,
550            def_id: DefId,
551        ) -> Self {
552            let preds = f(def_id);
553            if let Some(parent_def_id) = preds.parent {
554                self = self.with_own_clauses(f, parent_def_id);
555            }
556
557            self.with_own_clauses(f, def_id)
558        }
559    }
560
561    let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
562    let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
563    let self_pos_kind = create_self_param_position_kind(tcx, def_id, sig_id);
564    let filter_self_clauses = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
    SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
        => true,
    _ => false,
}matches!(
565        self_pos_kind,
566        SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
567    );
568
569    let collector = ClausesCollector { tcx, clauses: ::alloc::vec::Vec::new()vec![], args, folder, filter_self_clauses };
570    let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
571
572    // `explicit_clauses_of` is used here to avoid copying `Self: Trait` clause.
573    // Note: `clauses_of` query can also add inferred outlives clauses, but that
574    // is not the case here as `sig_id` is either a trait or a function.
575    let clauses = match inh_kind {
576        InheritanceKind::WithParent(false) => {
577            collector.with_clauses(|def_id| tcx.explicit_clauses_of(def_id), sig_id)
578        }
579        InheritanceKind::WithParent(true) => {
580            collector.with_clauses(|def_id| tcx.clauses_of(def_id), sig_id)
581        }
582        InheritanceKind::Own => collector.with_own_clauses(|def_id| tcx.clauses_of(def_id), sig_id),
583    }
584    .clauses;
585
586    ty::GenericClauses { parent, clauses: tcx.arena.alloc_from_iter(clauses) }
587}
588
589fn create_folder_and_args<'tcx>(
590    tcx: TyCtxt<'tcx>,
591    def_id: LocalDefId,
592    sig_id: DefId,
593    parent_args: &'tcx [ty::GenericArg<'tcx>],
594    child_args: &'tcx [ty::GenericArg<'tcx>],
595) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
596    let (args, delegation_parent_args) =
597        create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
598
599    let remap_table = create_mapping(tcx, sig_id, def_id);
600
601    let delegation_parent_consts = delegation_parent_args
602        .iter()
603        .filter_map(|a| {
604            a.as_const().and_then(|c| {
605                if let ty::ConstKind::Param(param) = c.kind() { Some(param) } else { None }
606            })
607        })
608        .collect();
609
610    (ParamIndexRemapper { tcx, remap_table, delegation_parent_consts }, args)
611}
612
613fn check_constraints<'tcx>(
614    tcx: TyCtxt<'tcx>,
615    def_id: LocalDefId,
616    sig_id: DefId,
617) -> Result<(), ErrorGuaranteed> {
618    let mut ret = Ok(());
619
620    let mut emit = |descr| {
621        ret = Err(tcx.dcx().emit_err(crate::diagnostics::UnsupportedDelegation {
622            span: tcx.def_span(def_id),
623            descr,
624            callee_span: tcx.def_span(sig_id),
625        }));
626    };
627
628    if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic() {
629        // See issue #127443 for explanation.
630        emit("delegation to C-variadic functions is not allowed");
631    }
632
633    ret
634}
635
636pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
637    tcx: TyCtxt<'tcx>,
638    def_id: LocalDefId,
639) -> &'tcx [Ty<'tcx>] {
640    let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id");
641    let caller_sig = tcx.fn_sig(sig_id);
642    if let Err(err) = check_constraints(tcx, def_id, sig_id) {
643        let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
644        let err_type = Ty::new_error(tcx, err);
645        return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
646    }
647
648    let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
649    let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
650    let caller_sig = EarlyBinder::bind(tcx, caller_sig.skip_binder().fold_with(&mut folder));
651
652    let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder();
653    let output = std::iter::once(sig.output());
654    let mut sig = sig.inputs().iter().cloned().chain(output).collect::<Vec<_>>();
655
656    adjust_sig_in_inherent_impl_cases(tcx, sig_id, def_id, parent_args, &mut sig);
657
658    tcx.arena.alloc_from_iter(sig)
659}
660
661/// We need to replace `Self` type of the signature function parent with
662/// either type of parent of delegation (which is either `Self` param in case of trait)
663/// and other ADT in case of inherent impl. We do the same thing when delegating to trait,
664/// in this case replacement happens during signature instantiation (as we can replace `Self`
665/// generic param with other type from `args` when instantiating).
666fn adjust_sig_in_inherent_impl_cases<'tcx>(
667    tcx: TyCtxt<'tcx>,
668    sig_id: DefId,
669    def_id: LocalDefId,
670    parent_args: &[ty::GenericArg<'tcx>],
671    sig: &mut [Ty<'tcx>],
672) {
673    if !tcx.is_method(sig_id) {
674        return;
675    }
676
677    let kinds @ (def_kind, _) = fn_kinds(tcx, def_id, sig_id);
678    if def_kind == FnKind::Free || !#[allow(non_exhaustive_omitted_patterns)] match kinds {
    (_, FnKind::AssocInherentImpl) => true,
    _ => false,
}matches!(kinds, (_, FnKind::AssocInherentImpl)) {
679        return;
680    }
681
682    let ty::Adt(def, _) = tcx.type_of(tcx.parent(sig_id)).skip_binder().kind() else {
683        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("delegation is supported only to struct or enums")));
}unreachable!("delegation is supported only to struct or enums")
684    };
685
686    for i in 0..sig.len() {
687        let to_replace = Ty::new_adt(tcx, *def, tcx.mk_args(parent_args));
688        let replacement = match def_kind {
689            FnKind::Free => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
690
691            FnKind::AssocTrait => Ty::new_param(tcx, 0, kw::SelfUpper),
692            _ => tcx.type_of(tcx.parent(def_id.to_def_id())).instantiate_identity().skip_norm_wip(),
693        };
694
695        struct Replacer<'tcx> {
696            tcx: TyCtxt<'tcx>,
697            to_replace: Ty<'tcx>,
698            replacement: Ty<'tcx>,
699        }
700
701        impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Replacer<'tcx> {
702            fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
703                if t == self.to_replace { self.replacement } else { t.super_fold_with(self) }
704            }
705
706            fn cx(&self) -> TyCtxt<'tcx> {
707                self.tcx
708            }
709        }
710
711        sig[i] = sig[i].fold_with(&mut Replacer { tcx, to_replace, replacement })
712    }
713}
714
715// Creates user-specified generic arguments from delegation path,
716// they will be used during delegation signature and predicates inheritance.
717// Example: reuse Trait::<'static, i32, 1>::foo::<A, B>
718// we want to extract [Self, 'static, i32, 1] for parent and [A, B] for child.
719pub(crate) fn delegation_user_specified_args<'tcx>(
720    tcx: TyCtxt<'tcx>,
721    def_id: LocalDefId,
722) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
723    let info = tcx.hir_delegation_info(def_id);
724
725    let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
726        let segment = tcx.hir_node(hir_id).expect_path_segment();
727        segment.res.opt_def_id().map(|def_id| (segment, def_id))
728    };
729
730    let ctx = ItemCtxt::new_for_delegation(tcx, def_id);
731    let lowerer = ctx.lowerer();
732
733    let parent_args = info
734        .parent_seg_id_for_sig
735        .and_then(get_segment)
736        .filter(|(_, def_id)| !#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(*def_id) {
    DefKind::Mod => true,
    _ => false,
}matches!(tcx.def_kind(*def_id), DefKind::Mod))
737        .map(|(segment, def_id)| {
738            // After lowering parent segment can be resolved only to those variants (and `DefKind::Mod`),
739            // which we do not process here.
740            {
    match tcx.def_kind(def_id) {
        DefKind::Trait | DefKind::Struct | DefKind::Enum => {}
        ref left_val => {
            ::core::panicking::assert_matches_failed(left_val,
                "DefKind::Trait | DefKind::Struct | DefKind::Enum",
                ::core::option::Option::None);
        }
    }
};assert_matches!(tcx.def_kind(def_id), DefKind::Trait | DefKind::Struct | DefKind::Enum);
741
742            let self_ty = (tcx.def_kind(def_id) == DefKind::Trait)
743                .then(|| Ty::new_param(tcx, 0, kw::SelfUpper));
744
745            lowerer
746                .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty)
747                .0
748                .as_slice()
749        });
750
751    let child_args = info.child_seg_id_for_sig.and_then(get_segment).map(|(segment, def_id)| {
752        {
    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);
        }
    }
};assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
753        let parent = tcx.parent(def_id);
754
755        let parent_args =
756            if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(parent) {
    DefKind::Impl { of_trait: false } | DefKind::Trait => true,
    _ => false,
}matches!(tcx.def_kind(parent), DefKind::Impl { of_trait: false } | DefKind::Trait) {
757                ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
758            } else if let Some(parent_args) = parent_args {
759                parent_args
760            } else {
761                &[]
762            };
763
764        let args = lowerer
765            .lower_generic_args_of_path(segment.ident.span, def_id, parent_args, segment, None)
766            .0;
767
768        let synth_params_count = tcx.generics_of(def_id).own_synthetic_params_count();
769        &args[parent_args.len()..args.len() - synth_params_count]
770    });
771
772    (parent_args.unwrap_or_default(), child_args.unwrap_or_default())
773}