rustc_ast_lowering/delegation/
generics.rs1use hir::HirId;
2use hir::def::{DefKind, Res};
3use rustc_ast::*;
4use rustc_hir as hir;
5use rustc_hir::def_id::DefId;
6use rustc_middle::ty::GenericParamDefKind;
7use rustc_middle::{bug, ty};
8use rustc_span::symbol::kw;
9use rustc_span::{Ident, Span, sym};
10
11use crate::LoweringContext;
12
13#[derive(#[automatically_derived]
impl ::core::clone::Clone for DelegationGenericsKind {
#[inline]
fn clone(&self) -> DelegationGenericsKind {
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DelegationGenericsKind { }Copy)]
14pub(super) enum DelegationGenericsKind {
15 UserSpecified,
17 Default,
19 SelfAndUserSpecified,
22 TraitImpl(bool ),
26}
27
28#[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)]
29pub(super) enum GenericsPosition {
30 Parent,
31 Child,
32}
33
34pub(super) struct DelegationGenerics<T> {
35 generics: T,
36 kind: DelegationGenericsKind,
37 pos: GenericsPosition,
38}
39
40impl<'hir> DelegationGenerics<&'hir [ty::GenericParamDef]> {
41 fn default(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self {
42 DelegationGenerics { generics, pos, kind: DelegationGenericsKind::Default }
43 }
44
45 fn user_specified(generics: &'hir [ty::GenericParamDef], pos: GenericsPosition) -> Self {
46 DelegationGenerics { generics, pos, kind: DelegationGenericsKind::UserSpecified }
47 }
48
49 fn trait_impl(
50 generics: &'hir [ty::GenericParamDef],
51 user_specified: bool,
52 pos: GenericsPosition,
53 ) -> Self {
54 DelegationGenerics {
55 generics,
56 pos,
57 kind: DelegationGenericsKind::TraitImpl(user_specified),
58 }
59 }
60}
61
62pub(super) enum HirOrTyGenerics<'hir> {
73 Ty(DelegationGenerics<&'hir [ty::GenericParamDef]>),
74 Hir(DelegationGenerics<&'hir hir::Generics<'hir>>),
75}
76
77pub(super) struct GenericsGenerationResult<'hir> {
78 pub(super) generics: HirOrTyGenerics<'hir>,
79 pub(super) args_segment_id: Option<HirId>,
80}
81
82pub(super) struct GenericsGenerationResults<'hir> {
83 pub(super) parent: GenericsGenerationResult<'hir>,
84 pub(super) child: GenericsGenerationResult<'hir>,
85 pub(super) self_ty_id: Option<HirId>,
86 pub(super) propagate_self_ty: bool,
87}
88
89pub(super) struct GenericArgsPropagationDetails {
90 pub(super) should_propagate: bool,
91 pub(super) use_args_in_sig_inheritance: bool,
92}
93
94impl DelegationGenericsKind {
95 fn args_propagation_details(self) -> GenericArgsPropagationDetails {
96 match self {
97 DelegationGenericsKind::UserSpecified
98 | DelegationGenericsKind::SelfAndUserSpecified => GenericArgsPropagationDetails {
99 should_propagate: false,
100 use_args_in_sig_inheritance: true,
101 },
102 DelegationGenericsKind::TraitImpl(user_specified) => GenericArgsPropagationDetails {
103 should_propagate: !user_specified,
104 use_args_in_sig_inheritance: false,
105 },
106 DelegationGenericsKind::Default => GenericArgsPropagationDetails {
107 should_propagate: true,
108 use_args_in_sig_inheritance: false,
109 },
110 }
111 }
112}
113
114impl<'hir> HirOrTyGenerics<'hir> {
115 pub(super) fn into_hir_generics(
116 &mut self,
117 ctx: &mut LoweringContext<'_, 'hir>,
118 span: Span,
119 ) -> &mut HirOrTyGenerics<'hir> {
120 if let HirOrTyGenerics::Ty(ty) = self {
121 let rename_self = #[allow(non_exhaustive_omitted_patterns)] match ty.pos {
GenericsPosition::Child => true,
_ => false,
}matches!(ty.pos, GenericsPosition::Child);
122 let params = ctx.uplift_delegation_generic_params(span, ty.generics, rename_self);
123
124 *self = HirOrTyGenerics::Hir(DelegationGenerics {
125 generics: params,
126 kind: ty.kind,
127 pos: ty.pos,
128 });
129 }
130
131 self
132 }
133
134 fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
135 match self {
136 HirOrTyGenerics::Ty(_) => hir::Generics::empty(),
137 HirOrTyGenerics::Hir(hir) => hir.generics,
138 }
139 }
140
141 pub(super) fn into_generic_args(
142 &self,
143 ctx: &mut LoweringContext<'_, 'hir>,
144 span: Span,
145 ) -> &'hir hir::GenericArgs<'hir> {
146 match self {
147 HirOrTyGenerics::Ty(_) => {
148 ::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")
149 }
150 HirOrTyGenerics::Hir(hir) => {
151 let add_lifetimes = #[allow(non_exhaustive_omitted_patterns)] match hir.pos {
GenericsPosition::Parent => true,
_ => false,
}matches!(hir.pos, GenericsPosition::Parent);
152 ctx.create_generics_args_from_params(hir.generics.params, add_lifetimes, span)
153 }
154 }
155 }
156
157 pub(super) fn args_propagation_details(&self) -> GenericArgsPropagationDetails {
158 match self {
159 HirOrTyGenerics::Ty(ty) => ty.kind.args_propagation_details(),
160 HirOrTyGenerics::Hir(hir) => hir.kind.args_propagation_details(),
161 }
162 }
163}
164
165impl<'hir> GenericsGenerationResult<'hir> {
166 fn new(
167 generics: DelegationGenerics<&'hir [ty::GenericParamDef]>,
168 ) -> GenericsGenerationResult<'hir> {
169 GenericsGenerationResult { generics: HirOrTyGenerics::Ty(generics), args_segment_id: None }
170 }
171}
172
173impl<'hir> GenericsGenerationResults<'hir> {
174 pub(super) fn all_params(
175 &mut self,
176 span: Span,
177 ctx: &mut LoweringContext<'_, 'hir>,
178 ) -> impl Iterator<Item = hir::GenericParam<'hir>> {
179 let mut create_params = |result: &mut GenericsGenerationResult<'hir>| {
185 result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().params
186 };
187
188 let parent = create_params(&mut self.parent);
189 let child = create_params(&mut self.child);
190
191 parent
196 .iter()
197 .filter(|p| p.is_lifetime())
198 .chain(child.iter().filter(|p| p.is_lifetime()))
199 .chain(parent.iter().filter(|p| !p.is_lifetime()))
200 .chain(child.iter().filter(|p| !p.is_lifetime()))
201 .copied()
202 }
203
204 pub(super) fn all_predicates(
209 &mut self,
210 span: Span,
211 ctx: &mut LoweringContext<'_, 'hir>,
212 ) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
213 let mut create_predicates = |result: &mut GenericsGenerationResult<'hir>| {
219 result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().predicates
220 };
221
222 let parent = create_predicates(&mut self.parent);
223 let child = create_predicates(&mut self.child);
224
225 parent.into_iter().chain(child).copied()
226 }
227}
228
229impl<'hir> LoweringContext<'_, 'hir> {
230 pub(super) fn uplift_delegation_generics(
231 &mut self,
232 delegation: &Delegation,
233 sig_id: DefId,
234 item_id: NodeId,
235 is_method: bool,
236 ) -> GenericsGenerationResults<'hir> {
237 let delegation_parent_kind =
238 self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id)));
239
240 let segments = &delegation.path.segments;
241 let len = segments.len();
242 let child_user_specified = segments[len - 1].args.is_some();
243
244 let sig_params = &self.tcx.generics_of(sig_id).own_params[..];
245
246 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 }) {
249 let parent = DelegationGenerics::trait_impl(&[], true, GenericsPosition::Parent);
252 let parent = GenericsGenerationResult::new(parent);
253
254 let child = DelegationGenerics::trait_impl(
255 sig_params,
256 child_user_specified,
257 GenericsPosition::Child,
258 );
259
260 let child = GenericsGenerationResult::new(child);
261
262 return GenericsGenerationResults {
263 parent,
264 child,
265 self_ty_id: None,
266 propagate_self_ty: false,
267 };
268 }
269
270 let delegation_in_free_ctx =
271 !#[allow(non_exhaustive_omitted_patterns)] match delegation_parent_kind {
DefKind::Trait | DefKind::Impl { .. } => true,
_ => false,
}matches!(delegation_parent_kind, DefKind::Trait | DefKind::Impl { .. });
272
273 let sig_parent = self.tcx.parent(sig_id);
274 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);
275 let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait;
276 let generate_self = free_to_trait_delegation && is_method && delegation.qself.is_none();
277
278 let can_add_generics_to_parent = len >= 2
279 && self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
280 #[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)
281 });
282
283 let parent_generics = if can_add_generics_to_parent {
284 let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params[..];
285
286 if segments[len - 2].args.is_some() {
287 if generate_self {
288 DelegationGenerics {
290 kind: DelegationGenericsKind::SelfAndUserSpecified,
291 generics: &sig_parent_params[..1],
292 pos: GenericsPosition::Parent,
293 }
294 } else {
295 DelegationGenerics::user_specified(&[], GenericsPosition::Parent)
296 }
297 } else {
298 let skip_self = usize::from(!generate_self);
299 DelegationGenerics::default(
300 &sig_parent_params[skip_self..],
301 GenericsPosition::Parent,
302 )
303 }
304 } else {
305 DelegationGenerics::default(&[], GenericsPosition::Parent)
306 };
307
308 let child_generics = if child_user_specified {
309 let synth_params_index =
310 sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len());
311
312 DelegationGenerics::user_specified(
313 &sig_params[synth_params_index..],
314 GenericsPosition::Child,
315 )
316 } else {
317 DelegationGenerics::default(sig_params, GenericsPosition::Child)
318 };
319
320 GenericsGenerationResults {
321 parent: GenericsGenerationResult::new(parent_generics),
322 child: GenericsGenerationResult::new(child_generics),
323 self_ty_id: None,
324 propagate_self_ty: free_to_trait_delegation && !generate_self,
325 }
326 }
327
328 fn uplift_delegation_generic_params(
329 &mut self,
330 span: Span,
331 params: &'hir [ty::GenericParamDef],
332 rename_self: bool,
333 ) -> &'hir hir::Generics<'hir> {
334 let params = self.arena.alloc_from_iter(params.iter().map(|p| {
335 let def_kind = match p.kind {
336 GenericParamDefKind::Lifetime => DefKind::LifetimeParam,
337 GenericParamDefKind::Type { .. } => DefKind::TyParam,
338 GenericParamDefKind::Const { .. } => DefKind::ConstParam,
339 };
340
341 let param_name =
352 if rename_self && p.name == kw::SelfUpper { sym::This } else { p.name };
353
354 let param_ident = Ident::new(param_name, span);
355 let def_name = Some(param_ident.name);
356 let node_id = self.next_node_id();
357
358 let def_id = self.create_def(node_id, def_name, def_kind, span);
359
360 let kind = match p.kind {
361 GenericParamDefKind::Lifetime => {
362 hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
363 }
364 GenericParamDefKind::Type { synthetic, .. } => {
365 hir::GenericParamKind::Type { default: None, synthetic }
366 }
367 GenericParamDefKind::Const { .. } => {
368 let hir_id = self.next_id();
369 let kind = hir::TyKind::InferDelegation(hir::InferDelegation::DefId(p.def_id));
370
371 hir::GenericParamKind::Const {
372 ty: self.arena.alloc(hir::Ty { kind, hir_id, span }),
373 default: None,
374 }
375 }
376 };
377
378 let hir_id = self.lower_node_id(node_id);
381
382 hir::GenericParam {
383 hir_id,
384 colon_span: Some(span),
385 def_id,
386 kind,
387 name: hir::ParamName::Plain(param_ident),
388 pure_wrt_drop: p.pure_wrt_drop,
389 source: hir::GenericParamSource::Generics,
390 span,
391 }
392 }));
393
394 let predicates =
398 self.arena.alloc_from_iter(params.iter().filter_map(|p| {
399 p.is_lifetime().then(|| self.generate_lifetime_predicate(p, span))
400 }));
401
402 self.arena.alloc(hir::Generics {
403 params,
404 predicates,
405 has_where_clause_predicates: false,
406 where_clause_span: span,
407 span,
408 })
409 }
410
411 fn generate_lifetime_predicate(
412 &mut self,
413 p: &hir::GenericParam<'hir>,
414 span: Span,
415 ) -> hir::WherePredicate<'hir> {
416 let create_lifetime = |this: &mut Self| -> &'hir hir::Lifetime {
417 this.arena.alloc(hir::Lifetime {
418 hir_id: this.next_id(),
419 ident: p.name.ident(),
420 kind: hir::LifetimeKind::Param(p.def_id),
421 source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
422 syntax: hir::LifetimeSyntax::ExplicitBound,
423 })
424 };
425
426 hir::WherePredicate {
427 hir_id: self.next_id(),
428 span,
429 kind: self.arena.alloc(hir::WherePredicateKind::RegionPredicate(
430 hir::WhereRegionPredicate {
431 in_where_clause: true,
432 lifetime: create_lifetime(self),
433 bounds: self
434 .arena
435 .alloc_slice(&[hir::GenericBound::Outlives(create_lifetime(self))]),
436 },
437 )),
438 }
439 }
440
441 fn create_generics_args_from_params(
442 &mut self,
443 params: &[hir::GenericParam<'hir>],
444 add_lifetimes: bool,
445 span: Span,
446 ) -> &'hir hir::GenericArgs<'hir> {
447 self.arena.alloc(hir::GenericArgs {
448 args: self.arena.alloc_from_iter(params.iter().filter_map(|p| {
449 if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() {
451 return None;
452 }
453
454 let create_path = |this: &mut Self| {
455 let res = Res::Def(
456 match p.kind {
457 hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
458 hir::GenericParamKind::Type { .. } => DefKind::TyParam,
459 hir::GenericParamKind::Const { .. } => DefKind::ConstParam,
460 },
461 p.def_id.to_def_id(),
462 );
463
464 hir::QPath::Resolved(
465 None,
466 self.arena.alloc(hir::Path {
467 segments: this.arena.alloc_slice(&[hir::PathSegment {
468 args: None,
469 hir_id: this.next_id(),
470 ident: p.name.ident(),
471 infer_args: false,
472 res,
473 }]),
474 res,
475 span: p.span,
476 }),
477 )
478 };
479
480 match p.kind {
481 hir::GenericParamKind::Lifetime { .. } => match add_lifetimes {
482 true => Some(hir::GenericArg::Lifetime(self.arena.alloc(hir::Lifetime {
483 hir_id: self.next_id(),
484 ident: p.name.ident(),
485 kind: hir::LifetimeKind::Param(p.def_id),
486 source: hir::LifetimeSource::Path {
487 angle_brackets: hir::AngleBrackets::Full,
488 },
489 syntax: hir::LifetimeSyntax::ExplicitBound,
490 }))),
491 false => None,
492 },
493 hir::GenericParamKind::Type { .. } => {
494 Some(hir::GenericArg::Type(self.arena.alloc(hir::Ty {
495 hir_id: self.next_id(),
496 span: p.span,
497 kind: hir::TyKind::Path(create_path(self)),
498 })))
499 }
500 hir::GenericParamKind::Const { .. } => {
501 Some(hir::GenericArg::Const(self.arena.alloc(hir::ConstArg {
502 hir_id: self.next_id(),
503 kind: hir::ConstArgKind::Path(create_path(self)),
504 span: p.span,
505 })))
506 }
507 }
508 })),
509 constraints: &[],
510 parenthesized: hir::GenericArgsParentheses::No,
511 span_ext: span,
512 })
513 }
514}