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, Upcast,
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 arg_kinds: Vec<ty::GenericArgKind<'tcx>>,
27}
28
29impl<'tcx> ParamIndexRemapper<'tcx> {
30 fn try_remap(
31 &self,
32 source_index: u32,
33 expected_kind: ty::GenericArgKind<'tcx>,
34 ) -> Result<u32, ()> {
35 self.remap_table
36 .get(&source_index)
37 .copied()
38 .filter(|&idx| {
39 self.arg_kinds.get(idx as usize).is_some_and(|kind| {
40 std::mem::discriminant(&expected_kind) == std::mem::discriminant(kind)
41 })
42 })
43 .ok_or(())
44 }
45}
46
47impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
48 type Error = ();
49
50 fn cx(&self) -> TyCtxt<'tcx> {
51 self.tcx
52 }
53
54 fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
55 if !ty.has_param() {
56 return Ok(ty);
57 }
58
59 if let ty::Param(param) = ty.kind() {
60 let index = self.try_remap(param.index, ty::GenericArgKind::Type(ty))?;
61 return Ok(Ty::new_param(self.tcx, index, param.name));
62 }
63
64 ty.try_super_fold_with(self)
65 }
66
67 fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
68 if let ty::ReEarlyParam(param) = r.kind() {
69 let index = self.try_remap(param.index, ty::GenericArgKind::Lifetime(r))?;
70 return Ok(ty::Region::new_early_param(
71 self.tcx,
72 ty::EarlyParamRegion { index, name: param.name },
73 ));
74 }
75 Ok(r)
76 }
77
78 fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
79 if let ty::ConstKind::Param(param) = ct.kind() {
80 let idx = self.try_remap(param.index, ty::GenericArgKind::Const(ct))?;
81 let param = ty::ParamConst::new(idx, param.name);
82 return Ok(ty::Const::new_param(self.tcx, param));
83 }
84 ct.try_super_fold_with(self)
85 }
86}
87
88#[derive(#[automatically_derived]impl ::core::fmt::Debug for SelfPositionKind {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::AfterLifetimes(__self_0) =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"AfterLifetimes", &__self_0),
Self::Zero => ::core::fmt::Formatter::write_str(f, "Zero"),
Self::None => ::core::fmt::Formatter::write_str(f, "None"),
}
}
}Debug)]
89enum SelfPositionKind {
90 AfterLifetimes(Option<DelegationSelfTyPropagationKind>),
91 Zero,
92 None,
93}
94
95fn create_self_param_position_kind(
96 tcx: TyCtxt<'_>,
97 def_id: LocalDefId,
98 sig_id: DefId,
99) -> SelfPositionKind {
100 match fn_kinds(tcx, def_id, sig_id) {
101 (FnKind::Free, FnKind::AssocTrait) => {
102 let kind = tcx.hir_delegation_info(def_id).self_ty_propagation_kind;
103 SelfPositionKind::AfterLifetimes(kind)
104 }
105
106 (_, FnKind::AssocTraitImpl) => ::core::panicking::unreachable_default_msg()unreachable!(),
107
108 (_, FnKind::AssocTrait) | (FnKind::AssocTrait, _) => SelfPositionKind::Zero,
109
110 (FnKind::AssocTraitImpl, _) => ::core::panicking::unreachable_default_msg()unreachable!(),
111
112 _ => SelfPositionKind::None,
113 }
114}
115
116#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for FnKind {
}
#[automatically_derived]impl ::core::clone::Clone for FnKind {
#[inline]
#[rustc_trivial_field_reads]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for FnKind { }Copy, #[automatically_derived]impl ::core::fmt::Debug for FnKind {
#[inline]
#[rustc_trivial_field_reads]
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: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq)]
117enum FnKind {
118 Free,
119 AssocInherentImpl,
120 AssocTrait,
121 AssocTraitImpl,
122}
123
124fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> FnKind {
125 let def_id = def_id.into();
126
127 match tcx.def_kind(def_id) {
128 DefKind::Fn => FnKind::Free,
129 DefKind::AssocFn => match tcx.def_kind(tcx.parent(def_id)) {
130 DefKind::Trait => FnKind::AssocTrait,
131 DefKind::Impl { of_trait } => match of_trait {
132 true => FnKind::AssocTraitImpl,
133 false => FnKind::AssocInherentImpl,
134 },
135 _ => {
::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"),
136 },
137 _ => {
::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"),
138 }
139}
140
141fn fn_kinds(tcx: TyCtxt<'_>, def_id: LocalDefId, sig_id: DefId) -> (FnKind, FnKind) {
142 let kinds = (fn_kind(tcx, def_id), fn_kind(tcx, sig_id));
143
144 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)));
146
147 kinds
148}
149
150#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for InheritanceKind {
}
#[automatically_derived]impl ::core::clone::Clone for InheritanceKind {
#[inline]
#[rustc_trivial_field_reads]
fn clone(&self) -> Self {
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]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::WithParent(__self_0) =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"WithParent", &__self_0),
Self::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: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::WithParent(__self_0), Self::WithParent(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq)]
153enum InheritanceKind {
154 WithParent(bool),
164 Own,
168}
169
170fn create_mapping<'tcx>(
180 tcx: TyCtxt<'tcx>,
181 sig_id: DefId,
182 def_id: LocalDefId,
183) -> FxHashMap<u32, u32> {
184 let mut mapping: FxHashMap<u32, u32> = Default::default();
185
186 let self_pos_kind = create_self_param_position_kind(tcx, def_id, sig_id);
187 let is_self_at_zero = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::Zero => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::Zero);
188
189 if is_self_at_zero {
191 mapping.insert(0, 0);
192 }
193
194 let mut args_index = 0;
195
196 args_index += is_self_at_zero as usize;
197 args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id);
198
199 let parent_kind = fn_kind(tcx, sig_id);
200 let process_parent = #[allow(non_exhaustive_omitted_patterns)] match parent_kind {
FnKind::AssocTrait | FnKind::AssocInherentImpl => true,
_ => false,
}matches!(parent_kind, FnKind::AssocTrait | FnKind::AssocInherentImpl);
201 let parent_generics = process_parent.then(|| tcx.generics_of(tcx.parent(sig_id)));
202
203 let parent_params = match parent_kind {
213 FnKind::AssocInherentImpl => {
214 let ty::Adt(_, args) = tcx.type_of(tcx.parent(sig_id)).skip_binder().kind() else {
215 {
::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")
216 };
217
218 let opt_param_info = |arg: GenericArg<'_>| match arg.kind() {
219 GenericArgKind::Lifetime(r) => (
220 match r.kind() {
221 RegionKind::ReEarlyParam(p) => Some(p.index),
222 _ => None,
223 },
224 false,
225 ),
226 GenericArgKind::Type(t) => (
227 match t.kind() {
228 ty::Param(p) => Some(p.index),
229 _ => None,
230 },
231 true,
232 ),
233 GenericArgKind::Const(c) => (
234 match c.kind() {
235 ConstKind::Param(p) => Some(p.index),
236 _ => None,
237 },
238 true,
239 ),
240 };
241
242 args.iter().map(opt_param_info).collect::<Vec<_>>()
243 }
244 FnKind::AssocTrait => parent_generics
245 .expect("trait must have generics")
246 .own_params
247 .iter()
248 .map(|p| (Some(p.index as u32), p.kind.is_ty_or_const()))
249 .collect::<Vec<_>>(),
250 _ => ::alloc::vec::Vec::new()vec![],
251 };
252
253 let has_self = match parent_kind {
254 FnKind::AssocTrait => parent_generics.expect("trait must have generics").has_self,
255 _ => false,
256 };
257
258 if process_parent {
259 for i in (has_self as usize)..parent_params.len() {
260 let (index, is_ty_or_const) = parent_params[i];
261 if !is_ty_or_const {
262 if let Some(index) = index {
263 mapping.insert(index, args_index as u32);
264 }
265
266 args_index += 1;
267 }
268 }
269 }
270
271 let child_generics = tcx.generics_of(sig_id);
272 for param in &child_generics.own_params {
273 if !param.kind.is_ty_or_const() {
274 mapping.insert(param.index, args_index as u32);
275 args_index += 1;
276 }
277 }
278
279 if #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes { .. } => true,
_ => false,
}matches!(self_pos_kind, SelfPositionKind::AfterLifetimes { .. }) {
283 mapping.insert(0, args_index as u32);
284 args_index += 1;
285 }
286
287 if process_parent {
288 for i in (has_self as usize)..parent_params.len() {
289 let (index, is_ty_or_const) = parent_params[i];
290 if is_ty_or_const {
291 if let Some(index) = index {
292 mapping.insert(index, args_index as u32);
293 }
294
295 args_index += 1;
296 }
297 }
298 }
299
300 for param in &child_generics.own_params {
301 if param.kind.is_ty_or_const() {
302 mapping.insert(param.index, args_index as u32);
303 args_index += 1;
304 }
305 }
306
307 mapping
308}
309
310fn get_delegation_parent_args_count_without_self<'tcx>(
311 tcx: TyCtxt<'tcx>,
312 def_id: LocalDefId,
313 sig_id: DefId,
314) -> usize {
315 let kinds @ (def_kind, _) = fn_kinds(tcx, def_id, sig_id);
316
317 match kinds {
318 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => 0,
319
320 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::unreachable_default_msg()unreachable!(),
321
322 (FnKind::Free, _) => 0,
323
324 (_, _) => {
325 let delegation_parent_args_count = tcx.generics_of(def_id).parent_count;
326 let has_self = def_kind == FnKind::AssocTrait;
327
328 delegation_parent_args_count - usize::from(has_self)
329 }
330 }
331}
332
333fn get_parent_and_inheritance_kind<'tcx>(
334 tcx: TyCtxt<'tcx>,
335 def_id: LocalDefId,
336 sig_id: DefId,
337) -> (Option<DefId>, InheritanceKind) {
338 let kinds @ (_, sig_kind) = fn_kinds(tcx, def_id, sig_id);
339
340 match kinds {
341 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
342 (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::Own)
343 }
344
345 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::unreachable_default_msg()unreachable!(),
346
347 (FnKind::Free, _) => {
348 let copy_self_clauses = sig_kind == FnKind::AssocTrait;
349 (None, InheritanceKind::WithParent(copy_self_clauses))
350 }
351
352 (_, _) => (Some(tcx.parent(def_id.to_def_id())), InheritanceKind::WithParent(false)),
353 }
354}
355
356fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<Ty<'tcx>> {
357 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("processing delegation");
358 let (caller_kind, callee_kind) = fn_kinds(tcx, def_id, sig_id);
359
360 match (caller_kind, callee_kind) {
361 (FnKind::AssocTraitImpl, FnKind::AssocTrait) | (FnKind::AssocInherentImpl, _) => {
362 Some(tcx.type_of(tcx.local_parent(def_id)).instantiate_identity().skip_norm_wip())
363 }
364
365 (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) => ::core::panicking::unreachable_default_msg()unreachable!(),
367
368 (_, _) => match create_self_param_position_kind(tcx, def_id, sig_id) {
369 SelfPositionKind::None => None,
370 SelfPositionKind::AfterLifetimes(propagation_kind) => Some(match propagation_kind {
371 Some(kind) => match kind {
372 DelegationSelfTyPropagationKind::SelfTy(self_ty_id) => {
373 let ctx = ItemCtxt::new(tcx, def_id);
374 ctx.lower_ty(tcx.hir_node(self_ty_id).expect_ty())
375 }
376 DelegationSelfTyPropagationKind::SelfParam => {
377 let index = tcx.generics_of(def_id).own_counts().lifetimes;
378 Ty::new_param(tcx, index as u32, kw::SelfUpper)
379 }
380 },
381 None => Ty::new_error_with_message(
382 tcx,
383 tcx.def_span(def_id),
384 "self propagation kind must be specified for `AfterLifetimes` variant",
385 ),
386 }),
387 SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)),
388 },
389 }
390}
391
392fn create_generic_args<'tcx>(
408 tcx: TyCtxt<'tcx>,
409 sig_id: DefId,
410 def_id: LocalDefId,
411 mut parent_args: ty::GenericArgs<'tcx>,
412 mut child_args: ty::GenericArgs<'tcx>,
413) -> (Vec<ty::GenericArg<'tcx>>, ty::GenericArgs<'tcx>) {
414 let delegation_generics = tcx.generics_of(def_id);
415 let delegation_args = ty::GenericArgs::identity_for_item(tcx, def_id);
416
417 let real_args_count = delegation_args.len() - delegation_generics.own_synthetic_params_count();
418 let synth_args = &delegation_args.as_slice()[real_args_count..];
419
420 let mut delegation_parent_args = tcx.mk_args(
421 &delegation_args.as_slice()
422 [delegation_generics.has_self as usize..delegation_generics.parent_count],
423 );
424
425 let delegation_args = &delegation_args.as_slice()[delegation_generics.parent_count..];
426
427 let kinds @ (_, parent_kind) = fn_kinds(tcx, def_id, sig_id);
428 if #[allow(non_exhaustive_omitted_patterns)] match kinds {
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => true,
_ => false,
}matches!(kinds, (FnKind::AssocTraitImpl, FnKind::AssocTrait)) {
429 let parent = tcx.local_parent(def_id);
433
434 parent_args =
435 tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args;
436
437 child_args = tcx.mk_args(
438 &delegation_args[delegation_args.len() - delegation_generics.own_params.len()..],
439 );
440
441 delegation_parent_args = ty::GenericArgs::empty();
442 }
443
444 let self_type = get_delegation_self_ty(tcx, def_id).map(ty::GenericArg::from);
445
446 if self_type.is_some() && !parent_args.is_empty() {
447 parent_args = match parent_kind {
448 FnKind::AssocInherentImpl => parent_args,
449 FnKind::AssocTrait => tcx.mk_args(&parent_args.as_slice()[1..]),
452 _ => {
::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"),
453 }
454 }
455
456 let (zero_self, after_lifetimes_self) =
457 match create_self_param_position_kind(tcx, def_id, sig_id) {
458 SelfPositionKind::AfterLifetimes(_) => {
459 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
460 (None, self_type)
461 }
462 SelfPositionKind::Zero => {
463 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
464 (self_type, None)
465 }
466 SelfPositionKind::None => (None, None),
467 };
468
469 let zero_self = zero_self.as_ref().into_iter();
470 let after_lifetimes_self = after_lifetimes_self.as_ref().into_iter();
471
472 let args = zero_self
473 .copied()
474 .chain(delegation_parent_args.iter())
475 .chain(parent_args.iter().filter(|a| a.as_region().is_some()))
476 .chain(child_args.iter().filter(|a| a.as_region().is_some()))
477 .chain(after_lifetimes_self.copied())
478 .chain(parent_args.iter().filter(|a| a.as_region().is_none()))
479 .chain(child_args.iter().filter(|a| a.as_region().is_none()))
480 .chain(synth_args.iter().copied())
481 .collect::<Vec<_>>();
482
483 (args, delegation_parent_args)
484}
485
486pub(crate) fn inherit_clauses_for_delegation_item<'tcx>(
487 tcx: TyCtxt<'tcx>,
488 def_id: LocalDefId,
489 sig_id: DefId,
490) -> ty::GenericClauses<'tcx> {
491 struct ClausesCollector<'tcx> {
492 tcx: TyCtxt<'tcx>,
493 clauses: Vec<(ty::Clause<'tcx>, Span)>,
494 args: Vec<ty::GenericArg<'tcx>>,
495 folder: ParamIndexRemapper<'tcx>,
496 filter_self_clauses: bool,
497 }
498
499 impl<'tcx> ClausesCollector<'tcx> {
500 fn with_own_clauses(
501 mut self,
502 f: impl Fn(DefId) -> ty::GenericClauses<'tcx>,
503 def_id: DefId,
504 ) -> Result<Self, ()> {
505 let clauses = f(def_id);
506 let args = self.args.as_slice();
507
508 for clause in clauses.clauses {
509 if self.filter_self_clauses
512 && let Some(trait_clause) = clause.0.as_trait_clause()
513 && trait_clause.self_ty().skip_binder().is_param(0)
515 {
516 continue;
517 }
518
519 let new_clause = clause.0.try_fold_with(&mut self.folder)?;
547 if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) =
548 new_clause.as_predicate().kind().skip_binder()
549 {
550 let unnorm_const = EarlyBinder::bind(self.tcx, ct).instantiate(self.tcx, args);
551 if let ty::ConstKind::Param(param) = unnorm_const.skip_norm_wip().kind()
552 && self.folder.delegation_parent_consts.contains(¶m)
553 {
554 continue;
555 }
556 }
557
558 self.clauses.push((
559 EarlyBinder::bind(self.tcx, new_clause)
560 .instantiate(self.tcx, args)
561 .skip_norm_wip(),
562 clause.1,
563 ));
564 }
565
566 Ok(self)
567 }
568
569 fn with_clauses(
570 mut self,
571 f: impl Fn(DefId) -> ty::GenericClauses<'tcx> + Copy,
572 def_id: DefId,
573 ) -> Result<Self, ()> {
574 let preds = f(def_id);
575 if let Some(parent_def_id) = preds.parent {
576 self = self.with_own_clauses(f, parent_def_id)?;
577 }
578
579 self.with_own_clauses(f, def_id)
580 }
581 }
582
583 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
584 let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
585 let self_pos_kind = create_self_param_position_kind(tcx, def_id, sig_id);
586 let filter_self_clauses = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
=> true,
_ => false,
}matches!(
587 self_pos_kind,
588 SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
589 );
590
591 let collector = ClausesCollector { tcx, clauses: ::alloc::vec::Vec::new()vec![], args, folder, filter_self_clauses };
592 let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
593
594 let collector = match inh_kind {
598 InheritanceKind::WithParent(false) => {
599 collector.with_clauses(|def_id| tcx.explicit_clauses_of(def_id), sig_id)
600 }
601 InheritanceKind::WithParent(true) => {
602 collector.with_clauses(|def_id| tcx.clauses_of(def_id), sig_id)
603 }
604 InheritanceKind::Own => collector.with_own_clauses(|def_id| tcx.clauses_of(def_id), sig_id),
605 };
606
607 let clauses = match collector {
608 Ok(collector) => collector.clauses,
609 Err(()) => {
610 tcx.dcx().emit_err(crate::diagnostics::DelegationInheritanceFailed {
611 span: tcx.def_span(def_id),
612 kind: "predicates",
613 callee_span: tcx.def_span(sig_id),
614 });
615
616 tcx.generics_of(def_id)
619 .own_params
620 .iter()
621 .filter_map(|param| {
622 if !#[allow(non_exhaustive_omitted_patterns)] match param.kind {
ty::GenericParamDefKind::Const { .. } => true,
_ => false,
}matches!(param.kind, ty::GenericParamDefKind::Const { .. }) {
623 return None;
624 }
625
626 let ct =
627 ty::Const::new_param(tcx, ty::ParamConst::new(param.index, param.name));
628 let ct_ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();
629
630 Some((
631 ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx),
632 tcx.def_span(param.def_id),
633 ))
634 })
635 .collect::<Vec<_>>()
636 }
637 };
638
639 ty::GenericClauses { parent, clauses: tcx.arena.alloc_from_iter(clauses) }
640}
641
642fn create_folder_and_args<'tcx>(
643 tcx: TyCtxt<'tcx>,
644 def_id: LocalDefId,
645 sig_id: DefId,
646 parent_args: ty::GenericArgs<'tcx>,
647 child_args: ty::GenericArgs<'tcx>,
648) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
649 let (args, delegation_parent_args) =
650 create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
651
652 let remap_table = create_mapping(tcx, sig_id, def_id);
653
654 let delegation_parent_consts = delegation_parent_args
655 .iter()
656 .filter_map(|a| {
657 a.as_const().and_then(|c| {
658 if let ty::ConstKind::Param(param) = c.kind() { Some(param) } else { None }
659 })
660 })
661 .collect();
662
663 let arg_kinds = args.iter().map(|arg| arg.kind()).collect();
664 (ParamIndexRemapper { tcx, remap_table, delegation_parent_consts, arg_kinds }, args)
665}
666
667fn check_constraints<'tcx>(
668 tcx: TyCtxt<'tcx>,
669 def_id: LocalDefId,
670 sig_id: DefId,
671) -> Result<(), ErrorGuaranteed> {
672 let mut ret = Ok(());
673
674 let mut emit = |descr| {
675 ret = Err(tcx.dcx().emit_err(crate::diagnostics::UnsupportedDelegation {
676 span: tcx.def_span(def_id),
677 descr,
678 callee_span: tcx.def_span(sig_id),
679 }));
680 };
681
682 if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic() {
683 emit("delegation to C-variadic functions is not allowed");
685 }
686
687 ret
688}
689
690fn error_sig_for_delegation<'tcx>(
691 tcx: TyCtxt<'tcx>,
692 sig_id: DefId,
693 err: ErrorGuaranteed,
694) -> &'tcx [Ty<'tcx>] {
695 let sig_len = tcx.fn_sig(sig_id).instantiate_identity().skip_binder().inputs().len() + 1;
696 let err_type = Ty::new_error(tcx, err);
697 tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type))
698}
699
700pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
701 tcx: TyCtxt<'tcx>,
702 def_id: LocalDefId,
703) -> &'tcx [Ty<'tcx>] {
704 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id");
705 let caller_sig = tcx.fn_sig(sig_id);
706 if let Err(err) = check_constraints(tcx, def_id, sig_id) {
707 return error_sig_for_delegation(tcx, sig_id, err);
708 }
709
710 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
711 let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
712 let folded_sig = match caller_sig.skip_binder().try_fold_with(&mut folder) {
713 Ok(sig) => sig,
714 Err(()) => {
715 let err = tcx.dcx().emit_err(crate::diagnostics::DelegationInheritanceFailed {
716 span: tcx.def_span(def_id),
717 kind: "signature",
718 callee_span: tcx.def_span(sig_id),
719 });
720 return error_sig_for_delegation(tcx, sig_id, err);
721 }
722 };
723 let caller_sig = EarlyBinder::bind(tcx, folded_sig);
724
725 let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder();
726 let output = std::iter::once(sig.output());
727 let mut sig = sig.inputs().iter().cloned().chain(output).collect::<Vec<_>>();
728
729 adjust_sig_in_inherent_impl_cases(tcx, sig_id, def_id, parent_args, &mut sig);
730
731 tcx.arena.alloc_from_iter(sig)
732}
733
734fn adjust_sig_in_inherent_impl_cases<'tcx>(
740 tcx: TyCtxt<'tcx>,
741 sig_id: DefId,
742 def_id: LocalDefId,
743 parent_args: ty::GenericArgs<'tcx>,
744 sig: &mut [Ty<'tcx>],
745) {
746 if !tcx.is_method(sig_id) {
747 return;
748 }
749
750 let kinds @ (def_kind, _) = fn_kinds(tcx, def_id, sig_id);
751 if def_kind == FnKind::Free || !#[allow(non_exhaustive_omitted_patterns)] match kinds {
(_, FnKind::AssocInherentImpl) => true,
_ => false,
}matches!(kinds, (_, FnKind::AssocInherentImpl)) {
752 return;
753 }
754
755 let ty::Adt(def, _) = tcx.type_of(tcx.parent(sig_id)).skip_binder().kind() else {
756 {
::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")
757 };
758
759 for i in 0..sig.len() {
760 let to_replace = Ty::new_adt(tcx, *def, parent_args);
761 let replacement = match def_kind {
762 FnKind::Free => ::core::panicking::unreachable_default_msg()unreachable!(),
763
764 FnKind::AssocTrait => Ty::new_param(tcx, 0, kw::SelfUpper),
765 _ => tcx.type_of(tcx.parent(def_id.to_def_id())).instantiate_identity().skip_norm_wip(),
766 };
767
768 struct Replacer<'tcx> {
769 tcx: TyCtxt<'tcx>,
770 to_replace: Ty<'tcx>,
771 replacement: Ty<'tcx>,
772 }
773
774 impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Replacer<'tcx> {
775 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
776 if t == self.to_replace { self.replacement } else { t.super_fold_with(self) }
777 }
778
779 fn cx(&self) -> TyCtxt<'tcx> {
780 self.tcx
781 }
782 }
783
784 sig[i] = sig[i].fold_with(&mut Replacer { tcx, to_replace, replacement })
785 }
786}
787
788pub(crate) fn delegation_user_specified_args<'tcx>(
793 tcx: TyCtxt<'tcx>,
794 def_id: LocalDefId,
795) -> (ty::GenericArgs<'tcx>, ty::GenericArgs<'tcx>) {
796 let info = tcx.hir_delegation_info(def_id);
797
798 let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
799 let segment = tcx.hir_node(hir_id).expect_path_segment();
800 segment.res.opt_def_id().map(|def_id| (segment, def_id))
801 };
802
803 let ctx = ItemCtxt::new_for_delegation(tcx, def_id);
804 let lowerer = ctx.lowerer();
805
806 let parent_args = info
807 .parent_seg_id_for_sig
808 .and_then(get_segment)
809 .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))
810 .map(|(segment, def_id)| {
811 {
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);
814
815 let self_ty = (tcx.def_kind(def_id) == DefKind::Trait)
816 .then(|| Ty::new_param(tcx, 0, kw::SelfUpper));
817
818 tcx.mk_args(
819 lowerer
820 .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty)
821 .0
822 .as_slice(),
823 )
824 });
825
826 let child_args = info.child_seg_id_for_sig.and_then(get_segment).map(|(segment, def_id)| {
827 {
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);
828 let parent = tcx.parent(def_id);
829
830 let parent_args =
831 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) {
832 ty::GenericArgs::identity_for_item(tcx, parent)
833 } else if let Some(parent_args) = parent_args {
834 parent_args
835 } else {
836 ty::GenericArgs::empty()
837 };
838
839 let args = lowerer
840 .lower_generic_args_of_path(
841 segment.ident.span,
842 def_id,
843 parent_args.as_slice(),
844 segment,
845 None,
846 )
847 .0;
848
849 let synth_params_count = tcx.generics_of(def_id).own_synthetic_params_count();
850 tcx.mk_args(&args.as_slice()[parent_args.len()..args.len() - synth_params_count])
851 });
852
853 (parent_args.unwrap_or_default(), child_args.unwrap_or_default())
854}