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