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]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::AfterLifetimes(__self_0) =>
::core::fmt::Formatter::debug_tuple_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::panic("internal error: entered unreachable code")unreachable!(),
107
108 (_, FnKind::AssocTrait) | (FnKind::AssocTrait, _) => SelfPositionKind::Zero,
109
110 (FnKind::AssocTraitImpl, _) => ::core::panicking::panic("internal error: entered unreachable code")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]
fn clone(&self) -> Self { *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: &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]
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]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::WithParent(__self_0) =>
::core::fmt::Formatter::debug_tuple_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::panic("internal error: entered unreachable code")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::panic("internal error: entered unreachable code")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::panic("internal error: entered unreachable code")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::GenericArg<'tcx>],
412 mut child_args: &[ty::GenericArg<'tcx>],
413) -> (Vec<ty::GenericArg<'tcx>>, &'tcx [ty::GenericArg<'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[real_args_count..];
419
420 let mut delegation_parent_args =
421 &delegation_args[delegation_generics.has_self as usize..delegation_generics.parent_count];
422
423 let delegation_args = &delegation_args[delegation_generics.parent_count..];
424
425 let kinds @ (_, parent_kind) = fn_kinds(tcx, def_id, sig_id);
426 if #[allow(non_exhaustive_omitted_patterns)] match kinds {
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => true,
_ => false,
}matches!(kinds, (FnKind::AssocTraitImpl, FnKind::AssocTrait)) {
427 let parent = tcx.local_parent(def_id);
431
432 parent_args =
433 tcx.impl_trait_header(parent).trait_ref.instantiate_identity().skip_norm_wip().args;
434
435 child_args =
436 &delegation_args[delegation_args.len() - delegation_generics.own_params.len()..];
437
438 delegation_parent_args = &[];
439 }
440
441 let self_type = get_delegation_self_ty(tcx, def_id).map(ty::GenericArg::from);
442
443 if self_type.is_some() && !parent_args.is_empty() {
444 parent_args = match parent_kind {
445 FnKind::AssocInherentImpl => parent_args,
446 FnKind::AssocTrait => &parent_args[1..],
449 _ => {
::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"),
450 }
451 }
452
453 let (zero_self, after_lifetimes_self) =
454 match create_self_param_position_kind(tcx, def_id, sig_id) {
455 SelfPositionKind::AfterLifetimes(_) => {
456 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
457 (None, self_type)
458 }
459 SelfPositionKind::Zero => {
460 if !self_type.is_some() {
::core::panicking::panic("assertion failed: self_type.is_some()")
};assert!(self_type.is_some());
461 (self_type, None)
462 }
463 SelfPositionKind::None => (None, None),
464 };
465
466 let zero_self = zero_self.as_ref().into_iter();
467 let after_lifetimes_self = after_lifetimes_self.as_ref().into_iter();
468
469 let args = zero_self
470 .chain(delegation_parent_args)
471 .chain(parent_args.iter().filter(|a| a.as_region().is_some()))
472 .chain(child_args.iter().filter(|a| a.as_region().is_some()))
473 .chain(after_lifetimes_self)
474 .chain(parent_args.iter().filter(|a| a.as_region().is_none()))
475 .chain(child_args.iter().filter(|a| a.as_region().is_none()))
476 .chain(synth_args)
477 .copied()
478 .collect::<Vec<_>>();
479
480 (args, delegation_parent_args)
481}
482
483pub(crate) fn inherit_clauses_for_delegation_item<'tcx>(
484 tcx: TyCtxt<'tcx>,
485 def_id: LocalDefId,
486 sig_id: DefId,
487) -> ty::GenericClauses<'tcx> {
488 struct ClausesCollector<'tcx> {
489 tcx: TyCtxt<'tcx>,
490 clauses: Vec<(ty::Clause<'tcx>, Span)>,
491 args: Vec<ty::GenericArg<'tcx>>,
492 folder: ParamIndexRemapper<'tcx>,
493 filter_self_clauses: bool,
494 }
495
496 impl<'tcx> ClausesCollector<'tcx> {
497 fn with_own_clauses(
498 mut self,
499 f: impl Fn(DefId) -> ty::GenericClauses<'tcx>,
500 def_id: DefId,
501 ) -> Result<Self, ()> {
502 let clauses = f(def_id);
503 let args = self.args.as_slice();
504
505 for clause in clauses.clauses {
506 if self.filter_self_clauses
509 && let Some(trait_clause) = clause.0.as_trait_clause()
510 && trait_clause.self_ty().skip_binder().is_param(0)
512 {
513 continue;
514 }
515
516 let new_clause = clause.0.try_fold_with(&mut self.folder)?;
544 if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) =
545 new_clause.as_predicate().kind().skip_binder()
546 {
547 let unnorm_const = EarlyBinder::bind(self.tcx, ct).instantiate(self.tcx, args);
548 if let ty::ConstKind::Param(param) = unnorm_const.skip_norm_wip().kind()
549 && self.folder.delegation_parent_consts.contains(¶m)
550 {
551 continue;
552 }
553 }
554
555 self.clauses.push((
556 EarlyBinder::bind(self.tcx, new_clause)
557 .instantiate(self.tcx, args)
558 .skip_norm_wip(),
559 clause.1,
560 ));
561 }
562
563 Ok(self)
564 }
565
566 fn with_clauses(
567 mut self,
568 f: impl Fn(DefId) -> ty::GenericClauses<'tcx> + Copy,
569 def_id: DefId,
570 ) -> Result<Self, ()> {
571 let preds = f(def_id);
572 if let Some(parent_def_id) = preds.parent {
573 self = self.with_own_clauses(f, parent_def_id)?;
574 }
575
576 self.with_own_clauses(f, def_id)
577 }
578 }
579
580 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
581 let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
582 let self_pos_kind = create_self_param_position_kind(tcx, def_id, sig_id);
583 let filter_self_clauses = #[allow(non_exhaustive_omitted_patterns)] match self_pos_kind {
SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
=> true,
_ => false,
}matches!(
584 self_pos_kind,
585 SelfPositionKind::AfterLifetimes(Some(DelegationSelfTyPropagationKind::SelfTy(..)))
586 );
587
588 let collector = ClausesCollector { tcx, clauses: ::alloc::vec::Vec::new()vec![], args, folder, filter_self_clauses };
589 let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
590
591 let collector = match inh_kind {
595 InheritanceKind::WithParent(false) => {
596 collector.with_clauses(|def_id| tcx.explicit_clauses_of(def_id), sig_id)
597 }
598 InheritanceKind::WithParent(true) => {
599 collector.with_clauses(|def_id| tcx.clauses_of(def_id), sig_id)
600 }
601 InheritanceKind::Own => collector.with_own_clauses(|def_id| tcx.clauses_of(def_id), sig_id),
602 };
603
604 let clauses = match collector {
605 Ok(collector) => collector.clauses,
606 Err(()) => {
607 tcx.dcx().emit_err(crate::diagnostics::DelegationInheritanceFailed {
608 span: tcx.def_span(def_id),
609 kind: "predicates",
610 callee_span: tcx.def_span(sig_id),
611 });
612
613 tcx.generics_of(def_id)
616 .own_params
617 .iter()
618 .filter_map(|param| {
619 if !#[allow(non_exhaustive_omitted_patterns)] match param.kind {
ty::GenericParamDefKind::Const { .. } => true,
_ => false,
}matches!(param.kind, ty::GenericParamDefKind::Const { .. }) {
620 return None;
621 }
622
623 let ct =
624 ty::Const::new_param(tcx, ty::ParamConst::new(param.index, param.name));
625 let ct_ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip();
626
627 Some((
628 ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx),
629 tcx.def_span(param.def_id),
630 ))
631 })
632 .collect::<Vec<_>>()
633 }
634 };
635
636 ty::GenericClauses { parent, clauses: tcx.arena.alloc_from_iter(clauses) }
637}
638
639fn create_folder_and_args<'tcx>(
640 tcx: TyCtxt<'tcx>,
641 def_id: LocalDefId,
642 sig_id: DefId,
643 parent_args: &'tcx [ty::GenericArg<'tcx>],
644 child_args: &'tcx [ty::GenericArg<'tcx>],
645) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
646 let (args, delegation_parent_args) =
647 create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
648
649 let remap_table = create_mapping(tcx, sig_id, def_id);
650
651 let delegation_parent_consts = delegation_parent_args
652 .iter()
653 .filter_map(|a| {
654 a.as_const().and_then(|c| {
655 if let ty::ConstKind::Param(param) = c.kind() { Some(param) } else { None }
656 })
657 })
658 .collect();
659
660 let arg_kinds = args.iter().map(|arg| arg.kind()).collect();
661 (ParamIndexRemapper { tcx, remap_table, delegation_parent_consts, arg_kinds }, args)
662}
663
664fn check_constraints<'tcx>(
665 tcx: TyCtxt<'tcx>,
666 def_id: LocalDefId,
667 sig_id: DefId,
668) -> Result<(), ErrorGuaranteed> {
669 let mut ret = Ok(());
670
671 let mut emit = |descr| {
672 ret = Err(tcx.dcx().emit_err(crate::diagnostics::UnsupportedDelegation {
673 span: tcx.def_span(def_id),
674 descr,
675 callee_span: tcx.def_span(sig_id),
676 }));
677 };
678
679 if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic() {
680 emit("delegation to C-variadic functions is not allowed");
682 }
683
684 ret
685}
686
687fn error_sig_for_delegation<'tcx>(
688 tcx: TyCtxt<'tcx>,
689 sig_id: DefId,
690 err: ErrorGuaranteed,
691) -> &'tcx [Ty<'tcx>] {
692 let sig_len = tcx.fn_sig(sig_id).instantiate_identity().skip_binder().inputs().len() + 1;
693 let err_type = Ty::new_error(tcx, err);
694 tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type))
695}
696
697pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
698 tcx: TyCtxt<'tcx>,
699 def_id: LocalDefId,
700) -> &'tcx [Ty<'tcx>] {
701 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id");
702 let caller_sig = tcx.fn_sig(sig_id);
703 if let Err(err) = check_constraints(tcx, def_id, sig_id) {
704 return error_sig_for_delegation(tcx, sig_id, err);
705 }
706
707 let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id);
708 let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
709 let folded_sig = match caller_sig.skip_binder().try_fold_with(&mut folder) {
710 Ok(sig) => sig,
711 Err(()) => {
712 let err = tcx.dcx().emit_err(crate::diagnostics::DelegationInheritanceFailed {
713 span: tcx.def_span(def_id),
714 kind: "signature",
715 callee_span: tcx.def_span(sig_id),
716 });
717 return error_sig_for_delegation(tcx, sig_id, err);
718 }
719 };
720 let caller_sig = EarlyBinder::bind(tcx, folded_sig);
721
722 let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder();
723 let output = std::iter::once(sig.output());
724 let mut sig = sig.inputs().iter().cloned().chain(output).collect::<Vec<_>>();
725
726 adjust_sig_in_inherent_impl_cases(tcx, sig_id, def_id, parent_args, &mut sig);
727
728 tcx.arena.alloc_from_iter(sig)
729}
730
731fn adjust_sig_in_inherent_impl_cases<'tcx>(
737 tcx: TyCtxt<'tcx>,
738 sig_id: DefId,
739 def_id: LocalDefId,
740 parent_args: &[ty::GenericArg<'tcx>],
741 sig: &mut [Ty<'tcx>],
742) {
743 if !tcx.is_method(sig_id) {
744 return;
745 }
746
747 let kinds @ (def_kind, _) = fn_kinds(tcx, def_id, sig_id);
748 if def_kind == FnKind::Free || !#[allow(non_exhaustive_omitted_patterns)] match kinds {
(_, FnKind::AssocInherentImpl) => true,
_ => false,
}matches!(kinds, (_, FnKind::AssocInherentImpl)) {
749 return;
750 }
751
752 let ty::Adt(def, _) = tcx.type_of(tcx.parent(sig_id)).skip_binder().kind() else {
753 {
::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")
754 };
755
756 for i in 0..sig.len() {
757 let to_replace = Ty::new_adt(tcx, *def, tcx.mk_args(parent_args));
758 let replacement = match def_kind {
759 FnKind::Free => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
760
761 FnKind::AssocTrait => Ty::new_param(tcx, 0, kw::SelfUpper),
762 _ => tcx.type_of(tcx.parent(def_id.to_def_id())).instantiate_identity().skip_norm_wip(),
763 };
764
765 struct Replacer<'tcx> {
766 tcx: TyCtxt<'tcx>,
767 to_replace: Ty<'tcx>,
768 replacement: Ty<'tcx>,
769 }
770
771 impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Replacer<'tcx> {
772 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
773 if t == self.to_replace { self.replacement } else { t.super_fold_with(self) }
774 }
775
776 fn cx(&self) -> TyCtxt<'tcx> {
777 self.tcx
778 }
779 }
780
781 sig[i] = sig[i].fold_with(&mut Replacer { tcx, to_replace, replacement })
782 }
783}
784
785pub(crate) fn delegation_user_specified_args<'tcx>(
790 tcx: TyCtxt<'tcx>,
791 def_id: LocalDefId,
792) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
793 let info = tcx.hir_delegation_info(def_id);
794
795 let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
796 let segment = tcx.hir_node(hir_id).expect_path_segment();
797 segment.res.opt_def_id().map(|def_id| (segment, def_id))
798 };
799
800 let ctx = ItemCtxt::new_for_delegation(tcx, def_id);
801 let lowerer = ctx.lowerer();
802
803 let parent_args = info
804 .parent_seg_id_for_sig
805 .and_then(get_segment)
806 .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))
807 .map(|(segment, def_id)| {
808 {
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);
811
812 let self_ty = (tcx.def_kind(def_id) == DefKind::Trait)
813 .then(|| Ty::new_param(tcx, 0, kw::SelfUpper));
814
815 lowerer
816 .lower_generic_args_of_path(segment.ident.span, def_id, &[], segment, self_ty)
817 .0
818 .as_slice()
819 });
820
821 let child_args = info.child_seg_id_for_sig.and_then(get_segment).map(|(segment, def_id)| {
822 {
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);
823 let parent = tcx.parent(def_id);
824
825 let parent_args =
826 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) {
827 ty::GenericArgs::identity_for_item(tcx, parent).as_slice()
828 } else if let Some(parent_args) = parent_args {
829 parent_args
830 } else {
831 &[]
832 };
833
834 let args = lowerer
835 .lower_generic_args_of_path(segment.ident.span, def_id, parent_args, segment, None)
836 .0;
837
838 let synth_params_count = tcx.generics_of(def_id).own_synthetic_params_count();
839 &args[parent_args.len()..args.len() - synth_params_count]
840 });
841
842 (parent_args.unwrap_or_default(), child_args.unwrap_or_default())
843}