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)]
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 = #[allow(non_exhaustive_omitted_patterns)] match ty.pos {
GenericsPosition::Child => true,
_ => false,
}matches!(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
223impl<'hir> GenericsGenerationResult<'hir> {
224 fn new(generics: DelegationGenerics<TyGenerics<'hir>>) -> GenericsGenerationResult<'hir> {
225 GenericsGenerationResult {
226 generics: HirOrTyGenerics::Ty(generics),
227 args_segment_id: HirId::INVALID,
228 use_for_sig_inheritance: false,
229 }
230 }
231}
232
233impl<'hir> GenericsGenerationResults<'hir> {
234 pub(super) fn all_params(&self) -> impl Iterator<Item = hir::GenericParam<'hir>> {
235 let parent = self.parent.generics.hir_generics_or_empty().params;
236 let child = self.child.generics.hir_generics_or_empty().params;
237
238 parent
243 .iter()
244 .filter(|p| p.is_lifetime())
245 .chain(child.iter().filter(|p| p.is_lifetime()))
246 .chain(parent.iter().filter(|p| !p.is_lifetime()))
247 .chain(child.iter().filter(|p| !p.is_lifetime()))
248 .copied()
249 }
250
251 pub(super) fn all_predicates(&self) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
256 self.parent
257 .generics
258 .hir_generics_or_empty()
259 .predicates
260 .into_iter()
261 .chain(self.child.generics.hir_generics_or_empty().predicates)
262 .copied()
263 }
264}
265
266impl<'hir> LoweringContext<'_, 'hir> {
267 pub(super) fn uplift_delegation_generics(
268 &mut self,
269 delegation: &Delegation,
270 sig_id: DefId,
271 ) -> GenericsGenerationResults<'hir> {
272 let delegation_parent_kind = self.tcx.def_kind(self.tcx.local_parent(self.owner.def_id));
273
274 let segments = &delegation.path.segments;
275 let len = segments.len();
276
277 let get_user_args = |idx: usize| -> Option<&AngleBracketedArgs> {
278 let segment = &segments[idx];
279
280 let Some(args) = segment.args.as_ref() else { return None };
281 let GenericArgs::AngleBracketed(args) = args else {
282 self.tcx.dcx().span_delayed_bug(
283 segment.span(),
284 "expected angle-bracketed generic args in delegation segment",
285 );
286
287 return None;
288 };
289
290 (!args.args.is_empty()).then(|| args)
294 };
295
296 let sig_params = &self.tcx.generics_of(sig_id).own_params[..];
297
298 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 }) {
301 let parent =
304 DelegationGenerics { data: ::alloc::vec::Vec::new()vec![], pos: GenericsPosition::Child, trait_impl: true };
305
306 let parent = GenericsGenerationResult::new(parent);
307
308 let child = DelegationGenerics::generate_all(sig_params, GenericsPosition::Child, true);
309 let child = GenericsGenerationResult::new(child);
310
311 return GenericsGenerationResults { parent, child, self_ty_propagation_kind: None };
312 }
313
314 let delegation_in_free_ctx =
315 !#[allow(non_exhaustive_omitted_patterns)] match delegation_parent_kind {
DefKind::Trait | DefKind::Impl { .. } => true,
_ => false,
}matches!(delegation_parent_kind, DefKind::Trait | DefKind::Impl { .. });
316
317 let sig_parent = self.tcx.parent(sig_id);
318 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);
319 let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait;
320
321 let qself_is_infer =
322 delegation.qself.as_ref().is_some_and(|qself| qself.ty.is_maybe_parenthesised_infer());
323
324 let qself_is_none = delegation.qself.is_none();
325
326 let generate_self = free_to_trait_delegation && (qself_is_none || qself_is_infer);
327
328 let can_add_generics_to_parent = len >= 2
329 && self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
330 #[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)
331 });
332
333 let parent_generics = if can_add_generics_to_parent {
334 let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params;
335
336 if let Some(args) = get_user_args(len - 2) {
337 DelegationGenerics {
338 data: self.create_slots_from_args(
339 args,
340 &sig_parent_params[usize::from(!generate_self)..],
341 generate_self,
342 ),
343 pos: GenericsPosition::Parent,
344 trait_impl: false,
345 }
346 } else {
347 DelegationGenerics::generate_all(
348 &sig_parent_params[usize::from(!generate_self)..],
349 GenericsPosition::Parent,
350 false,
351 )
352 }
353 } else {
354 DelegationGenerics { data: ::alloc::vec::Vec::new()vec![], pos: GenericsPosition::Parent, trait_impl: false }
355 };
356
357 let child_generics = if let Some(args) = get_user_args(len - 1) {
358 let synth_params_index =
359 sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len());
360
361 let mut slots =
362 self.create_slots_from_args(args, &sig_params[..synth_params_index], false);
363
364 for synth_param in &sig_params[synth_params_index..] {
365 slots.push(GenericArgSlot::Generate(synth_param, None));
366 }
367
368 DelegationGenerics { data: slots, pos: GenericsPosition::Child, trait_impl: false }
369 } else {
370 DelegationGenerics::generate_all(sig_params, GenericsPosition::Child, false)
371 };
372
373 GenericsGenerationResults {
374 parent: GenericsGenerationResult::new(parent_generics),
375 child: GenericsGenerationResult::new(child_generics),
376 self_ty_propagation_kind: match free_to_trait_delegation {
377 true => Some(match qself_is_none {
378 true => hir::DelegationSelfTyPropagationKind::SelfParam,
379 false => match qself_is_infer {
380 true => hir::DelegationSelfTyPropagationKind::SelfParam,
381 false => hir::DelegationSelfTyPropagationKind::SelfTy(HirId::INVALID),
383 },
384 }),
385 false => None,
386 },
387 }
388 }
389
390 fn create_slots_from_args(
399 &self,
400 args: &AngleBracketedArgs,
401 params: &'hir [ty::GenericParamDef],
402 add_first_self: bool,
403 ) -> TyGenerics<'hir> {
404 let mut slots = ::alloc::vec::Vec::new()vec![];
405 if add_first_self {
406 slots.push(GenericArgSlot::Generate(¶ms[0], None));
407 }
408
409 let params = ¶ms[usize::from(add_first_self)..];
410 for (idx, (arg, param)) in args.args.iter().zip(params).enumerate() {
411 let AngleBracketedArg::Arg(arg) = arg else { continue };
412
413 let is_infer = match arg {
414 GenericArg::Lifetime(lt) => lt.ident.name == kw::UnderscoreLifetime,
415 GenericArg::Type(ty) => ty.is_maybe_parenthesised_infer(),
416 GenericArg::Const(_) => false,
417 };
418
419 if is_infer
423 && #[allow(non_exhaustive_omitted_patterns)] match (arg, ¶m.kind) {
(GenericArg::Lifetime(_),
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. })
|
(GenericArg::Type(_) | GenericArg::Const(_),
GenericParamDefKind::Lifetime { .. }) => true,
_ => false,
}matches!(
424 (arg, ¶m.kind),
425 (
426 GenericArg::Lifetime(_),
427 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. }
428 ) | (
429 GenericArg::Type(_) | GenericArg::Const(_),
430 GenericParamDefKind::Lifetime { .. }
431 )
432 )
433 {
434 let (actual, expected) = if #[allow(non_exhaustive_omitted_patterns)] match arg {
GenericArg::Lifetime(..) => true,
_ => false,
}matches!(arg, GenericArg::Lifetime(..)) {
435 (kw::UnderscoreLifetime, kw::Underscore)
436 } else {
437 (kw::Underscore, kw::UnderscoreLifetime)
438 };
439
440 self.tcx.dcx().emit_err(DelegationInfersMismatch {
441 span: arg.span(),
442 actual,
443 expected,
444 });
445 }
446
447 slots.push(match is_infer {
448 true => GenericArgSlot::Generate(param, Some(idx)),
449 false => GenericArgSlot::UserSpecified,
450 });
451 }
452
453 slots
454 }
455
456 fn uplift_delegation_generic_params(
457 &mut self,
458 span: Span,
459 params: &[GenericArgSlot<&ty::GenericParamDef>],
460 rename_self: bool,
461 ) -> &'hir hir::Generics<'hir> {
462 let params = self.arena.alloc_from_iter(params.iter().flat_map(|p| {
463 let GenericArgSlot::Generate(p, _) = p else { return None };
464
465 let def_kind = match p.kind {
466 GenericParamDefKind::Lifetime => DefKind::LifetimeParam,
467 GenericParamDefKind::Type { .. } => DefKind::TyParam,
468 GenericParamDefKind::Const { .. } => DefKind::ConstParam,
469 };
470
471 let param_name =
482 if rename_self && p.name == kw::SelfUpper { sym::This } else { p.name };
483
484 let param_ident = Ident::new(param_name, span);
485 let def_name = Some(param_ident.name);
486 let node_id = self.next_node_id();
487
488 let def_id = self.create_def(node_id, def_name, def_kind, span);
489
490 let kind = match p.kind {
491 GenericParamDefKind::Lifetime => {
492 hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
493 }
494 GenericParamDefKind::Type { synthetic, .. } => {
495 hir::GenericParamKind::Type { default: None, synthetic }
496 }
497 GenericParamDefKind::Const { .. } => {
498 let hir_id = self.next_id();
499 let kind = hir::TyKind::InferDelegation(hir::InferDelegation::DefId(p.def_id));
500
501 hir::GenericParamKind::Const {
502 ty: self.arena.alloc(hir::Ty { kind, hir_id, span }),
503 default: None,
504 }
505 }
506 };
507
508 let hir_id = self.lower_node_id(node_id);
511
512 Some(hir::GenericParam {
513 hir_id,
514 colon_span: Some(span),
515 def_id,
516 kind,
517 name: hir::ParamName::Plain(param_ident),
518 pure_wrt_drop: p.pure_wrt_drop,
519 source: hir::GenericParamSource::Generics,
520 span,
521 })
522 }));
523
524 let predicates =
528 self.arena.alloc_from_iter(params.iter().filter_map(|p| {
529 p.is_lifetime().then(|| self.generate_lifetime_predicate(p, span))
530 }));
531
532 self.arena.alloc(hir::Generics {
533 params,
534 predicates,
535 has_where_clause_predicates: false,
536 where_clause_span: span,
537 span,
538 })
539 }
540
541 fn generate_lifetime_predicate(
542 &mut self,
543 p: &hir::GenericParam<'hir>,
544 span: Span,
545 ) -> hir::WherePredicate<'hir> {
546 let create_lifetime = |this: &mut Self| -> &'hir hir::Lifetime {
547 this.arena.alloc(hir::Lifetime {
548 hir_id: this.next_id(),
549 ident: p.name.ident(),
550 kind: hir::LifetimeKind::Param(p.def_id),
551 source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
552 syntax: hir::LifetimeSyntax::ExplicitBound,
553 })
554 };
555
556 hir::WherePredicate {
557 hir_id: self.next_id(),
558 span,
559 kind: self.arena.alloc(hir::WherePredicateKind::RegionPredicate(
560 hir::WhereRegionPredicate {
561 in_where_clause: true,
562 lifetime: create_lifetime(self),
563 bounds: self
564 .arena
565 .alloc_slice(&[hir::GenericBound::Outlives(create_lifetime(self))]),
566 },
567 )),
568 }
569 }
570
571 pub(super) fn create_generic_arg_path(
572 &mut self,
573 p: &hir::GenericParam<'hir>,
574 ) -> hir::QPath<'hir> {
575 let res = Res::Def(
576 match p.kind {
577 hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
578 hir::GenericParamKind::Type { .. } => DefKind::TyParam,
579 hir::GenericParamKind::Const { .. } => DefKind::ConstParam,
580 },
581 p.def_id.to_def_id(),
582 );
583
584 hir::QPath::Resolved(
585 None,
586 self.arena.alloc(hir::Path {
587 segments: self.arena.alloc_slice(&[hir::PathSegment {
588 args: None,
589 hir_id: self.next_id(),
590 ident: p.name.ident(),
591 infer_args: false,
592 res,
593 }]),
594 res,
595 span: p.span,
596 }),
597 )
598 }
599}