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};
10
11use crate::{LoweringContext, ResolverAstLoweringExt};
12
13pub(super) enum DelegationGenerics<T> {
14 UserSpecified,
16 Default(T),
18 SelfAndUserSpecified(T),
21 TraitImpl(T, bool ),
25}
26
27pub(super) enum HirOrTyGenerics<'hir> {
38 Ty(DelegationGenerics<&'hir [ty::GenericParamDef]>),
39 Hir(DelegationGenerics<&'hir hir::Generics<'hir>>),
40}
41
42pub(super) struct GenericsGenerationResult<'hir> {
43 pub(super) generics: HirOrTyGenerics<'hir>,
44 pub(super) args_segment_id: Option<HirId>,
45}
46
47pub(super) struct GenericsGenerationResults<'hir> {
48 pub(super) parent: GenericsGenerationResult<'hir>,
49 pub(super) child: GenericsGenerationResult<'hir>,
50}
51
52pub(super) struct GenericArgsPropagationDetails {
53 pub(super) should_propagate: bool,
54 pub(super) use_args_in_sig_inheritance: bool,
55}
56
57impl<T> DelegationGenerics<T> {
58 fn args_propagation_details(&self) -> GenericArgsPropagationDetails {
59 match self {
60 DelegationGenerics::UserSpecified | DelegationGenerics::SelfAndUserSpecified { .. } => {
61 GenericArgsPropagationDetails {
62 should_propagate: false,
63 use_args_in_sig_inheritance: true,
64 }
65 }
66 DelegationGenerics::TraitImpl(_, user_specified) => GenericArgsPropagationDetails {
67 should_propagate: !*user_specified,
68 use_args_in_sig_inheritance: false,
69 },
70 DelegationGenerics::Default(_) => GenericArgsPropagationDetails {
71 should_propagate: true,
72 use_args_in_sig_inheritance: false,
73 },
74 }
75 }
76}
77
78impl<'hir> HirOrTyGenerics<'hir> {
79 pub(super) fn into_hir_generics(
80 &mut self,
81 ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
82 span: Span,
83 ) -> &mut HirOrTyGenerics<'hir> {
84 if let HirOrTyGenerics::Ty(params) = self {
85 let mut uplift_params = |generics: &'hir [ty::GenericParamDef]| {
86 ctx.uplift_delegation_generic_params(span, generics)
87 };
88
89 let hir_generics = match params {
90 DelegationGenerics::UserSpecified => DelegationGenerics::UserSpecified,
91 DelegationGenerics::Default(params) => {
92 DelegationGenerics::Default(uplift_params(params))
93 }
94 DelegationGenerics::SelfAndUserSpecified(params) => {
95 DelegationGenerics::SelfAndUserSpecified(uplift_params(params))
96 }
97 DelegationGenerics::TraitImpl(params, user_specified) => {
98 DelegationGenerics::TraitImpl(uplift_params(params), *user_specified)
99 }
100 };
101
102 *self = HirOrTyGenerics::Hir(hir_generics);
103 }
104
105 self
106 }
107
108 fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
109 match self {
110 HirOrTyGenerics::Ty(_) => hir::Generics::empty(),
111 HirOrTyGenerics::Hir(hir_generics) => match hir_generics {
112 DelegationGenerics::UserSpecified => hir::Generics::empty(),
113 DelegationGenerics::Default(generics)
114 | DelegationGenerics::SelfAndUserSpecified(generics)
115 | DelegationGenerics::TraitImpl(generics, _) => generics,
116 },
117 }
118 }
119
120 pub(super) fn into_generic_args(
121 &self,
122 ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
123 add_lifetimes: bool,
124 span: Span,
125 ) -> &'hir hir::GenericArgs<'hir> {
126 match self {
127 HirOrTyGenerics::Ty(_) => {
128 ::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")
129 }
130 HirOrTyGenerics::Hir(hir_generics) => match hir_generics {
131 DelegationGenerics::UserSpecified => hir::GenericArgs::NONE,
132 DelegationGenerics::Default(generics)
133 | DelegationGenerics::SelfAndUserSpecified(generics)
134 | DelegationGenerics::TraitImpl(generics, _) => {
135 ctx.create_generics_args_from_params(generics.params, add_lifetimes, span)
136 }
137 },
138 }
139 }
140
141 pub(super) fn args_propagation_details(&self) -> GenericArgsPropagationDetails {
142 match self {
143 HirOrTyGenerics::Ty(ty_generics) => ty_generics.args_propagation_details(),
144 HirOrTyGenerics::Hir(hir_generics) => hir_generics.args_propagation_details(),
145 }
146 }
147}
148
149impl<'hir> GenericsGenerationResult<'hir> {
150 fn new(
151 generics: DelegationGenerics<&'hir [ty::GenericParamDef]>,
152 ) -> GenericsGenerationResult<'hir> {
153 GenericsGenerationResult { generics: HirOrTyGenerics::Ty(generics), args_segment_id: None }
154 }
155}
156
157impl<'hir> GenericsGenerationResults<'hir> {
158 pub(super) fn all_params(
159 &mut self,
160 span: Span,
161 ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
162 ) -> impl Iterator<Item = hir::GenericParam<'hir>> {
163 let mut create_params = |result: &mut GenericsGenerationResult<'hir>| {
169 result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().params
170 };
171
172 let parent = create_params(&mut self.parent);
173 let child = create_params(&mut self.child);
174
175 parent
180 .iter()
181 .filter(|p| p.is_lifetime())
182 .chain(child.iter().filter(|p| p.is_lifetime()))
183 .chain(parent.iter().filter(|p| !p.is_lifetime()))
184 .chain(child.iter().filter(|p| !p.is_lifetime()))
185 .copied()
186 }
187
188 pub(super) fn all_predicates(
193 &mut self,
194 span: Span,
195 ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
196 ) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
197 let mut create_predicates = |result: &mut GenericsGenerationResult<'hir>| {
203 result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().predicates
204 };
205
206 let parent = create_predicates(&mut self.parent);
207 let child = create_predicates(&mut self.child);
208
209 parent.into_iter().chain(child).copied()
210 }
211}
212
213impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
214 pub(super) fn uplift_delegation_generics(
215 &mut self,
216 delegation: &Delegation,
217 sig_id: DefId,
218 item_id: NodeId,
219 ) -> GenericsGenerationResults<'hir> {
220 let delegation_parent_kind =
221 self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id)));
222
223 let segments = &delegation.path.segments;
224 let len = segments.len();
225 let child_user_specified = segments[len - 1].args.is_some();
226
227 let sig_params = &self.tcx.generics_of(sig_id).own_params[..];
228
229 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 }) {
232 let parent = GenericsGenerationResult::new(DelegationGenerics::TraitImpl(&[], true));
235
236 let child = DelegationGenerics::TraitImpl(sig_params, child_user_specified);
237 let child = GenericsGenerationResult::new(child);
238
239 return GenericsGenerationResults { parent, child };
240 }
241
242 let delegation_in_free_ctx =
243 !#[allow(non_exhaustive_omitted_patterns)] match delegation_parent_kind {
DefKind::Trait | DefKind::Impl { .. } => true,
_ => false,
}matches!(delegation_parent_kind, DefKind::Trait | DefKind::Impl { .. });
244
245 let sig_parent = self.tcx.parent(sig_id);
246 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);
247
248 let can_add_generics_to_parent = len >= 2
249 && self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
250 #[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)
251 });
252
253 let generate_self = delegation_in_free_ctx && sig_in_trait;
254 let parent_generics = if can_add_generics_to_parent {
255 let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params[..];
256
257 if segments[len - 2].args.is_some() {
258 if generate_self {
259 DelegationGenerics::SelfAndUserSpecified(&sig_parent_params[..1])
261 } else {
262 DelegationGenerics::UserSpecified
263 }
264 } else {
265 let skip_self = usize::from(!generate_self);
266 DelegationGenerics::Default(&sig_parent_params[skip_self..])
267 }
268 } else {
269 DelegationGenerics::<&'hir [ty::GenericParamDef]>::Default(&[])
270 };
271
272 let child_generics = if child_user_specified {
273 DelegationGenerics::UserSpecified
274 } else {
275 DelegationGenerics::Default(sig_params)
276 };
277
278 GenericsGenerationResults {
279 parent: GenericsGenerationResult::new(parent_generics),
280 child: GenericsGenerationResult::new(child_generics),
281 }
282 }
283
284 fn uplift_delegation_generic_params(
285 &mut self,
286 span: Span,
287 params: &'hir [ty::GenericParamDef],
288 ) -> &'hir hir::Generics<'hir> {
289 let params = self.arena.alloc_from_iter(params.iter().map(|p| {
290 let def_kind = match p.kind {
291 GenericParamDefKind::Lifetime => DefKind::LifetimeParam,
292 GenericParamDefKind::Type { .. } => DefKind::TyParam,
293 GenericParamDefKind::Const { .. } => DefKind::ConstParam,
294 };
295
296 let param_ident = Ident::new(p.name, span);
297 let def_name = Some(param_ident.name);
298 let path_data = def_kind.def_path_data(def_name);
299 let node_id = self.next_node_id();
300
301 let def_id = self.create_def(node_id, def_name, def_kind, path_data, span);
302
303 let kind = match p.kind {
304 GenericParamDefKind::Lifetime => {
305 hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
306 }
307 GenericParamDefKind::Type { synthetic, .. } => {
308 hir::GenericParamKind::Type { default: None, synthetic }
309 }
310 GenericParamDefKind::Const { .. } => {
311 let hir_id = self.next_id();
312 let kind = hir::TyKind::InferDelegation(hir::InferDelegation::DefId(p.def_id));
313
314 hir::GenericParamKind::Const {
315 ty: self.arena.alloc(hir::Ty { kind, hir_id, span }),
316 default: None,
317 }
318 }
319 };
320
321 let hir_id = self.lower_node_id(node_id);
324
325 hir::GenericParam {
326 hir_id,
327 colon_span: Some(span),
328 def_id,
329 kind,
330 name: hir::ParamName::Plain(param_ident),
331 pure_wrt_drop: p.pure_wrt_drop,
332 source: hir::GenericParamSource::Generics,
333 span,
334 }
335 }));
336
337 let predicates =
341 self.arena.alloc_from_iter(params.iter().filter_map(|p| {
342 p.is_lifetime().then(|| self.generate_lifetime_predicate(p, span))
343 }));
344
345 self.arena.alloc(hir::Generics {
346 params,
347 predicates,
348 has_where_clause_predicates: false,
349 where_clause_span: span,
350 span,
351 })
352 }
353
354 fn generate_lifetime_predicate(
355 &mut self,
356 p: &hir::GenericParam<'hir>,
357 span: Span,
358 ) -> hir::WherePredicate<'hir> {
359 let create_lifetime = |this: &mut Self| -> &'hir hir::Lifetime {
360 this.arena.alloc(hir::Lifetime {
361 hir_id: this.next_id(),
362 ident: p.name.ident(),
363 kind: hir::LifetimeKind::Param(p.def_id),
364 source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
365 syntax: hir::LifetimeSyntax::ExplicitBound,
366 })
367 };
368
369 hir::WherePredicate {
370 hir_id: self.next_id(),
371 span,
372 kind: self.arena.alloc(hir::WherePredicateKind::RegionPredicate(
373 hir::WhereRegionPredicate {
374 in_where_clause: true,
375 lifetime: create_lifetime(self),
376 bounds: self
377 .arena
378 .alloc_slice(&[hir::GenericBound::Outlives(create_lifetime(self))]),
379 },
380 )),
381 }
382 }
383
384 fn create_generics_args_from_params(
385 &mut self,
386 params: &[hir::GenericParam<'hir>],
387 add_lifetimes: bool,
388 span: Span,
389 ) -> &'hir hir::GenericArgs<'hir> {
390 self.arena.alloc(hir::GenericArgs {
391 args: self.arena.alloc_from_iter(params.iter().filter_map(|p| {
392 if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() {
394 return None;
395 }
396
397 let create_path = |this: &mut Self| {
398 let res = Res::Def(
399 match p.kind {
400 hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
401 hir::GenericParamKind::Type { .. } => DefKind::TyParam,
402 hir::GenericParamKind::Const { .. } => DefKind::ConstParam,
403 },
404 p.def_id.to_def_id(),
405 );
406
407 hir::QPath::Resolved(
408 None,
409 self.arena.alloc(hir::Path {
410 segments: this.arena.alloc_slice(&[hir::PathSegment {
411 args: None,
412 hir_id: this.next_id(),
413 ident: p.name.ident(),
414 infer_args: false,
415 res,
416 }]),
417 res,
418 span: p.span,
419 }),
420 )
421 };
422
423 match p.kind {
424 hir::GenericParamKind::Lifetime { .. } => match add_lifetimes {
425 true => Some(hir::GenericArg::Lifetime(self.arena.alloc(hir::Lifetime {
426 hir_id: self.next_id(),
427 ident: p.name.ident(),
428 kind: hir::LifetimeKind::Param(p.def_id),
429 source: hir::LifetimeSource::Path {
430 angle_brackets: hir::AngleBrackets::Full,
431 },
432 syntax: hir::LifetimeSyntax::ExplicitBound,
433 }))),
434 false => None,
435 },
436 hir::GenericParamKind::Type { .. } => {
437 Some(hir::GenericArg::Type(self.arena.alloc(hir::Ty {
438 hir_id: self.next_id(),
439 span: p.span,
440 kind: hir::TyKind::Path(create_path(self)),
441 })))
442 }
443 hir::GenericParamKind::Const { .. } => {
444 Some(hir::GenericArg::Const(self.arena.alloc(hir::ConstArg {
445 hir_id: self.next_id(),
446 kind: hir::ConstArgKind::Path(create_path(self)),
447 span: p.span,
448 })))
449 }
450 }
451 })),
452 constraints: &[],
453 parenthesized: hir::GenericArgsParentheses::No,
454 span_ext: span,
455 })
456 }
457}