Skip to main content

rustc_ast_lowering/delegation/
generics.rs

1use hir::HirId;
2use hir::def::{DefKind, Res};
3use rustc_ast::*;
4use rustc_data_structures::fx::FxHashSet;
5use rustc_hir as hir;
6use rustc_hir::def_id::DefId;
7use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
8use rustc_middle::{bug, ty};
9use rustc_span::symbol::kw;
10use rustc_span::{ErrorGuaranteed, Ident, Span, sym};
11
12use crate::LoweringContext;
13use crate::delegation::resolution::resolver::DelegationResolver;
14use crate::diagnostics::DelegationInfersMismatch;
15
16#[derive(#[automatically_derived]
impl ::core::fmt::Debug for GenericsPosition {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                GenericsPosition::Parent => "Parent",
                GenericsPosition::Child => "Child",
            })
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for GenericsPosition {
    #[inline]
    fn clone(&self) -> GenericsPosition { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for GenericsPosition { }Copy, #[automatically_derived]
impl ::core::cmp::Eq for GenericsPosition {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for GenericsPosition {
    #[inline]
    fn eq(&self, other: &GenericsPosition) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
17pub(super) enum GenericsPosition {
18    Parent,
19    Child,
20}
21
22#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for GenericArgSlot<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            GenericArgSlot::UserSpecified =>
                ::core::fmt::Formatter::write_str(f, "UserSpecified"),
            GenericArgSlot::Generate(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "Generate", __self_0, &__self_1),
        }
    }
}Debug)]
23pub(super) enum GenericArgSlot<T> {
24    UserSpecified,
25    Generate(T, Option<usize> /* Infer arg index from AST */),
26}
27
28pub(super) struct DelegationGenerics<T> {
29    data: T,
30    pos: GenericsPosition,
31    trait_impl: bool,
32}
33
34type TyGenerics<'hir> = Vec<GenericArgSlot<&'hir ty::GenericParamDef>>;
35
36impl<'hir> DelegationGenerics<TyGenerics<'hir>> {
37    fn generate_all(
38        params: &'hir [ty::GenericParamDef],
39        pos: GenericsPosition,
40        trait_impl: bool,
41    ) -> Self {
42        DelegationGenerics {
43            data: params.iter().map(|p| GenericArgSlot::Generate(p, None)).collect(),
44            pos,
45            trait_impl,
46        }
47    }
48}
49
50/// Used for storing either ty generics or their uplifted HIR version. First we obtain
51/// ty generics. Next, at some point of generics processing we need to uplift those
52/// generics to HIR, for this purpose we use `into_hir_generics` that uplifts ty generics
53/// and replaces Ty variant with Hir. Such approach is useful as we can call this method
54/// at any time knowing that uplifting will occur at most only once. Then, in order to obtain generic
55/// params or args we use `hir_generics_or_empty` or `into_generic_args` functions.
56/// There also may be situations when we obtained ty generics but never uplifted them to HIR,
57/// meaning we did not propagate them and thus we do not need to generate generic params
58/// (i.e., method call scenarios), in such a case this approach helps
59/// a lot as if `into_hir_generics` will not be called then uplifting will not happen.
60pub(super) enum HirOrTyGenerics<'hir> {
61    Ty(DelegationGenerics<TyGenerics<'hir>>),
62    Hir(DelegationGenerics<&'hir hir::Generics<'hir>>),
63}
64
65pub(super) struct GenericsGenerationResult<'hir> {
66    pub(super) generics: HirOrTyGenerics<'hir>,
67    pub(super) args_segment_id: HirId,
68    pub(super) use_for_sig_inheritance: bool,
69}
70
71impl GenericsGenerationResult<'_> {
72    pub(super) fn segment_id_for_sig(&self) -> Option<HirId> {
73        self.use_for_sig_inheritance.then(|| self.args_segment_id)
74    }
75}
76
77pub(super) struct GenericsGenerationResults<'hir> {
78    pub(super) parent: GenericsGenerationResult<'hir>,
79    pub(super) child: GenericsGenerationResult<'hir>,
80    pub(super) self_ty_propagation_kind: Option<hir::DelegationSelfTyPropagationKind>,
81}
82
83pub(super) struct DelegationGenericArgsIterator<'hir> {
84    index: usize = Default::default(),
85    params: &'hir [hir::GenericParam<'hir>],
86}
87
88/// During generic args propagation we need to create generic args
89/// (and their `HirId`s) on demand, as some of generic args can not be used
90/// and in this case an assert of an unseen `HirId` will be triggered. Moreover,
91/// when replacing infers with generated generic params we should reuse existing
92/// `HirId` of replaced infer, thus this iterator abstracts the way `HirId`s are
93/// created for new generic args.
94impl<'hir> DelegationGenericArgsIterator<'hir> {
95    pub(super) fn next(
96        &mut self,
97        ctx: &mut LoweringContext<'_, 'hir>,
98        hir_id_factory: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> HirId,
99    ) -> Option<hir::GenericArg<'hir>> {
100        let p = loop {
101            if self.index >= self.params.len() {
102                return None;
103            }
104
105            let p = self.params[self.index];
106            self.index += 1;
107
108            // Skip self generic arg, we do not need to propagate it.
109            if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() {
110                continue;
111            }
112
113            break p;
114        };
115
116        let hir_id = hir_id_factory(ctx);
117
118        Some(match p.kind {
119            hir::GenericParamKind::Lifetime { .. } => {
120                hir::GenericArg::Lifetime(ctx.arena.alloc(hir::Lifetime {
121                    hir_id,
122                    ident: p.name.ident(),
123                    kind: hir::LifetimeKind::Param(p.def_id),
124                    source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
125                    syntax: hir::LifetimeSyntax::ExplicitBound,
126                }))
127            }
128            hir::GenericParamKind::Type { .. } => hir::GenericArg::Type(ctx.arena.alloc(hir::Ty {
129                hir_id,
130                span: p.span,
131                kind: hir::TyKind::Path(ctx.create_generic_arg_path(&p)),
132            })),
133            hir::GenericParamKind::Const { .. } => {
134                hir::GenericArg::Const(ctx.arena.alloc(hir::ConstArg {
135                    hir_id,
136                    kind: hir::ConstArgKind::Path(ctx.create_generic_arg_path(&p)),
137                    span: p.span,
138                }))
139            }
140        })
141    }
142
143    pub(super) fn consume_all(
144        mut self,
145        ctx: &mut LoweringContext<'_, 'hir>,
146    ) -> Vec<hir::GenericArg<'hir>> {
147        let mut args = ::alloc::vec::Vec::new()vec![];
148        while let Some(arg) = self.next(ctx, |ctx| ctx.next_id()) {
149            args.push(arg);
150        }
151
152        args
153    }
154}
155
156impl<'hir> HirOrTyGenerics<'hir> {
157    pub(super) fn into_hir_generics(&mut self, ctx: &mut LoweringContext<'_, 'hir>, span: Span) {
158        if let HirOrTyGenerics::Ty(ty) = self {
159            let rename_self = ty.pos == GenericsPosition::Child;
160            let params = ctx.uplift_delegation_generic_params(span, &ty.data, rename_self);
161
162            *self = HirOrTyGenerics::Hir(DelegationGenerics {
163                data: params,
164                pos: ty.pos,
165                trait_impl: ty.trait_impl,
166            });
167        }
168    }
169
170    fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
171        match self {
172            HirOrTyGenerics::Ty(_) => hir::Generics::empty(),
173            HirOrTyGenerics::Hir(hir) => hir.data,
174        }
175    }
176
177    pub(super) fn create_args_iterator(&self) -> DelegationGenericArgsIterator<'hir> {
178        match self {
179            HirOrTyGenerics::Ty(_) => {
180                ::rustc_middle::util::bug::bug_fmt(format_args!("attempting to get generic args before uplifting to HIR"))bug!("attempting to get generic args before uplifting to HIR")
181            }
182            HirOrTyGenerics::Hir(hir) => {
183                DelegationGenericArgsIterator { params: hir.data.params, .. }
184            }
185        }
186    }
187
188    pub(super) fn infer_indices(&self) -> FxHashSet<usize> {
189        match self {
190            HirOrTyGenerics::Ty(ty) => ty
191                .data
192                .iter()
193                .flat_map(|slot| match slot {
194                    GenericArgSlot::Generate(_, Some(idx)) => Some(*idx),
195                    _ => None,
196                })
197                .collect(),
198            HirOrTyGenerics::Hir(_) => ::rustc_middle::util::bug::bug_fmt(format_args!("accessed infer indices on uplifted generics"))bug!("accessed infer indices on uplifted generics"),
199        }
200    }
201
202    pub(super) fn is_trait_impl(&self) -> bool {
203        match self {
204            HirOrTyGenerics::Ty(ty) => ty.trait_impl,
205            HirOrTyGenerics::Hir(hir) => hir.trait_impl,
206        }
207    }
208
209    pub(super) fn find_self_param(&self) -> &'hir hir::GenericParam<'hir> {
210        match self {
211            HirOrTyGenerics::Ty(_) => {
212                ::rustc_middle::util::bug::bug_fmt(format_args!("accessed ty-level generics while searching for uplifted `Self` param"))bug!("accessed ty-level generics while searching for uplifted `Self` param")
213            }
214            HirOrTyGenerics::Hir(hir) => hir
215                .data
216                .params
217                .iter()
218                .find(|p| p.name.ident().name == kw::SelfUpper)
219                .expect("`Self` generic param is not found while expected"),
220        }
221    }
222
223    pub(crate) fn pos(&self) -> GenericsPosition {
224        match self {
225            HirOrTyGenerics::Ty(ty) => ty.pos,
226            HirOrTyGenerics::Hir(hir) => hir.pos,
227        }
228    }
229}
230
231impl<'hir> GenericsGenerationResult<'hir> {
232    fn new(generics: DelegationGenerics<TyGenerics<'hir>>) -> GenericsGenerationResult<'hir> {
233        GenericsGenerationResult {
234            generics: HirOrTyGenerics::Ty(generics),
235            args_segment_id: HirId::INVALID,
236            use_for_sig_inheritance: false,
237        }
238    }
239}
240
241enum ParentSegmentArgs<'a> {
242    /// Parent segment is valid and generic args are specified:
243    /// `reuse Trait::<'static, ()>::foo;`.
244    Specified(&'a AngleBracketedArgs),
245    /// Parent segment is valid and args are not specified:
246    /// `reuse Trait::foo;`.
247    NotSpecified,
248    /// Parent segment does not exist (`reuse foo`) or we can not
249    /// add generics to it:
250    /// ```rust
251    /// mod to_reuse {
252    ///     fn foo() {}
253    /// }
254    ///
255    /// // Can't add generic args to module.
256    /// reuse to_reuse::foo;
257    /// ```
258    Invalid,
259}
260
261struct GenericsResolution<'a, 'tcx> {
262    trait_impl: bool,
263
264    parent_args: ParentSegmentArgs<'a>,
265    child_args: Option<&'a AngleBracketedArgs>,
266
267    sig_parent_params: &'tcx [ty::GenericParamDef],
268    sig_child_params: &'tcx [ty::GenericParamDef],
269
270    free_to_trait_delegation: bool,
271    /// `reuse Trait::foo;`.
272    qself_is_none: bool,
273    /// `reuse <_ as Trait>::foo;`.
274    qself_is_infer: bool,
275    /// Whether we should generate `Self` generic param.
276    generate_self: bool,
277}
278
279impl<'hir> DelegationResolver<'_, 'hir> {
280    fn resolve_generics<'a>(
281        &self,
282        delegation: &'a Delegation,
283        sig_id: DefId,
284    ) -> Result<GenericsResolution<'a, 'hir>, ErrorGuaranteed> {
285        let tcx = self.tcx();
286        let delegation_parent_kind = tcx.def_kind(tcx.local_parent(self.owner_id()));
287
288        let delegation_in_free_ctx =
289            !#[allow(non_exhaustive_omitted_patterns)] match delegation_parent_kind {
    DefKind::Trait | DefKind::Impl { .. } => true,
    _ => false,
}matches!(delegation_parent_kind, DefKind::Trait | DefKind::Impl { .. });
290
291        let sig_parent = tcx.parent(sig_id);
292        let sig_in_trait = #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(sig_parent) {
    DefKind::Trait => true,
    _ => false,
}matches!(tcx.def_kind(sig_parent), DefKind::Trait);
293        let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait;
294
295        let mut sig_parent_params: &[ty::GenericParamDef] = &[];
296
297        let qself_is_infer =
298            delegation.qself.as_ref().is_some_and(|qself| qself.ty.is_maybe_parenthesised_infer());
299
300        let qself_is_none = delegation.qself.is_none();
301
302        let parent_args = if let [.., parent_segment, _] = &delegation.path.segments[..] {
303            let res = self.get_resolution_id(parent_segment.id)?;
304            if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(res) {
    DefKind::Trait | DefKind::TraitAlias => true,
    _ => false,
}matches!(tcx.def_kind(res), DefKind::Trait | DefKind::TraitAlias) {
305                sig_parent_params = &tcx.generics_of(sig_parent).own_params;
306                self.get_user_args(parent_segment)
307                    .map(|args| ParentSegmentArgs::Specified(args))
308                    .unwrap_or(ParentSegmentArgs::NotSpecified)
309            } else {
310                ParentSegmentArgs::Invalid
311            }
312        } else {
313            ParentSegmentArgs::Invalid
314        };
315
316        Ok(GenericsResolution {
317            parent_args,
318            sig_parent_params,
319            qself_is_none,
320            qself_is_infer,
321            free_to_trait_delegation,
322            generate_self: free_to_trait_delegation && (qself_is_none || qself_is_infer),
323            trait_impl: #[allow(non_exhaustive_omitted_patterns)] match delegation_parent_kind {
    DefKind::Impl { of_trait: true } => true,
    _ => false,
}matches!(delegation_parent_kind, DefKind::Impl { of_trait: true }),
324            sig_child_params: &tcx.generics_of(sig_id).own_params,
325            child_args: self.get_user_args(
326                delegation.path.segments.last().expect("must be at least one segment"),
327            ),
328        })
329    }
330
331    fn get_user_args<'a>(&self, segment: &'a PathSegment) -> Option<&'a AngleBracketedArgs> {
332        let Some(args) = &segment.args else { return None };
333        let GenericArgs::AngleBracketed(args) = args else {
334            self.tcx().dcx().span_delayed_bug(
335                segment.span(),
336                "expected angle-bracketed generic args in delegation segment",
337            );
338
339            return None;
340        };
341
342        // Treat empty args `reuse foo::<> as bar` as `reuse foo as bar`,
343        // the same logic applied when we call function `fn f<T>(t: T)`
344        // like that `f::<>(())`, in HIR no `<>` will be generated.
345        (!args.args.is_empty()).then(|| args)
346    }
347
348    pub(super) fn resolve_and_generate_generics(
349        &self,
350        delegation: &Delegation,
351        sig_id: DefId,
352    ) -> Result<GenericsGenerationResults<'hir>, ErrorGuaranteed> {
353        let res @ GenericsResolution {
354            trait_impl,
355            generate_self,
356            sig_child_params,
357            sig_parent_params,
358            ..
359        } = self.resolve_generics(delegation, sig_id)?;
360
361        // If we are in trait impl always generate function whose generics matches
362        // those that are defined in trait.
363        if trait_impl {
364            // Considering parent generics, during signature inheritance
365            // we will take those args that are in trait impl header trait ref.
366            let parent =
367                DelegationGenerics { data: ::alloc::vec::Vec::new()vec![], pos: GenericsPosition::Child, trait_impl: true };
368
369            let parent = GenericsGenerationResult::new(parent);
370
371            let child =
372                DelegationGenerics::generate_all(sig_child_params, GenericsPosition::Child, true);
373
374            let child = GenericsGenerationResult::new(child);
375
376            return Ok(GenericsGenerationResults { parent, child, self_ty_propagation_kind: None });
377        }
378
379        let tcx = self.tcx();
380        let parent_generics = match res.parent_args {
381            ParentSegmentArgs::Specified(args) => DelegationGenerics {
382                data: Self::create_slots_from_args(
383                    tcx,
384                    args,
385                    &sig_parent_params[usize::from(!generate_self)..],
386                    generate_self,
387                ),
388                pos: GenericsPosition::Parent,
389                trait_impl,
390            },
391            ParentSegmentArgs::NotSpecified => DelegationGenerics::generate_all(
392                &sig_parent_params[usize::from(!generate_self)..],
393                GenericsPosition::Parent,
394                trait_impl,
395            ),
396            ParentSegmentArgs::Invalid => {
397                DelegationGenerics { data: ::alloc::vec::Vec::new()vec![], pos: GenericsPosition::Parent, trait_impl }
398            }
399        };
400
401        let child_generics = if let Some(args) = res.child_args {
402            let synth_params_index = sig_child_params
403                .iter()
404                .position(|p| p.kind.is_synthetic())
405                .unwrap_or(sig_child_params.len());
406
407            let mut slots = Self::create_slots_from_args(
408                tcx,
409                args,
410                &sig_child_params[..synth_params_index],
411                trait_impl,
412            );
413
414            for synth_param in &sig_child_params[synth_params_index..] {
415                slots.push(GenericArgSlot::Generate(synth_param, None));
416            }
417
418            DelegationGenerics { data: slots, pos: GenericsPosition::Child, trait_impl }
419        } else {
420            DelegationGenerics::generate_all(sig_child_params, GenericsPosition::Child, trait_impl)
421        };
422
423        Ok(GenericsGenerationResults {
424            parent: GenericsGenerationResult::new(parent_generics),
425            child: GenericsGenerationResult::new(child_generics),
426            self_ty_propagation_kind: match res.free_to_trait_delegation {
427                true => Some(match res.qself_is_none {
428                    true => hir::DelegationSelfTyPropagationKind::SelfParam,
429                    false => match res.qself_is_infer {
430                        true => hir::DelegationSelfTyPropagationKind::SelfParam,
431                        // HirId is filled during generic args propagation.
432                        false => hir::DelegationSelfTyPropagationKind::SelfTy(HirId::INVALID),
433                    },
434                }),
435                false => None,
436            },
437        })
438    }
439
440    /// Generates generic argument slots for user-specified `args` and
441    /// generic `params` of the signature function. This function checks whether
442    /// there are infers (`kw::UnderscoreLifetime` or `kw::Underscore`) in
443    /// user-specified args, and if so we add `Generate` slot meaning we have to
444    /// generate generic param for delegation and propagate it instead of this infer.
445    /// We zip over user-specified args and signature generic params, so if there are more
446    /// infers than generic params then we will not process all infers thus not generating
447    /// more generic params then needed (anyway it is an error).
448    fn create_slots_from_args(
449        tcx: TyCtxt<'_>,
450        args: &AngleBracketedArgs,
451        params: &'hir [ty::GenericParamDef],
452        add_first_self: bool,
453    ) -> TyGenerics<'hir> {
454        let mut slots = ::alloc::vec::Vec::new()vec![];
455        if add_first_self {
456            slots.push(GenericArgSlot::Generate(&params[0], None));
457        }
458
459        let params = &params[usize::from(add_first_self)..];
460        for (idx, (arg, param)) in args.args.iter().zip(params).enumerate() {
461            let AngleBracketedArg::Arg(arg) = arg else { continue };
462
463            let is_infer = match arg {
464                GenericArg::Lifetime(lt) => lt.ident.name == kw::UnderscoreLifetime,
465                GenericArg::Type(ty) => ty.is_maybe_parenthesised_infer(),
466                GenericArg::Const(_) => false,
467            };
468
469            // If `'_` is used instead of `_` (or vice versa) we emit a meaningful
470            // error instead of processing this infer or leaving it as is for signature
471            // inheritance.
472            if is_infer
473                && #[allow(non_exhaustive_omitted_patterns)] match (arg, &param.kind) {
    (GenericArg::Lifetime(_),
        GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. })
        |
        (GenericArg::Type(_) | GenericArg::Const(_),
        GenericParamDefKind::Lifetime { .. }) => true,
    _ => false,
}matches!(
474                    (arg, &param.kind),
475                    (
476                        GenericArg::Lifetime(_),
477                        GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. }
478                    ) | (
479                        GenericArg::Type(_) | GenericArg::Const(_),
480                        GenericParamDefKind::Lifetime { .. }
481                    )
482                )
483            {
484                let (actual, expected) = if #[allow(non_exhaustive_omitted_patterns)] match arg {
    GenericArg::Lifetime(..) => true,
    _ => false,
}matches!(arg, GenericArg::Lifetime(..)) {
485                    (kw::UnderscoreLifetime, kw::Underscore)
486                } else {
487                    (kw::Underscore, kw::UnderscoreLifetime)
488                };
489
490                tcx.dcx().emit_err(DelegationInfersMismatch { span: arg.span(), actual, expected });
491            }
492
493            slots.push(match is_infer {
494                true => GenericArgSlot::Generate(param, Some(idx)),
495                false => GenericArgSlot::UserSpecified,
496            });
497        }
498
499        slots
500    }
501}
502
503impl<'hir> GenericsGenerationResults<'hir> {
504    pub(super) fn all_params(&self) -> impl Iterator<Item = hir::GenericParam<'hir>> {
505        let parent = self.parent.generics.hir_generics_or_empty().params;
506        let child = self.child.generics.hir_generics_or_empty().params;
507
508        // Order generics, first we have parent and child lifetimes,
509        // then parent and child types and consts.
510        // `generics_of` in `rustc_hir_analysis` will order them anyway,
511        // however we want the order to be consistent in HIR too.
512        parent
513            .iter()
514            .filter(|p| p.is_lifetime())
515            .chain(child.iter().filter(|p| p.is_lifetime()))
516            .chain(parent.iter().filter(|p| !p.is_lifetime()))
517            .chain(child.iter().filter(|p| !p.is_lifetime()))
518            .copied()
519    }
520
521    /// As we add hack predicates(`'a: 'a`) for all lifetimes (see `uplift_delegation_generic_params`
522    /// and `generate_lifetime_predicate` functions) we need to add them to delegation generics.
523    /// Those predicates will not affect resulting predicate inheritance and folding
524    /// in `rustc_hir_analysis`, as we inherit all predicates from delegation signature.
525    pub(super) fn all_predicates(&self) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
526        self.parent
527            .generics
528            .hir_generics_or_empty()
529            .predicates
530            .into_iter()
531            .chain(self.child.generics.hir_generics_or_empty().predicates)
532            .copied()
533    }
534}
535
536impl<'hir> LoweringContext<'_, 'hir> {
537    fn uplift_delegation_generic_params(
538        &mut self,
539        span: Span,
540        params: &[GenericArgSlot<&ty::GenericParamDef>],
541        rename_self: bool,
542    ) -> &'hir hir::Generics<'hir> {
543        let params = self.arena.alloc_from_iter(params.iter().flat_map(|p| {
544            let GenericArgSlot::Generate(p, _) = p else { return None };
545
546            let def_kind = match p.kind {
547                GenericParamDefKind::Lifetime => DefKind::LifetimeParam,
548                GenericParamDefKind::Type { .. } => DefKind::TyParam,
549                GenericParamDefKind::Const { .. } => DefKind::ConstParam,
550            };
551
552            // Rename Self generic param to This so it is properly propagated.
553            // If the user will create a function `fn foo<Self>() {}` with generic
554            // param "Self" then it will not be generated in HIR, the same thing
555            // applies to traits, `trait Trait<Self> {}` will be represented as
556            // `trait Trait {}` in HIR and "unexpected keyword `Self` in generic parameters"
557            // error will be emitted.
558            // Note that we do not rename `Self` to `This` after non-recursive reuse
559            // from Trait, in this case the `Self` should not be propagated
560            // (we rely that implicit `Self` generic param of a trait is named "Self")
561            // and it is OK to have Self generic param generated during lowering.
562            let param_name =
563                if rename_self && p.name == kw::SelfUpper { sym::This } else { p.name };
564
565            let param_ident = Ident::new(param_name, span);
566            let def_name = Some(param_ident.name);
567            let node_id = self.next_node_id();
568
569            let def_id = self.create_def(node_id, def_name, def_kind, span);
570
571            let kind = match p.kind {
572                GenericParamDefKind::Lifetime => {
573                    hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
574                }
575                GenericParamDefKind::Type { synthetic, .. } => {
576                    hir::GenericParamKind::Type { default: None, synthetic }
577                }
578                GenericParamDefKind::Const { .. } => {
579                    let hir_id = self.next_id();
580                    let kind = hir::TyKind::InferDelegation(hir::InferDelegation::DefId(p.def_id));
581
582                    hir::GenericParamKind::Const {
583                        ty: self.arena.alloc(hir::Ty { kind, hir_id, span }),
584                        default: None,
585                    }
586                }
587            };
588
589            // Important: we don't use `self.next_id()` as we want to execute
590            // `lower_node_id` routine so param's id is added to `self.children`.
591            let hir_id = self.lower_node_id(node_id);
592
593            Some(hir::GenericParam {
594                hir_id,
595                colon_span: Some(span),
596                def_id,
597                kind,
598                name: hir::ParamName::Plain(param_ident),
599                pure_wrt_drop: p.pure_wrt_drop,
600                source: hir::GenericParamSource::Generics,
601                span,
602            })
603        }));
604
605        // HACK: for now we generate predicates such that all lifetimes are early bound,
606        // we can not not generate early-bound lifetimes, but we can't know which of them
607        // are late-bound at this level of compilation.
608        let predicates =
609            self.arena.alloc_from_iter(params.iter().filter_map(|p| {
610                p.is_lifetime().then(|| self.generate_lifetime_predicate(p, span))
611            }));
612
613        self.arena.alloc(hir::Generics {
614            params,
615            predicates,
616            has_where_clause_predicates: false,
617            where_clause_span: span,
618            span,
619        })
620    }
621
622    fn generate_lifetime_predicate(
623        &mut self,
624        p: &hir::GenericParam<'hir>,
625        span: Span,
626    ) -> hir::WherePredicate<'hir> {
627        let create_lifetime = |this: &mut Self| -> &'hir hir::Lifetime {
628            this.arena.alloc(hir::Lifetime {
629                hir_id: this.next_id(),
630                ident: p.name.ident(),
631                kind: hir::LifetimeKind::Param(p.def_id),
632                source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
633                syntax: hir::LifetimeSyntax::ExplicitBound,
634            })
635        };
636
637        hir::WherePredicate {
638            hir_id: self.next_id(),
639            span,
640            kind: self.arena.alloc(hir::WherePredicateKind::RegionPredicate(
641                hir::WhereRegionPredicate {
642                    in_where_clause: true,
643                    lifetime: create_lifetime(self),
644                    bounds: self
645                        .arena
646                        .alloc_slice(&[hir::GenericBound::Outlives(create_lifetime(self))]),
647                },
648            )),
649        }
650    }
651
652    pub(super) fn create_generic_arg_path(
653        &mut self,
654        p: &hir::GenericParam<'hir>,
655    ) -> hir::QPath<'hir> {
656        let res = Res::Def(
657            match p.kind {
658                hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
659                hir::GenericParamKind::Type { .. } => DefKind::TyParam,
660                hir::GenericParamKind::Const { .. } => DefKind::ConstParam,
661            },
662            p.def_id.to_def_id(),
663        );
664
665        self.create_resolved_path(res, p.name.ident(), p.span)
666    }
667
668    pub(super) fn create_resolved_path(
669        &mut self,
670        res: Res,
671        ident: Ident,
672        span: Span,
673    ) -> hir::QPath<'hir> {
674        hir::QPath::Resolved(
675            None,
676            self.arena.alloc(hir::Path {
677                segments: self.arena.alloc_slice(&[hir::PathSegment {
678                    args: None,
679                    hir_id: self.next_id(),
680                    ident,
681                    infer_args: false,
682                    res,
683                    delegation_child_segment: false,
684                }]),
685                res,
686                span,
687            }),
688        )
689    }
690}