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