1use 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::sym::{self};
9use rustc_span::symbol::kw;
10use rustc_span::{DUMMY_SP, Ident, Span};
11use thin_vec::{ThinVec, thin_vec};
12
13use crate::{AstOwner, LoweringContext};
14
15pub(super) enum DelegationGenerics<T> {
16 UserSpecified,
18 Default(Option<T>),
20 SelfAndUserSpecified(Option<T>),
23}
24
25pub(super) enum HirOrAstGenerics<'hir> {
37 Ast(DelegationGenerics<Generics>),
38 Hir(DelegationGenerics<&'hir hir::Generics<'hir>>),
39}
40
41pub(super) struct GenericsGenerationResult<'hir> {
42 pub(super) generics: HirOrAstGenerics<'hir>,
43 pub(super) args_segment_id: Option<HirId>,
44}
45
46pub(super) struct GenericsGenerationResults<'hir> {
47 pub(super) parent: GenericsGenerationResult<'hir>,
48 pub(super) child: GenericsGenerationResult<'hir>,
49}
50
51impl<T> DelegationGenerics<T> {
52 fn is_user_specified(&self) -> bool {
53 #[allow(non_exhaustive_omitted_patterns)] match self {
DelegationGenerics::UserSpecified |
DelegationGenerics::SelfAndUserSpecified { .. } => true,
_ => false,
}matches!(
54 self,
55 DelegationGenerics::UserSpecified | DelegationGenerics::SelfAndUserSpecified { .. }
56 )
57 }
58}
59
60impl<'hir> HirOrAstGenerics<'hir> {
61 pub(super) fn into_hir_generics(
62 &mut self,
63 ctx: &mut LoweringContext<'_, 'hir>,
64 item_id: NodeId,
65 span: Span,
66 ) -> &mut HirOrAstGenerics<'hir> {
67 if let HirOrAstGenerics::Ast(generics) = self {
68 let process_params = |generics: &mut Generics| {
69 ctx.lower_delegation_generic_params(item_id, span, &mut generics.params)
70 };
71
72 let hir_generics = match generics {
73 DelegationGenerics::UserSpecified => DelegationGenerics::UserSpecified,
74 DelegationGenerics::Default(generics) => {
75 DelegationGenerics::Default(generics.as_mut().map(process_params))
76 }
77 DelegationGenerics::SelfAndUserSpecified(generics) => {
78 DelegationGenerics::SelfAndUserSpecified(generics.as_mut().map(process_params))
79 }
80 };
81
82 *self = HirOrAstGenerics::Hir(hir_generics);
83 }
84
85 self
86 }
87
88 fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
89 match self {
90 HirOrAstGenerics::Ast(_) => hir::Generics::empty(),
91 HirOrAstGenerics::Hir(hir_generics) => match hir_generics {
92 DelegationGenerics::UserSpecified => hir::Generics::empty(),
93 DelegationGenerics::Default(generics)
94 | DelegationGenerics::SelfAndUserSpecified(generics) => {
95 generics.unwrap_or(hir::Generics::empty())
96 }
97 },
98 }
99 }
100
101 pub(super) fn into_generic_args(
102 &self,
103 ctx: &mut LoweringContext<'_, 'hir>,
104 add_lifetimes: bool,
105 span: Span,
106 ) -> Option<&'hir hir::GenericArgs<'hir>> {
107 match self {
108 HirOrAstGenerics::Ast(_) => {
109 ::rustc_middle::util::bug::bug_fmt(format_args!("Attempting to get generic args before lowering to HIR"))bug!("Attempting to get generic args before lowering to HIR")
110 }
111 HirOrAstGenerics::Hir(hir_generics) => match hir_generics {
112 DelegationGenerics::UserSpecified => None,
113 DelegationGenerics::Default(generics)
114 | DelegationGenerics::SelfAndUserSpecified(generics) => generics.map(|generics| {
115 ctx.create_generics_args_from_params(generics.params, add_lifetimes, span)
116 }),
117 },
118 }
119 }
120
121 pub(super) fn is_user_specified(&self) -> bool {
122 match self {
123 HirOrAstGenerics::Ast(ast_generics) => ast_generics.is_user_specified(),
124 HirOrAstGenerics::Hir(hir_generics) => hir_generics.is_user_specified(),
125 }
126 }
127}
128
129impl<'a> GenericsGenerationResult<'a> {
130 fn new(generics: DelegationGenerics<Generics>) -> GenericsGenerationResult<'a> {
131 GenericsGenerationResult {
132 generics: HirOrAstGenerics::Ast(generics),
133 args_segment_id: None,
134 }
135 }
136}
137
138impl<'hir> GenericsGenerationResults<'hir> {
139 pub(super) fn all_params(
140 &mut self,
141 item_id: NodeId,
142 span: Span,
143 ctx: &mut LoweringContext<'_, 'hir>,
144 ) -> impl Iterator<Item = hir::GenericParam<'hir>> {
145 let parent = self
151 .parent
152 .generics
153 .into_hir_generics(ctx, item_id, span)
154 .hir_generics_or_empty()
155 .params;
156
157 let child = self
158 .child
159 .generics
160 .into_hir_generics(ctx, item_id, span)
161 .hir_generics_or_empty()
162 .params;
163
164 parent
169 .iter()
170 .filter(|p| p.is_lifetime())
171 .chain(child.iter().filter(|p| p.is_lifetime()))
172 .chain(parent.iter().filter(|p| !p.is_lifetime()))
173 .chain(child.iter().filter(|p| !p.is_lifetime()))
174 .copied()
175 }
176
177 pub(super) fn all_predicates(
182 &mut self,
183 item_id: NodeId,
184 span: Span,
185 ctx: &mut LoweringContext<'_, 'hir>,
186 ) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
187 self.parent
193 .generics
194 .into_hir_generics(ctx, item_id, span)
195 .hir_generics_or_empty()
196 .predicates
197 .into_iter()
198 .chain(
199 self.child
200 .generics
201 .into_hir_generics(ctx, item_id, span)
202 .hir_generics_or_empty()
203 .predicates
204 .into_iter(),
205 )
206 .copied()
207 }
208}
209
210impl<'hir> LoweringContext<'_, 'hir> {
211 pub(super) fn lower_delegation_generics(
212 &mut self,
213 delegation: &Delegation,
214 root_fn_id: DefId,
215 item_id: NodeId,
216 span: Span,
217 ) -> GenericsGenerationResults<'hir> {
218 let delegation_in_free_ctx = !#[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id)))
{
DefKind::Trait | DefKind::Impl { .. } => true,
_ => false,
}matches!(
219 self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id))),
220 DefKind::Trait | DefKind::Impl { .. }
221 );
222
223 let root_function_in_trait =
224 #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(self.tcx.parent(root_fn_id))
{
DefKind::Trait => true,
_ => false,
}matches!(self.tcx.def_kind(self.tcx.parent(root_fn_id)), DefKind::Trait);
225
226 let generate_self = delegation_in_free_ctx && root_function_in_trait;
227
228 let parent_generics_factory = |this: &mut Self, user_specified: bool| {
229 this.get_parent_generics(
230 this.tcx.parent(root_fn_id),
231 generate_self,
232 user_specified,
233 span,
234 )
235 };
236
237 let segments = &delegation.path.segments;
238 let len = segments.len();
239
240 let can_add_generics_to_parent = len >= 2
241 && self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
242 #[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)
243 });
244
245 let parent_generics = if can_add_generics_to_parent {
246 if segments[len - 2].args.is_some() {
247 if generate_self {
248 DelegationGenerics::SelfAndUserSpecified(parent_generics_factory(self, true))
249 } else {
250 DelegationGenerics::UserSpecified
251 }
252 } else {
253 DelegationGenerics::Default(parent_generics_factory(self, false))
254 }
255 } else {
256 DelegationGenerics::Default(None)
257 };
258
259 let child_generics = if segments[len - 1].args.is_some() {
260 DelegationGenerics::UserSpecified
261 } else {
262 DelegationGenerics::Default(self.get_fn_like_generics(root_fn_id, span))
263 };
264
265 GenericsGenerationResults {
266 parent: GenericsGenerationResult::new(parent_generics),
267 child: GenericsGenerationResult::new(child_generics),
268 }
269 }
270
271 fn lower_delegation_generic_params(
272 &mut self,
273 item_id: NodeId,
274 span: Span,
275 params: &mut ThinVec<GenericParam>,
276 ) -> &'hir hir::Generics<'hir> {
277 for p in params.iter_mut() {
278 p.id = self.next_node_id();
281
282 match &mut p.kind {
285 GenericParamKind::Lifetime => {}
286 GenericParamKind::Type { default } => *default = None,
287 GenericParamKind::Const { default, .. } => *default = None,
288 }
289
290 self.resolver.node_id_to_def_id.insert(
293 p.id,
294 self.tcx
295 .create_def(
296 self.resolver.node_id_to_def_id[&item_id],
297 Some(p.ident.name),
298 match p.kind {
299 GenericParamKind::Lifetime => DefKind::LifetimeParam,
300 GenericParamKind::Type { .. } => DefKind::TyParam,
301 GenericParamKind::Const { .. } => DefKind::ConstParam,
302 },
303 None,
304 &mut self.disambiguator,
305 )
306 .def_id(),
307 );
308 }
309
310 let params = self.arena.alloc_from_iter(
312 params.iter().map(|p| self.lower_generic_param(p, hir::GenericParamSource::Generics)),
313 );
314
315 self.arena.alloc(hir::Generics {
320 params,
321 predicates: self.arena.alloc_from_iter(
322 params
323 .iter()
324 .filter_map(|p| p.is_lifetime().then(|| self.generate_lifetime_predicate(p))),
325 ),
326 has_where_clause_predicates: false,
327 where_clause_span: span,
328 span,
329 })
330 }
331
332 fn generate_lifetime_predicate(
333 &mut self,
334 p: &hir::GenericParam<'hir>,
335 ) -> hir::WherePredicate<'hir> {
336 let create_lifetime = |this: &mut Self| -> &'hir hir::Lifetime {
337 this.arena.alloc(hir::Lifetime {
338 hir_id: this.next_id(),
339 ident: p.name.ident(),
340 kind: rustc_hir::LifetimeKind::Param(p.def_id),
341 source: rustc_hir::LifetimeSource::Path {
342 angle_brackets: rustc_hir::AngleBrackets::Full,
343 },
344 syntax: rustc_hir::LifetimeSyntax::ExplicitBound,
345 })
346 };
347
348 hir::WherePredicate {
349 hir_id: self.next_id(),
350 span: DUMMY_SP,
351 kind: self.arena.alloc(hir::WherePredicateKind::RegionPredicate(
352 hir::WhereRegionPredicate {
353 in_where_clause: true,
354 lifetime: create_lifetime(self),
355 bounds: self
356 .arena
357 .alloc_slice(&[hir::GenericBound::Outlives(create_lifetime(self))]),
358 },
359 )),
360 }
361 }
362
363 fn create_generics_args_from_params(
364 &mut self,
365 params: &[hir::GenericParam<'hir>],
366 add_lifetimes: bool,
367 span: Span,
368 ) -> &'hir hir::GenericArgs<'hir> {
369 self.arena.alloc(hir::GenericArgs {
370 args: self.arena.alloc_from_iter(params.iter().filter_map(|p| {
371 if p.name.ident().name == kw::SelfUpper {
373 return None;
374 }
375
376 let create_path = |this: &mut Self| {
377 let res = Res::Def(
378 match p.kind {
379 hir::GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
380 hir::GenericParamKind::Type { .. } => DefKind::TyParam,
381 hir::GenericParamKind::Const { .. } => DefKind::ConstParam,
382 },
383 p.def_id.to_def_id(),
384 );
385
386 hir::QPath::Resolved(
387 None,
388 self.arena.alloc(hir::Path {
389 segments: this.arena.alloc_slice(&[hir::PathSegment {
390 args: None,
391 hir_id: this.next_id(),
392 ident: p.name.ident(),
393 infer_args: false,
394 res,
395 }]),
396 res,
397 span: p.span,
398 }),
399 )
400 };
401
402 match p.kind {
403 hir::GenericParamKind::Lifetime { .. } => match add_lifetimes {
404 true => Some(hir::GenericArg::Lifetime(self.arena.alloc(hir::Lifetime {
405 hir_id: self.next_id(),
406 ident: p.name.ident(),
407 kind: hir::LifetimeKind::Param(p.def_id),
408 source: hir::LifetimeSource::Path {
409 angle_brackets: hir::AngleBrackets::Full,
410 },
411 syntax: hir::LifetimeSyntax::ExplicitBound,
412 }))),
413 false => None,
414 },
415 hir::GenericParamKind::Type { .. } => {
416 Some(hir::GenericArg::Type(self.arena.alloc(hir::Ty {
417 hir_id: self.next_id(),
418 span: p.span,
419 kind: hir::TyKind::Path(create_path(self)),
420 })))
421 }
422 hir::GenericParamKind::Const { .. } => {
423 Some(hir::GenericArg::Const(self.arena.alloc(hir::ConstArg {
424 hir_id: self.next_id(),
425 kind: hir::ConstArgKind::Path(create_path(self)),
426 span: p.span,
427 })))
428 }
429 }
430 })),
431 constraints: &[],
432 parenthesized: hir::GenericArgsParentheses::No,
433 span_ext: span,
434 })
435 }
436
437 fn get_fn_like_generics(&mut self, id: DefId, span: Span) -> Option<Generics> {
438 if let Some(local_id) = id.as_local() {
439 match self.ast_index.get(local_id) {
440 Some(AstOwner::Item(item)) if let ItemKind::Fn(f) = &item.kind => {
441 Some(f.generics.clone())
442 }
443 Some(AstOwner::AssocItem(item, _)) if let AssocItemKind::Fn(f) = &item.kind => {
444 Some(f.generics.clone())
445 }
446 _ => None,
447 }
448 } else {
449 self.get_external_generics(id, false, span)
450 }
451 }
452
453 fn get_external_generics(
454 &mut self,
455 id: DefId,
456 processing_parent: bool,
457 span: Span,
458 ) -> Option<Generics> {
459 let generics = self.tcx.generics_of(id);
460 if generics.own_params.is_empty() {
461 return None;
462 }
463
464 let to_skip = (processing_parent && generics.has_self) as usize;
466
467 Some(Generics {
468 params: generics
469 .own_params
470 .iter()
471 .skip(to_skip)
472 .map(|p| GenericParam {
473 attrs: Default::default(),
474 bounds: Default::default(),
475 colon_span: None,
476 id: self.next_node_id(),
477 ident: Ident::with_dummy_span(p.name),
478 is_placeholder: false,
479 kind: match p.kind {
480 GenericParamDefKind::Lifetime => GenericParamKind::Lifetime,
481 GenericParamDefKind::Type { .. } => {
482 GenericParamKind::Type { default: None }
483 }
484 GenericParamDefKind::Const { .. } => self.map_const_kind(p, span),
485 },
486 })
487 .collect(),
488 where_clause: Default::default(),
489 span: DUMMY_SP,
490 })
491 }
492
493 fn map_const_kind(&mut self, p: &ty::GenericParamDef, span: Span) -> GenericParamKind {
494 let const_type = self.tcx.type_of(p.def_id).instantiate_identity();
495
496 let (type_symbol, res) = match const_type.kind() {
497 ty::Bool => (sym::bool, Res::PrimTy(hir::PrimTy::Bool)),
498 ty::Uint(uint) => (uint.name(), Res::PrimTy(hir::PrimTy::Uint(*uint))),
499 ty::Int(int) => (int.name(), Res::PrimTy(hir::PrimTy::Int(*int))),
500 ty::Char => (sym::char, Res::PrimTy(hir::PrimTy::Char)),
501 _ => {
502 self.tcx
503 .dcx()
504 .span_delayed_bug(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Unexpected const type: {0}",
const_type))
})format!("Unexpected const type: {}", const_type));
505
506 (sym::dummy, Res::Err)
507 }
508 };
509
510 let node_id = self.next_node_id();
511
512 self.resolver.partial_res_map.insert(node_id, hir::def::PartialRes::new(res));
513
514 GenericParamKind::Const {
515 ty: Box::new(Ty {
516 id: node_id,
517 kind: TyKind::Path(
518 None,
519 Path {
520 segments: {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(PathSegment {
ident: Ident::with_dummy_span(type_symbol),
id: self.next_node_id(),
args: None,
});
vec
}thin_vec![PathSegment {
521 ident: Ident::with_dummy_span(type_symbol),
522 id: self.next_node_id(),
523 args: None
524 }],
525 span: DUMMY_SP,
526 tokens: None,
527 },
528 ),
529 span: DUMMY_SP,
530 tokens: None,
531 }),
532 span: DUMMY_SP,
533 default: None,
534 }
535 }
536
537 fn get_parent_generics(
538 &mut self,
539 id: DefId,
540 add_self: bool,
541 user_specified: bool,
542 span: Span,
543 ) -> Option<Generics> {
544 let mut generics = if user_specified {
546 None
547 } else {
548 if let Some(local_id) = id.as_local() {
549 if let Some(AstOwner::Item(item)) = self.ast_index.get(local_id)
550 && #[allow(non_exhaustive_omitted_patterns)] match item.kind {
ItemKind::Trait(..) => true,
_ => false,
}matches!(item.kind, ItemKind::Trait(..))
551 {
552 item.opt_generics().cloned()
553 } else {
554 None
555 }
556 } else {
557 self.get_external_generics(id, true, span)
558 }
559 };
560
561 if add_self {
562 generics.get_or_insert_default().params.insert(
563 0,
564 GenericParam {
565 id: self.next_node_id(),
566 ident: Ident::new(kw::SelfUpper, DUMMY_SP),
567 attrs: Default::default(),
568 bounds: ::alloc::vec::Vec::new()vec![],
569 is_placeholder: false,
570 kind: GenericParamKind::Type { default: None },
571 colon_span: None,
572 },
573 );
574 }
575
576 generics
577 }
578}