1use std::assert_matches;
6
7use rustc_data_structures::fx::{FxHashMap, FxHashSet};
8use rustc_hir::def::DefKind;
9use rustc_hir::def_id::{DefId, LocalDefId};
10use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment};
11use rustc_middle::ty::{
12 self, ConstKind, EarlyBinder, GenericArg, GenericArgKind, RegionKind, Ty, TyCtxt, TypeFoldable,
13 TypeFolder, TypeSuperFoldable, TypeVisitableExt,
14};
15use rustc_span::{ErrorGuaranteed, Span, kw};
16
17use crate::collect::ItemCtxt;
18use crate::hir_ty_lowering::HirTyLowerer;
19
20type RemapTable = FxHashMap<u32, u32>;
21
22struct ParamIndexRemapper<'tcx> {
23 tcx: TyCtxt<'tcx>,
24 remap_table: RemapTable,
25 delegation_parent_consts: FxHashSet<ty::ParamConst>,
26}
27
28impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
29 fn cx(&self) -> TyCtxt<'tcx> {
30 self.tcx
31 }
32
33 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
34 if !ty.has_param() {
35 return ty;
36 }
37
38 if let ty::Param(param) = ty.kind()
39 && let Some(index) = self.remap_table.get(¶m.index)
40 {
41 return Ty::new_param(self.tcx, *index, param.name);
42 }
43 ty.super_fold_with(self)
44 }
45
46 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
47 if let ty::ReEarlyParam(param) = r.kind()
48 && let Some(index) = self.remap_table.get(¶m.index).copied()
49 {
50 return ty::Region::new_early_param(
51 self.tcx,
52 ty::EarlyParamRegion { index, name: param.name },
53 );
54 }
55 r
56 }
57
58 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
59 if let ty::ConstKind::Param(param) = ct.kind()
60 && let Some(idx) = self.remap_table.get(¶m.index)
61 {
62 let param = ty::ParamConst::new(*idx, param.name);
63 return ty::Const::new_param(self.tcx, param);
64 }
65 ct.super_fold_with(self)
66 }
67}
68
69#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SelfPositionKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
SelfPositionKind::AfterLifetimes(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"AfterLifetimes", &__self_0),
SelfPositionKind::Zero =>
::core::fmt::Formatter::write_str(f, "Zero"),
SelfPositionKind::None =>
::core::fmt::Formatter::write_str(f, "None"),
}
}
}Debug)]
70enum SelfPositionKind {
71 AfterLifetimes(Option<DelegationSelfTyPropagationKind>),
72 Zero,
73 None,
74}
75
76fn create_self_param_position_kind(
77 tcx: TyCtxt<'_>,
78 def_id: LocalDefId,
79 sig_id: DefId,
80) -> SelfPositionKind {
81 match fn_kinds(tcx, def_id, sig_id) {
82 (FnKind::Free, FnKind::AssocTrait) => {
83 let kind = tcx.hir_delegation_info(def_id).self_ty_propagation_kind;
84 SelfPositionKind::AfterLifetimes(kind)
85 }
86
87 (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
88
89 (_, FnKind::AssocTrait) | (FnKind::AssocTrait, _) => SelfPositionKind::Zero,
90
91 (FnKind::AssocTraitImpl, _) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
92
93 _ => SelfPositionKind::None,
94 }
95}
96
97#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for FnKind { }
#[automatically_derived]
impl ::core::clone::Clone for FnKind {
#[inline]
fn clone(&self) -> FnKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnKind { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for FnKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
FnKind::Free => "Free",
FnKind::AssocInherentImpl => "AssocInherentImpl",
FnKind::AssocTrait => "AssocTrait",
FnKind::AssocTraitImpl => "AssocTraitImpl",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for FnKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for FnKind {
#[inline]
fn eq(&self, other: &FnKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
98enum FnKind {
99 Free,
100 AssocInherentImpl,
101 AssocTrait,
102 AssocTraitImpl,
103}
104
105fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> FnKind {
106 let def_id = def_id.into();
107
108 match tcx.def_kind(def_id) {
109 DefKind::Fn => FnKind::Free,
110 DefKind::AssocFn => match tcx.def_kind(tcx.parent(def_id)) {
111 DefKind::Trait => FnKind::AssocTrait,
112 DefKind::Impl { of_trait } => match of_trait {
113 true => FnKind::AssocTraitImpl,
114 false => FnKind::AssocInherentImpl,
115 },
116 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("associated function can only be in trait or impl")));
}unreachable!("associated function can only be in trait or impl"),
117 },
118 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("delegation/signature can be either free or associated function")));
}unreachable!("delegation/signature can be either free or associated function"),
119 }
120}
121
122fn fn_kinds(tcx: TyCtxt<'_>, def_id: LocalDefId, sig_id: DefId) -> (FnKind, FnKind) {
123 let kinds = (fn_kind(tcx, def_id), fn_kind(tcx, sig_id));
124
125 if !!#[allow(non_exhaustive_omitted_patterns)] match kinds {
(_, FnKind::AssocTraitImpl) => true,
_ => false,
} {
::core::panicking::panic("assertion failed: !matches!(kinds, (_, FnKind::AssocTraitImpl))")
};assert!(!matches!(kinds, (_, FnKind::AssocTraitImpl)));
127
128 kinds
129}
130
131#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for InheritanceKind { }
#[automatically_derived]
impl ::core::clone::Clone for InheritanceKind {
#[inline]
fn clone(&self) -> InheritanceKind {
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for InheritanceKind { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for InheritanceKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
InheritanceKind::WithParent(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"WithParent", &__self_0),
InheritanceKind::Own =>
::core::fmt::Formatter::write_str(f, "Own"),
}
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for InheritanceKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for InheritanceKind {
#[inline]
fn eq(&self, other: &InheritanceKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(InheritanceKind::WithParent(__self_0),
InheritanceKind::WithParent(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq)]
134enum InheritanceKind {
135 WithParent(bool),
145 Own,
149}
150
151fn create_mapping<'tcx>(
161 tcx: TyCtxt<'tcx>,
162 sig_id: DefId,
163 def_id: LocalDefId,
164) -> FxHashMap<u32, u32> {
165 let mut mapping: FxHashMap<u32, u32> = Default::default();
166
167 let self_pos_kind = create_self_param_position_kind(tcx, def_id, sig_id);
168 let is_self_at_zero = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::Zero => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::Zero);
169
170 if is_self_at_zero {
172 mapping.insert(0, 0);
173 }
174
175 let mut args_index = 0;
176
177 args_index += is_self_at_zero as usize;
178 args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id);
179
180 let parent_kind = fn_kind(tcx, sig_id);
181 let process_parent = #[allow(non_exhaustive_omitted_patterns)] match parent_kind {
FnKind::AssocTrait | FnKind::AssocInherentImpl => true,
_ => false,
}matches!(parent_kind, FnKind::AssocTrait | FnKind::AssocInherentImpl);
182 let parent_generics = process_parent.then(|| tcx.generics_of(tcx.parent(sig_id)));
183
184 let parent_params = match parent_kind {
194 FnKind::AssocInherentImpl => {
195 let ty::Adt(_, args) = tcx.type_of(tcx.parent(sig_id)).skip_binder().kind() else {
196 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("parent of inherent function in delegation can be only struct or enum")));
}unreachable!("parent of inherent function in delegation can be only struct or enum")
197 };
198
199 let opt_param_info = |arg: GenericArg<'_>| match arg.kind() {
200 GenericArgKind::Lifetime(r) => (
201 match r.kind() {
202 RegionKind::ReEarlyParam(p) => Some(p.index),
203 _ => None,
204 },
205 false,
206 ),
207 GenericArgKind::Type(t) => (
208 match t.kind() {
209 ty::Param(p) => Some(p.index),
210 _ => None,
211 },
212 true,
213 ),
214 GenericArgKind::Const(c) => (
215 match c.kind() {
216 ConstKind::Param(p) => Some(p.index),
217 _ => None,
218 },
219 true,
220 ),
221 };
222
223 args.iter().map(opt_param_info).collect::<Vec<_>>()
224 }
225 FnKind::AssocTrait => parent_generics
226 .expect("trait must have generics")
227 .own_params
228 .iter()
229 .map(|p| (Some(p.index as u32), p.kind.is_ty_or_const()))
230 .collect::<Vec<_>>(),
231 _ => ::alloc::vec::Vec::new()vec![],
232 };
233
234 let has_self = match parent_kind {
235 FnKind::AssocTrait => parent_generics.expect("trait must have generics").has_self,
236 _ => false,
237 };
238
239 if process_parent {
240 for i in (has_self as usize)..parent_params.len() {
241 let (index, is_ty_or_const) = parent_params[i];
242 if !is_ty_or_const {
243 if let Some(index) = index {
244 mapping.insert(index, args_index as u32);
245 }
246
247 args_index += 1;
248 }
249 }
250 }
251
252 let child_generics = tcx.generics_of(sig_id);
253 for param in &child_generics.own_params {
254 if !param.kind.is_ty_or_const() {
255 mapping.insert(param.index, args_index as u32);
256 args_index += 1;
257 }
258 }
259
260 if #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes { .. } => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes { .. }) {
264 mapping.insert(0, args_index as u32);
265 args_index += 1;
266 }
267
268 if process_parent {
269 for i in (has_self as usize)..parent_params.len() {
270 let (index, is_ty_or_const) = parent_params[i];
271 if is_ty_or_const {
272 if let Some(index) = index {
273 mapping.insert(index, args_index as u32);
274 }
275
276 args_index += 1;
277 }
278 }
279 }
280
281 for param in &child_generics.own_params {
282 if param.kind.is_ty_or_const() {
283 mapping.insert(param.index, args_index as u32);
284 args_index += 1;
285 }
286 }
287
288 mapping
289}
290
291fn get_delegation_parent_args_count_without_self<'tcx>(
292 tcx: TyCtxt<'tcx>,
293 def_id: LocalDefId,
294 sig_id: DefId,
295) -> usize {
296 let kinds @ (def_kind, _) = fn_kinds(tcx, def_id, sig_id);
297
298 match kinds {
299 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => 0,
300
301 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
302
303 (FnKind::Free, _) => 0,
304
305 (_, _) => {
306 let delegation_parent_args_count = tcx.generics_of(def_id).parent_count;
307 let has_self = def_kind == FnKind::AssocTrait;
308
309 delegation_parent_args_count - usize::from(has_self)
310 }
311 }
312}
313
314fn get_parent_and_inheritance_kind<'tcx>(
315 tcx: TyCtxt<'tcx>,
316 def_id: LocalDefId,
317 sig_id: DefId,
318) -> (Option<DefId>, InheritanceKind) {
319 let kinds @ (_, sig_kind) = fn_kinds(tcx, def_id, sig_id);
320
321 match kinds {
322 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
323 (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::Own)
324 }
325
326 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
327
328 (FnKind::Free, _) => {
329 let copy_self_clauses = sig_kind == FnKind::AssocTrait;
330 (None, InheritanceKind::WithParent(copy_self_clauses))
331 }
332
333 (_, _) => (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::WithParent(false)),
334 }
335}
336
337fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<Ty<'tcx>> {
338 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("processing delegation");
339 let (caller_kind, callee_kind) = fn_kinds(tcx, def_id, sig_id);
340
341 match (caller_kind, callee_kind) {
342 (FnKind::AssocTraitImpl, FnKind::AssocTrait) | (FnKind::AssocInherentImpl, _) => {
343 Some(tcx.type_of(tcx.local_parent(def_id)).instantiate_identity().skip_norm_wip())
344 }
345
346 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
348
349 (_, _) => match create_self_param_position_kind(tcx, def_id, sig_id) {
350 SelfPositionKind::None => None,
351 SelfPositionKind::AfterLifetimes(propagation_kind) => Some(match propagation_kind {
352 Some(kind) => match kind {
353 DelegationSelfTyPropagationKind::SelfTy(self_ty_id) => {
354 let ctx = ItemCtxt::new(tcx, def_id);
355 ctx.lower_ty(tcx.hir_node(self_ty_id).expect_ty())
356 }
357 DelegationSelfTyPropagationKind::SelfParam => {
358 let index = tcx.generics_of(def_id).own_counts().lifetimes;
359 Ty::new_param(tcx, index as u32, kw::SelfUpper)
360 }
361 },
362 None => Ty::new_error_with_message(
363 tcx,
364 tcx.def_span(def_id),
365 "self propagation kind must be specified for `AfterLifetimes` variant",
366 ),
367 }),
368 SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)),
369 },
370 }
371}
372
373fn create_generic_args<'tcx>(
389 tcx: TyCtxt<'tcx>,
390 sig_id: DefId,
391 def_id: LocalDefId,
392 mut parent_args: &[ty::GenericArg<'tcx>],
393 mut child_args: &[ty::GenericArg<'tcx>],
394) -> (Vec<ty::GenericArg<'tcx>>, &'tcx [ty::GenericArg<'tcx>]) {
395 let delegation_generics = tcx.generics_of(def_id);
396 let delegation_args = ty::GenericArgs::identity_for_item(tcx, def_id);
397
398 let real_args_count = delegation_args.len() - delegation_generics.own_synthetic_params_count();
399 let synth_args = &delegation_args[real_args_count..];
400
401 let mut delegation_parent_args =
402 &delegation_args[delegation_generics.has_self as usize..delegation_generics.parent_count];
403
404 let delegation_args = &delegation_args[delegation_generics.parent_count..];
405
406 let kinds @ (_, parent_kind) = fn_kinds(tcx, def_id, sig_id);
407 if #[allow(non_exhaustive_omitted_patterns)] match kinds {
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => true,
_ => false,
}matches!(kinds, (FnKind::AssocTraitImpl, FnKind::AssocTrait)) {
408 let parent = tcx.local_parent(def_id);
412
413 parent_args =
414 tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args;
415
416 child_args =
417 &delegation_args[delegation_args.len() - delegation_generics.own_params.len()..];
418
419 delegation_parent_args = &[];
420 }
421
422 let self_type = get_delegation_self_ty(tcx, def_id).map(ty::GenericArg::from);
423
424 if self_type.is_some() && !parent_args.is_empty() {
425 parent_args = match parent_kind {
426 FnKind::AssocInherentImpl => parent_args,
427 FnKind::AssocTrait => &parent_args[1..],
430 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("if parent args are non-empty then the parent must exist")));
}unreachable!("if parent args are non-empty then the parent must exist"),
431 }
432 }
433
434 let (zero_self, after_lifetimes_self) =
435 match create_self_param_position_kind(tcx, def_id, sig_id) {
436 SelfPositionKind::AfterLifetimes(_) => {
437 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
438 (None, self_type)
439 }
440 SelfPositionKind::Zero => {
441 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
442 (self_type, None)
443 }
444 SelfPositionKind::None => (None, None),
445 };
446
447 let zero_self = zero_self.as_ref().into_iter();
448 let after_lifetimes_self = after_lifetimes_self.as_ref().into_iter();
449
450 let args = zero_self
451 .chain(delegation_parent_args)
452 .chain(parent_args.iter().filter(|a| a.as_region().is_some()))
453 .chain(child_args.iter().filter(|a| a.as_region().is_some()))
454 .chain(after_lifetimes_self)
455 .chain(parent_args.iter().filter(|a| a.as_region().is_none()))
456 .chain(child_args.iter().filter(|a| a.as_region().is_none()))
457 .chain(synth_args)
458 .copied()
459 .collect::<Vec<_>>();
460
461 (args, delegation_parent_args)
462}
463
464pub(crate) fn inherit_clauses_for_delegation_item<'tcx>(
465 tcx: TyCtxt<'tcx>,
466 def_id: LocalDefId,
467 sig_id: DefId,
468) -> ty::GenericClauses<'tcx> {
469 struct ClausesCollector<'tcx> {
470 tcx: TyCtxt<'tcx>,
471 clauses: Vec<(ty::Clause<'tcx>, Span)>,
472 args: Vec<ty::GenericArg<'tcx>>,
473 folder: ParamIndexRemapper<'tcx>,
474 filter_self_clauses: bool,
475 }
476
477 impl<'tcx> ClausesCollector<'tcx> {
478 fn with_own_clauses(
479 mut self,
480 f: impl Fn(DefId) -> ty::GenericClauses<'tcx>,
481 def_id: DefId,
482 ) -> Self {
483 let clauses = f(def_id);
484 let args = self.args.as_slice();
485
486 for clause in clauses.clauses {
487 if self.filter_self_clauses
490 && let Some(trait_clause) = clause.0.as_trait_clause()
491 && trait_clause.self_ty().skip_binder().is_param(0)
493 {
494 continue;
495 }
496
497 if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) =
525 clause.0.as_predicate().fold_with(&mut self.folder).kind().skip_binder()
526 {
527 let unnorm_const = EarlyBinder::bind(self.tcx, ct).instantiate(self.tcx, args);
528 if let ty::ConstKind::Param(param) = unnorm_const.skip_norm_wip().kind()
529 && self.folder.delegation_parent_consts.contains(¶m)
530 {
531 continue;
532 }
533 }
534
535 let new_clause = clause.0.fold_with(&mut self.folder);
536 self.clauses.push((
537 EarlyBinder::bind(self.tcx, new_clause)
538 .instantiate(self.tcx, args)
539 .skip_norm_wip(),
540 clause.1,
541 ));
542 }
543
544 self
545 }
546
547 fn with_clauses(
548 mut self,
549 f: impl Fn(DefId) -> ty::GenericClauses<'tcx> + Copy,
550 def_id: DefId,
551 ) -> Self {
552 let preds = f(def_id);
553 if let Some(parent_def_id) = preds.parent {
554 self = self.with_own_clauses(f, parent_def_id);
555 }
556
557 self.with_own_clauses(f, def_id)
558 }
559 }
560
561 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
562 let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
563 let self_pos_kind = create_self_param_position_kind(tcx, def_id, sig_id);
564 let filter_self_clauses = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
=> true,
_ => false,
}matches!(
565 self_pos_kind,
566 SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
567 );
568
569 let collector = ClausesCollector { tcx, clauses: ::alloc::vec::Vec::new()vec![], args, folder, filter_self_clauses };
570 let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
571
572 let clauses = match inh_kind {
576 InheritanceKind::WithParent(false) => {
577 collector.with_clauses(|def_id| tcx.explicit_clauses_of(def_id), sig_id)
578 }
579 InheritanceKind::WithParent(true) => {
580 collector.with_clauses(|def_id| tcx.clauses_of(def_id), sig_id)
581 }
582 InheritanceKind::Own => collector.with_own_clauses(|def_id| tcx.clauses_of(def_id), sig_id),
583 }
584 .clauses;
585
586 ty::GenericClauses { parent, clauses: tcx.arena.alloc_from_iter(clauses) }
587}
588
589fn create_folder_and_args<'tcx>(
590 tcx: TyCtxt<'tcx>,
591 def_id: LocalDefId,
592 sig_id: DefId,
593 parent_args: &'tcx [ty::GenericArg<'tcx>],
594 child_args: &'tcx [ty::GenericArg<'tcx>],
595) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
596 let (args, delegation_parent_args) =
597 create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
598
599 let remap_table = create_mapping(tcx, sig_id, def_id);
600
601 let delegation_parent_consts = delegation_parent_args
602 .iter()
603 .filter_map(|a| {
604 a.as_const().and_then(|c| {
605 if let ty::ConstKind::Param(param) = c.kind() { Some(param) } else { None }
606 })
607 })
608 .collect();
609
610 (ParamIndexRemapper { tcx, remap_table, delegation_parent_consts }, args)
611}
612
613fn check_constraints<'tcx>(
614 tcx: TyCtxt<'tcx>,
615 def_id: LocalDefId,
616 sig_id: DefId,
617) -> Result<(), ErrorGuaranteed> {
618 let mut ret = Ok(());
619
620 let mut emit = |descr| {
621 ret = Err(tcx.dcx().emit_err(crate::diagnostics::UnsupportedDelegation {
622 span: tcx.def_span(def_id),
623 descr,
624 callee_span: tcx.def_span(sig_id),
625 }));
626 };
627
628 if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic() {
629 emit("delegation to C-variadic functions is not allowed");
631 }
632
633 ret
634}
635
636pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
637 tcx: TyCtxt<'tcx>,
638 def_id: LocalDefId,
639) -> &'tcx [Ty<'tcx>] {
640 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id");
641 let caller_sig = tcx.fn_sig(sig_id);
642 if let Err(err) = check_constraints(tcx, def_id, sig_id) {
643 let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
644 let err_type = Ty::new_error(tcx, err);
645 return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
646 }
647
648 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
649 let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
650 let caller_sig = EarlyBinder::bind(tcx, caller_sig.skip_binder().fold_with(&mut folder));
651
652 let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder();
653 let output = std::iter::once(sig.output());
654 let mut sig = sig.inputs().iter().cloned().chain(output).collect::<Vec<_>>();
655
656 adjust_sig_in_inherent_impl_cases(tcx, sig_id, def_id, parent_args, &mut sig);
657
658 tcx.arena.alloc_from_iter(sig)
659}
660
661fn adjust_sig_in_inherent_impl_cases<'tcx>(
667 tcx: TyCtxt<'tcx>,
668 sig_id: DefId,
669 def_id: LocalDefId,
670 parent_args: &[ty::GenericArg<'tcx>],
671 sig: &mut [Ty<'tcx>],
672) {
673 if !tcx.is_method(sig_id) {
674 return;
675 }
676
677 let kinds @ (def_kind, _) = fn_kinds(tcx, def_id, sig_id);
678 if def_kind == FnKind::Free || !#[allow(non_exhaustive_omitted_patterns)] match kinds {
(_, FnKind::AssocInherentImpl) => true,
_ => false,
}matches!(kinds, (_, FnKind::AssocInherentImpl)) {
679 return;
680 }
681
682 let ty::Adt(def, _) = tcx.type_of(tcx.parent(sig_id)).skip_binder().kind() else {
683 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("delegation is supported only to struct or enums")));
}unreachable!("delegation is supported only to struct or enums")
684 };
685
686 for i in 0..sig.len() {
687 let to_replace = Ty::new_adt(tcx, *def, tcx.mk_args(parent_args));
688 let replacement = match def_kind {
689 FnKind::Free => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
690
691 FnKind::AssocTrait => Ty::new_param(tcx, 0, kw::SelfUpper),
692 _ => tcx.type_of(tcx.parent(def_id.to_def_id())).instantiate_identity().skip_norm_wip(),
693 };
694
695 struct Replacer<'tcx> {
696 tcx: TyCtxt<'tcx>,
697 to_replace: Ty<'tcx>,
698 replacement: Ty<'tcx>,
699 }
700
701 impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Replacer<'tcx> {
702 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
703 if t == self.to_replace { self.replacement } else { t.super_fold_with(self) }
704 }
705
706 fn cx(&self) -> TyCtxt<'tcx> {
707 self.tcx
708 }
709 }
710
711 sig[i] = sig[i].fold_with(&mut Replacer { tcx, to_replace, replacement })
712 }
713}
714
715pub(crate) fn delegation_user_specified_args<'tcx>(
720 tcx: TyCtxt<'tcx>,
721 def_id: LocalDefId,
722) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
723 let info = tcx.hir_delegation_info(def_id);
724
725 let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
726 let segment = tcx.hir_node(hir_id).expect_path_segment();
727 segment.res.opt_def_id().map(|def_id| (segment, def_id))
728 };
729
730 let ctx = ItemCtxt::new_for_delegation(tcx, def_id);
731 let lowerer = ctx.lowerer();
732
733 let parent_args = info
734 .parent_seg_id_for_sig
735 .and_then(get_segment)
736 .filter(|(_, def_id)| !#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(*def_id) {
DefKind::Mod => true,
_ => false,
}matches!(tcx.def_kind(*def_id), DefKind::Mod))
737 .map(|(segment, def_id)| {
738 {
match tcx.def_kind(def_id) {
DefKind::Trait | DefKind::Struct | DefKind::Enum => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"DefKind::Trait | DefKind::Struct | DefKind::Enum",
::core::option::Option::None);
}
}
};assert_matches!(tcx.def_kind(def_id), DefKind::Trait | DefKind::Struct | DefKind::Enum);
741
742 let self_ty = (tcx.def_kind(def_id) == DefKind::Trait)
743 .then(|| Ty::new_param(tcx, 0, kw::SelfUpper));
744
745 lowerer
746 .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty)
747 .0
748 .as_slice()
749 });
750
751 let child_args = info.child_seg_id_for_sig.and_then(get_segment).map(|(segment, def_id)| {
752 {
match tcx.def_kind(def_id) {
DefKind::Fn | DefKind::AssocFn => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"DefKind::Fn | DefKind::AssocFn",
::core::option::Option::None);
}
}
};assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
753 let parent = tcx.parent(def_id);
754
755 let parent_args =
756 if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(parent) {
DefKind::Impl { of_trait: false } | DefKind::Trait => true,
_ => false,
}matches!(tcx.def_kind(parent), DefKind::Impl { of_trait: false } | DefKind::Trait) {
757 ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
758 } else if let Some(parent_args) = parent_args {
759 parent_args
760 } else {
761 &[]
762 };
763
764 let args = lowerer
765 .lower_generic_args_of_path(segment.ident.span, def_id, parent_args, segment, None)
766 .0;
767
768 let synth_params_count = tcx.generics_of(def_id).own_synthetic_params_count();
769 &args[parent_args.len()..args.len() - synth_params_count]
770 });
771
772 (parent_args.unwrap_or_default(), child_args.unwrap_or_default())
773}