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;
8use rustc_middle::{bug, ty};
9use rustc_span::symbol::kw;
10use rustc_span::{Ident, Span, sym};
11
12use crate::LoweringContext;
13use crate::diagnostics::DelegationInfersMismatch;
14
15#[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)]
16pub(super) enum GenericsPosition {
17 Parent,
18 Child,
19}
20
21#[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)]
22pub(super) enum GenericArgSlot<T> {
23 UserSpecified,
24 Generate(T, Option<usize> ),
25}
26
27pub(super) struct DelegationGenerics<T> {
28 data: T,
29 pos: GenericsPosition,
30 trait_impl: bool,
31}
32
33type TyGenerics<'hir> = Vec<GenericArgSlot<&'hir ty::GenericParamDef>>;
34
35impl<'hir> DelegationGenerics<TyGenerics<'hir>> {
36 fn generate_all(
37 params: &'hir [ty::GenericParamDef],
38 pos: GenericsPosition,
39 trait_impl: bool,
40 ) -> Self {
41 DelegationGenerics {
42 data: params.iter().map(|p| GenericArgSlot::Generate(p, None)).collect(),
43 pos,
44 trait_impl,
45 }
46 }
47}
48
49pub(super) enum HirOrTyGenerics<'hir> {
60 Ty(DelegationGenerics<TyGenerics<'hir>>),
61 Hir(DelegationGenerics<&'hir hir::Generics<'hir>>),
62}
63
64pub(super) struct GenericsGenerationResult<'hir> {
65 pub(super) generics: HirOrTyGenerics<'hir>,
66 pub(super) args_segment_id: HirId,
67 pub(super) use_for_sig_inheritance: bool,
68}
69
70impl GenericsGenerationResult<'_> {
71 pub(super) fn segment_id_for_sig(&self) -> Option<HirId> {
72 self.use_for_sig_inheritance.then(|| self.args_segment_id)
73 }
74}
75
76pub(super) struct GenericsGenerationResults<'hir> {
77 pub(super) parent: GenericsGenerationResult<'hir>,
78 pub(super) child: GenericsGenerationResult<'hir>,
79 pub(super) self_ty_propagation_kind: Option<hir::DelegationSelfTyPropagationKind>,
80}
81
82pub(super) struct DelegationGenericArgsIterator<'hir> {
83 index: usize = Default::default(),
84 params: &'hir [hir::GenericParam<'hir>],
85}
86
87impl<'hir> DelegationGenericArgsIterator<'hir> {
94 pub(super) fn next(
95 &mut self,
96 ctx: &mut LoweringContext<'_, 'hir>,
97 hir_id_factory: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> HirId,
98 ) -> Option<hir::GenericArg<'hir>> {
99 let p = loop {
100 if self.index >= self.params.len() {
101 return None;
102 }
103
104 let p = self.params[self.index];
105 self.index += 1;
106
107 if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() {
109 continue;
110 }
111
112 break p;
113 };
114
115 let hir_id = hir_id_factory(ctx);
116
117 Some(match p.kind {
118 hir::GenericParamKind::Lifetime { .. } => {
119 hir::GenericArg::Lifetime(ctx.arena.alloc(hir::Lifetime {
120 hir_id,
121 ident: p.name.ident(),
122 kind: hir::LifetimeKind::Param(p.def_id),
123 source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
124 syntax: hir::LifetimeSyntax::ExplicitBound,
125 }))
126 }
127 hir::GenericParamKind::Type { .. } => hir::GenericArg::Type(ctx.arena.alloc(hir::Ty {
128 hir_id,
129 span: p.span,
130 kind: hir::TyKind::Path(ctx.create_generic_arg_path(&p)),
131 })),
132 hir::GenericParamKind::Const { .. } => {
133 hir::GenericArg::Const(ctx.arena.alloc(hir::ConstArg {
134 hir_id,
135 kind: hir::ConstArgKind::Path(ctx.create_generic_arg_path(&p)),
136 span: p.span,
137 }))
138 }
139 })
140 }
141
142 pub(super) fn consume_all(
143 mut self,
144 ctx: &mut LoweringContext<'_, 'hir>,
145 ) -> Vec<hir::GenericArg<'hir>> {
146 let mut args = ::alloc::vec::Vec::new()vec![];
147 while let Some(arg) = self.next(ctx, |ctx| ctx.next_id()) {
148 args.push(arg);
149 }
150
151 args
152 }
153}
154
155impl<'hir> HirOrTyGenerics<'hir> {
156 pub(super) fn into_hir_generics(&mut self, ctx: &mut LoweringContext<'_, 'hir>, span: Span) {
157 if let HirOrTyGenerics::Ty(ty) = self {
158 let rename_self = ty.pos == GenericsPosition::Child;
159 let params = ctx.uplift_delegation_generic_params(span, &ty.data, rename_self);
160
161 *self = HirOrTyGenerics::Hir(DelegationGenerics {
162 data: params,
163 pos: ty.pos,
164 trait_impl: ty.trait_impl,
165 });
166 }
167 }
168
169 fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
170 match self {
171 HirOrTyGenerics::Ty(_) => hir::Generics::empty(),
172 HirOrTyGenerics::Hir(hir) => hir.data,
173 }
174 }
175
176 pub(super) fn create_args_iterator(&self) -> DelegationGenericArgsIterator<'hir> {
177 match self {
178 HirOrTyGenerics::Ty(_) => {
179 ::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")
180 }
181 HirOrTyGenerics::Hir(hir) => {
182 DelegationGenericArgsIterator { params: hir.data.params, .. }
183 }
184 }
185 }
186
187 pub(super) fn infer_indices(&self) -> FxHashSet<usize> {
188 match self {
189 HirOrTyGenerics::Ty(ty) => ty
190 .data
191 .iter()
192 .flat_map(|slot| match slot {
193 GenericArgSlot::Generate(_, Some(idx)) => Some(*idx),
194 _ => None,
195 })
196 .collect(),
197 HirOrTyGenerics::Hir(_) => ::rustc_middle::util::bug::bug_fmt(format_args!("accessed infer indices on uplifted generics"))bug!("accessed infer indices on uplifted generics"),
198 }
199 }
200
201 pub(super) fn is_trait_impl(&self) -> bool {
202 match self {
203 HirOrTyGenerics::Ty(ty) => ty.trait_impl,
204 HirOrTyGenerics::Hir(hir) => hir.trait_impl,
205 }
206 }
207
208 pub(super) fn find_self_param(&self) -> &'hir hir::GenericParam<'hir> {
209 match self {
210 HirOrTyGenerics::Ty(_) => {
211 ::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")
212 }
213 HirOrTyGenerics::Hir(hir) => hir
214 .data
215 .params
216 .iter()
217 .find(|p| p.name.ident().name == kw::SelfUpper)
218 .expect("`Self` generic param is not found while expected"),
219 }
220 }
221
222 pub(crate) fn pos(&self) -> GenericsPosition {
223 match self {
224 HirOrTyGenerics::Ty(ty) => ty.pos,
225 HirOrTyGenerics::Hir(hir) => hir.pos,
226 }
227 }
228}
229
230impl<'hir> GenericsGenerationResult<'hir> {
231 fn new(generics: DelegationGenerics<TyGenerics<'hir>>) -> GenericsGenerationResult<'hir> {
232 GenericsGenerationResult {
233 generics: HirOrTyGenerics::Ty(generics),
234 args_segment_id: HirId::INVALID,
235 use_for_sig_inheritance: false,
236 }
237 }
238}
239
240impl<'hir> GenericsGenerationResults<'hir> {
241 pub(super) fn all_params(&self) -> impl Iterator<Item = hir::GenericParam<'hir>> {
242 let parent = self.parent.generics.hir_generics_or_empty().params;
243 let child = self.child.generics.hir_generics_or_empty().params;
244
245 parent
250 .iter()
251 .filter(|p| p.is_lifetime())
252 .chain(child.iter().filter(|p| p.is_lifetime()))
253 .chain(parent.iter().filter(|p| !p.is_lifetime()))
254 .chain(child.iter().filter(|p| !p.is_lifetime()))
255 .copied()
256 }
257
258 pub(super) fn all_predicates(&self) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
263 self.parent
264 .generics
265 .hir_generics_or_empty()
266 .predicates
267 .into_iter()
268 .chain(self.child.generics.hir_generics_or_empty().predicates)
269 .copied()
270 }
271}
272
273impl<'hir> LoweringContext<'_, 'hir> {
274 pub(super) fn uplift_delegation_generics(
275 &mut self,
276 delegation: &Delegation,
277 sig_id: DefId,
278 ) -> GenericsGenerationResults<'hir> {
279 let delegation_parent_kind = self.tcx.def_kind(self.tcx.local_parent(self.owner.def_id));
280
281 let segments = &delegation.path.segments;
282 let len = segments.len();
283
284 let get_user_args = |idx: usize| -> Option<&AngleBracketedArgs> {
285 let segment = &segments[idx];
286
287 let Some(args) = segment.args.as_ref() else { return None };
288 let GenericArgs::AngleBracketed(args) = args else {
289 self.tcx.dcx().span_delayed_bug(
290 segment.span(),
291 "expected angle-bracketed generic args in delegation segment",
292 );
293
294 return None;
295 };
296
297 (!args.args.is_empty()).then(|| args)
301 };
302
303 let sig_params = &self.tcx.generics_of(sig_id).own_params[..];
304
305 if #[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 }) {
308 let parent =
311 DelegationGenerics { data: ::alloc::vec::Vec::new()vec![], pos: GenericsPosition::Child, trait_impl: true };
312
313 let parent = GenericsGenerationResult::new(parent);
314
315 let child = DelegationGenerics::generate_all(sig_params, GenericsPosition::Child, true);
316 let child = GenericsGenerationResult::new(child);
317
318 return GenericsGenerationResults { parent, child, self_ty_propagation_kind: None };
319 }
320
321 let delegation_in_free_ctx =
322 !#[allow(non_exhaustive_omitted_patterns)] match delegation_parent_kind {
DefKind::Trait | DefKind::Impl { .. } => true,
_ => false,
}matches!(delegation_parent_kind, DefKind::Trait | DefKind::Impl { .. });
323
324 let sig_parent = self.tcx.parent(sig_id);
325 let sig_in_trait = #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(sig_parent)
{
DefKind::Trait => true,
_ => false,
}matches!(self.tcx.def_kind(sig_parent), DefKind::Trait);
326 let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait;
327
328 let qself_is_infer =
329 delegation.qself.as_ref().is_some_and(|qself| qself.ty.is_maybe_parenthesised_infer());
330
331 let qself_is_none = delegation.qself.is_none();
332
333 let generate_self = free_to_trait_delegation && (qself_is_none || qself_is_infer);
334
335 let can_add_generics_to_parent = len >= 2
336 && self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
337 #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(def_id) {
DefKind::Trait | DefKind::TraitAlias => true,
_ => false,
}matches!(self.tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias)
338 });
339
340 let parent_generics = if can_add_generics_to_parent {
341 let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params;
342
343 if let Some(args) = get_user_args(len - 2) {
344 DelegationGenerics {
345 data: self.create_slots_from_args(
346 args,
347 &sig_parent_params[usize::from(!generate_self)..],
348 generate_self,
349 ),
350 pos: GenericsPosition::Parent,
351 trait_impl: false,
352 }
353 } else {
354 DelegationGenerics::generate_all(
355 &sig_parent_params[usize::from(!generate_self)..],
356 GenericsPosition::Parent,
357 false,
358 )
359 }
360 } else {
361 DelegationGenerics { data: ::alloc::vec::Vec::new()vec![], pos: GenericsPosition::Parent, trait_impl: false }
362 };
363
364 let child_generics = if let Some(args) = get_user_args(len - 1) {
365 let synth_params_index =
366 sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len());
367
368 let mut slots =
369 self.create_slots_from_args(args, &sig_params[..synth_params_index], false);
370
371 for synth_param in &sig_params[synth_params_index..] {
372 slots.push(GenericArgSlot::Generate(synth_param, None));
373 }
374
375 DelegationGenerics { data: slots, pos: GenericsPosition::Child, trait_impl: false }
376 } else {
377 DelegationGenerics::generate_all(sig_params, GenericsPosition::Child, false)
378 };
379
380 GenericsGenerationResults {
381 parent: GenericsGenerationResult::new(parent_generics),
382 child: GenericsGenerationResult::new(child_generics),
383 self_ty_propagation_kind: match free_to_trait_delegation {
384 true => Some(match qself_is_none {
385 true => hir::DelegationSelfTyPropagationKind::SelfParam,
386 false => match qself_is_infer {
387 true => hir::DelegationSelfTyPropagationKind::SelfParam,
388 false => hir::DelegationSelfTyPropagationKind::SelfTy(HirId::INVALID),
390 },
391 }),
392 false => None,
393 },
394 }
395 }
396
397 fn create_slots_from_args(
406 &self,
407 args: &AngleBracketedArgs,
408 params: &'hir [ty::GenericParamDef],
409 add_first_self: bool,
410 ) -> TyGenerics<'hir> {
411 let mut slots = ::alloc::vec::Vec::new()vec![];
412 if add_first_self {
413 slots.push(GenericArgSlot::Generate(¶ms[0], None));
414 }
415
416 let params = ¶ms[usize::from(add_first_self)..];
417 for (idx, (arg, param)) in args.args.iter().zip(params).enumerate() {
418 let AngleBracketedArg::Arg(arg) = arg else { continue };
419
420 let is_infer = match arg {
421 GenericArg::Lifetime(lt) => lt.ident.name == kw::UnderscoreLifetime,
422 GenericArg::Type(ty) => ty.is_maybe_parenthesised_infer(),
423 GenericArg::Const(_) => false,
424 };
425
426 if is_infer
430 && #[allow(non_exhaustive_omitted_patterns)] match (arg, ¶m.kind) {
(GenericArg::Lifetime(_),
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. })
|
(GenericArg::Type(_) | GenericArg::Const(_),
GenericParamDefKind::Lifetime { .. }) => true,
_ => false,
}matches!(
431 (arg, ¶m.kind),
432 (
433 GenericArg::Lifetime(_),
434 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. }
435 ) | (
436 GenericArg::Type(_) | GenericArg::Const(_),
437 GenericParamDefKind::Lifetime { .. }
438 )
439 )
440 {
441 let (actual, expected) = if #[allow(non_exhaustive_omitted_patterns)] match arg {
GenericArg::Lifetime(..) => true,
_ => false,
}matches!(arg, GenericArg::Lifetime(..)) {
442 (kw::UnderscoreLifetime, kw::Underscore)
443 } else {
444 (kw::Underscore, kw::UnderscoreLifetime)
445 };
446
447 self.tcx.dcx().emit_err(DelegationInfersMismatch {
448 span: arg.span(),
449 actual,
450 expected,
451 });
452 }
453
454 slots.push(match is_infer {
455 true => GenericArgSlot::Generate(param, Some(idx)),
456 false => GenericArgSlot::UserSpecified,
457 });
458 }
459
460 slots
461 }
462
463 fn uplift_delegation_generic_params(
464 &mut self,
465 span: Span,
466 params: &[GenericArgSlot<&ty::GenericParamDef>],
467 rename_self: bool,
468 ) -> &'hir hir::Generics<'hir> {
469 let params = self.arena.alloc_from_iter(params.iter().flat_map(|p| {
470 let GenericArgSlot::Generate(p, _) = p else { return None };
471
472 let def_kind = match p.kind {
473 GenericParamDefKind::Lifetime => DefKind::LifetimeParam,
474 GenericParamDefKind::Type { .. } => DefKind::TyParam,
475 GenericParamDefKind::Const { .. } => DefKind::ConstParam,
476 };
477
478 let param_name =
489 if rename_self && p.name == kw::SelfUpper { sym::This } else { p.name };
490
491 let param_ident = Ident::new(param_name, span);
492 let def_name = Some(param_ident.name);
493 let node_id = self.next_node_id();
494
495 let def_id = self.create_def(node_id, def_name, def_kind, span);
496
497 let kind = match p.kind {
498 GenericParamDefKind::Lifetime => {
499 hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
500 }
501 GenericParamDefKind::Type { synthetic, .. } => {
502 hir::GenericParamKind::Type { default: None, synthetic }
503 }
504 GenericParamDefKind::Const { .. } => {
505 let hir_id = self.next_id();
506 let kind = hir::TyKind::InferDelegation(hir::InferDelegation::DefId(p.def_id));
507
508 hir::GenericParamKind::Const {
509 ty: self.arena.alloc(hir::Ty { kind, hir_id, span }),
510 default: None,
511 }
512 }
513 };
514
515 let hir_id = self.lower_node_id(node_id);
518
519 Some(hir::GenericParam {
520 hir_id,
521 colon_span: Some(span),
522 def_id,
523 kind,
524 name: hir::ParamName::Plain(param_ident),
525 pure_wrt_drop: p.pure_wrt_drop,
526 source: hir::GenericParamSource::Generics,
527 span,
528 })
529 }));
530
531 let predicates =
535 self.arena.alloc_from_iter(params.iter().filter_map(|p| {
536 p.is_lifetime().then(|| self.generate_lifetime_predicate(p, span))
537 }));
538
539 self.arena.alloc(hir::Generics {
540 params,
541 predicates,
542 has_where_clause_predicates: false,
543 where_clause_span: span,
544 span,
545 })
546 }
547
548 fn generate_lifetime_predicate(
549 &mut self,
550 p: &hir::GenericParam<'hir>,
551 span: Span,
552 ) -> hir::WherePredicate<'hir> {
553 let create_lifetime = |this: &mut Self| -> &'hir hir::Lifetime {
554 this.arena.alloc(hir::Lifetime {
555 hir_id: this.next_id(),
556 ident: p.name.ident(),
557 kind: hir::LifetimeKind::Param(p.def_id),
558 source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
559 syntax: hir::LifetimeSyntax::ExplicitBound,
560 })
561 };
562
563 hir::WherePredicate {
564 hir_id: self.next_id(),
565 span,
566 kind: self.arena.alloc(hir::WherePredicateKind::RegionPredicate(
567 hir::WhereRegionPredicate {
568 in_where_clause: true,
569 lifetime: create_lifetime(self),
570 bounds: self
571 .arena
572 .alloc_slice(&[hir::GenericBound::Outlives(create_lifetime(self))]),
573 },
574 )),
575 }
576 }
577
578 pub(super) fn create_generic_arg_path(
579 &mut self,
580 p: &hir::GenericParam<'hir>,
581 ) -> hir::QPath<'hir> {
582 let res = Res::Def(
583 match p.kind {
584 hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
585 hir::GenericParamKind::Type { .. } => DefKind::TyParam,
586 hir::GenericParamKind::Const { .. } => DefKind::ConstParam,
587 },
588 p.def_id.to_def_id(),
589 );
590
591 self.create_resolved_path(res, p.name.ident(), p.span)
592 }
593
594 pub(super) fn create_resolved_path(
595 &mut self,
596 res: Res,
597 ident: Ident,
598 span: Span,
599 ) -> hir::QPath<'hir> {
600 hir::QPath::Resolved(
601 None,
602 self.arena.alloc(hir::Path {
603 segments: self.arena.alloc_slice(&[hir::PathSegment {
604 args: None,
605 hir_id: self.next_id(),
606 ident,
607 infer_args: false,
608 res,
609 delegation_child_segment: false,
610 }]),
611 res,
612 span,
613 }),
614 )
615 }
616}