1use rustc_data_structures::debug_assert_matches;
6use rustc_data_structures::fx::FxHashMap;
7use rustc_hir::def::DefKind;
8use rustc_hir::def_id::{DefId, LocalDefId};
9use rustc_middle::ty::{
10 self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
11};
12use rustc_span::{ErrorGuaranteed, Span};
13
14type RemapTable = FxHashMap<u32, u32>;
15
16struct ParamIndexRemapper<'tcx> {
17 tcx: TyCtxt<'tcx>,
18 remap_table: RemapTable,
19}
20
21impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
22 fn cx(&self) -> TyCtxt<'tcx> {
23 self.tcx
24 }
25
26 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
27 if !ty.has_param() {
28 return ty;
29 }
30
31 if let ty::Param(param) = ty.kind()
32 && let Some(index) = self.remap_table.get(¶m.index)
33 {
34 return Ty::new_param(self.tcx, *index, param.name);
35 }
36 ty.super_fold_with(self)
37 }
38
39 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
40 if let ty::ReEarlyParam(param) = r.kind()
41 && let Some(index) = self.remap_table.get(¶m.index).copied()
42 {
43 return ty::Region::new_early_param(
44 self.tcx,
45 ty::EarlyParamRegion { index, name: param.name },
46 );
47 }
48 r
49 }
50
51 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
52 if let ty::ConstKind::Param(param) = ct.kind()
53 && let Some(idx) = self.remap_table.get(¶m.index)
54 {
55 let param = ty::ParamConst::new(*idx, param.name);
56 return ty::Const::new_param(self.tcx, param);
57 }
58 ct.super_fold_with(self)
59 }
60}
61
62#[derive(#[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::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)]
63enum FnKind {
64 Free,
65 AssocInherentImpl,
66 AssocTrait,
67 AssocTraitImpl,
68}
69
70fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
71 if true {
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);
}
};
};debug_assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
72
73 let parent = tcx.parent(def_id);
74 match tcx.def_kind(parent) {
75 DefKind::Trait => FnKind::AssocTrait,
76 DefKind::Impl { of_trait: true } => FnKind::AssocTraitImpl,
77 DefKind::Impl { of_trait: false } => FnKind::AssocInherentImpl,
78 _ => FnKind::Free,
79 }
80}
81
82#[derive(#[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::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)]
85enum InheritanceKind {
86 WithParent(bool),
96 Own,
100}
101
102fn build_generics<'tcx>(
103 tcx: TyCtxt<'tcx>,
104 sig_id: DefId,
105 parent: Option<DefId>,
106 inh_kind: InheritanceKind,
107) -> ty::Generics {
108 let mut own_params = ::alloc::vec::Vec::new()vec![];
109
110 let sig_generics = tcx.generics_of(sig_id);
111 if let InheritanceKind::WithParent(has_self) = inh_kind
112 && let Some(parent_def_id) = sig_generics.parent
113 {
114 let sig_parent_generics = tcx.generics_of(parent_def_id);
115 own_params.append(&mut sig_parent_generics.own_params.clone());
116 if !has_self {
117 own_params.remove(0);
118 }
119 }
120 own_params.append(&mut sig_generics.own_params.clone());
121
122 own_params.sort_by_key(|key| key.kind.is_ty_or_const());
136
137 let (parent_count, has_self) = if let Some(def_id) = parent {
138 let parent_generics = tcx.generics_of(def_id);
139 let parent_kind = tcx.def_kind(def_id);
140 (parent_generics.count(), parent_kind == DefKind::Trait)
141 } else {
142 (0, false)
143 };
144
145 for (idx, param) in own_params.iter_mut().enumerate() {
146 param.index = (idx + parent_count) as u32;
147 if let ty::GenericParamDefKind::Type { has_default, .. }
155 | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
156 {
157 *has_default = false;
158 }
159 }
160
161 let param_def_id_to_index =
162 own_params.iter().map(|param| (param.def_id, param.index)).collect();
163
164 ty::Generics {
165 parent,
166 parent_count,
167 own_params,
168 param_def_id_to_index,
169 has_self,
170 has_late_bound_regions: sig_generics.has_late_bound_regions,
171 }
172}
173
174fn build_predicates<'tcx>(
175 tcx: TyCtxt<'tcx>,
176 sig_id: DefId,
177 parent: Option<DefId>,
178 inh_kind: InheritanceKind,
179 args: ty::GenericArgsRef<'tcx>,
180) -> ty::GenericPredicates<'tcx> {
181 struct PredicatesCollector<'tcx> {
182 tcx: TyCtxt<'tcx>,
183 preds: Vec<(ty::Clause<'tcx>, Span)>,
184 args: ty::GenericArgsRef<'tcx>,
185 }
186
187 impl<'tcx> PredicatesCollector<'tcx> {
188 fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
189 PredicatesCollector { tcx, preds: ::alloc::vec::Vec::new()vec![], args }
190 }
191
192 fn with_own_preds(
193 mut self,
194 f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
195 def_id: DefId,
196 ) -> Self {
197 let preds = f(def_id).instantiate_own(self.tcx, self.args);
198 self.preds.extend(preds);
199 self
200 }
201
202 fn with_preds(
203 mut self,
204 f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
205 def_id: DefId,
206 ) -> Self {
207 let preds = f(def_id);
208 if let Some(parent_def_id) = preds.parent {
209 self = self.with_own_preds(f, parent_def_id);
210 }
211 self.with_own_preds(f, def_id)
212 }
213 }
214 let collector = PredicatesCollector::new(tcx, args);
215
216 let preds = match inh_kind {
220 InheritanceKind::WithParent(false) => {
221 collector.with_preds(|def_id| tcx.explicit_predicates_of(def_id), sig_id)
222 }
223 InheritanceKind::WithParent(true) => {
224 collector.with_preds(|def_id| tcx.predicates_of(def_id), sig_id)
225 }
226 InheritanceKind::Own => {
227 collector.with_own_preds(|def_id| tcx.predicates_of(def_id), sig_id)
228 }
229 }
230 .preds;
231
232 ty::GenericPredicates { parent, predicates: tcx.arena.alloc_from_iter(preds) }
233}
234
235fn build_generic_args<'tcx>(
236 tcx: TyCtxt<'tcx>,
237 sig_id: DefId,
238 def_id: LocalDefId,
239 args: ty::GenericArgsRef<'tcx>,
240) -> ty::GenericArgsRef<'tcx> {
241 let caller_generics = tcx.generics_of(def_id);
242 let callee_generics = tcx.generics_of(sig_id);
243
244 let mut remap_table = FxHashMap::default();
245 for caller_param in &caller_generics.own_params {
246 let callee_index = callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap();
247 remap_table.insert(callee_index, caller_param.index);
248 }
249
250 let mut folder = ParamIndexRemapper { tcx, remap_table };
251 args.fold_with(&mut folder)
252}
253
254fn create_generic_args<'tcx>(
255 tcx: TyCtxt<'tcx>,
256 def_id: LocalDefId,
257 sig_id: DefId,
258) -> ty::GenericArgsRef<'tcx> {
259 let caller_kind = fn_kind(tcx, def_id.into());
260 let callee_kind = fn_kind(tcx, sig_id);
261 match (caller_kind, callee_kind) {
262 (FnKind::Free, FnKind::Free)
263 | (FnKind::Free, FnKind::AssocTrait)
264 | (FnKind::AssocInherentImpl, FnKind::Free)
265 | (FnKind::AssocTrait, FnKind::Free)
266 | (FnKind::AssocTrait, FnKind::AssocTrait) => {
267 let args = ty::GenericArgs::identity_for_item(tcx, sig_id);
268 build_generic_args(tcx, sig_id, def_id, args)
269 }
270
271 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
272 let callee_generics = tcx.generics_of(sig_id);
273 let parent = tcx.parent(def_id.into());
274 let parent_args = tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args;
275
276 let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
277 let method_args = tcx.mk_args(&trait_args[callee_generics.parent_count..]);
278 let method_args = build_generic_args(tcx, sig_id, def_id, method_args);
279
280 tcx.mk_args_from_iter(parent_args.iter().chain(method_args))
281 }
282
283 (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
284 let parent = tcx.parent(def_id.into());
285 let self_ty = tcx.type_of(parent).instantiate_identity();
286 let generic_self_ty = ty::GenericArg::from(self_ty);
287
288 let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
289 let trait_args = build_generic_args(tcx, sig_id, def_id, trait_args);
290
291 let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1));
292 tcx.mk_args_from_iter(args)
293 }
294
295 (FnKind::AssocTraitImpl, _)
298 | (_, FnKind::AssocTraitImpl)
299 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
300 }
301}
302
303pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
315 tcx: TyCtxt<'tcx>,
316 def_id: LocalDefId,
317 sig_id: DefId,
318) -> ty::Generics {
319 let caller_kind = fn_kind(tcx, def_id.into());
320 let callee_kind = fn_kind(tcx, sig_id);
321 match (caller_kind, callee_kind) {
322 (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
323 build_generics(tcx, sig_id, None, InheritanceKind::WithParent(true))
324 }
325
326 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
327 build_generics(tcx, sig_id, Some(tcx.parent(def_id.into())), InheritanceKind::Own)
328 }
329
330 (FnKind::AssocInherentImpl, FnKind::AssocTrait)
331 | (FnKind::AssocTrait, FnKind::AssocTrait)
332 | (FnKind::AssocInherentImpl, FnKind::Free)
333 | (FnKind::AssocTrait, FnKind::Free) => build_generics(
334 tcx,
335 sig_id,
336 Some(tcx.parent(def_id.into())),
337 InheritanceKind::WithParent(false),
338 ),
339
340 (FnKind::AssocTraitImpl, _)
343 | (_, FnKind::AssocTraitImpl)
344 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
345 }
346}
347
348pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
349 tcx: TyCtxt<'tcx>,
350 def_id: LocalDefId,
351 sig_id: DefId,
352) -> ty::GenericPredicates<'tcx> {
353 let args = create_generic_args(tcx, def_id, sig_id);
354 let caller_kind = fn_kind(tcx, def_id.into());
355 let callee_kind = fn_kind(tcx, sig_id);
356 match (caller_kind, callee_kind) {
357 (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
358 build_predicates(tcx, sig_id, None, InheritanceKind::WithParent(true), args)
359 }
360
361 (FnKind::AssocTraitImpl, FnKind::AssocTrait) => build_predicates(
362 tcx,
363 sig_id,
364 Some(tcx.parent(def_id.into())),
365 InheritanceKind::Own,
366 args,
367 ),
368
369 (FnKind::AssocInherentImpl, FnKind::AssocTrait)
370 | (FnKind::AssocTrait, FnKind::AssocTrait)
371 | (FnKind::AssocInherentImpl, FnKind::Free)
372 | (FnKind::AssocTrait, FnKind::Free) => build_predicates(
373 tcx,
374 sig_id,
375 Some(tcx.parent(def_id.into())),
376 InheritanceKind::WithParent(false),
377 args,
378 ),
379
380 (FnKind::AssocTraitImpl, _)
383 | (_, FnKind::AssocTraitImpl)
384 | (_, FnKind::AssocInherentImpl) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
385 }
386}
387
388fn check_constraints<'tcx>(
389 tcx: TyCtxt<'tcx>,
390 def_id: LocalDefId,
391 sig_id: DefId,
392) -> Result<(), ErrorGuaranteed> {
393 let mut ret = Ok(());
394
395 let mut emit = |descr| {
396 ret = Err(tcx.dcx().emit_err(crate::errors::UnsupportedDelegation {
397 span: tcx.def_span(def_id),
398 descr,
399 callee_span: tcx.def_span(sig_id),
400 }));
401 };
402
403 if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic {
404 emit("delegation to C-variadic functions is not allowed");
406 }
407
408 ret
409}
410
411pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
412 tcx: TyCtxt<'tcx>,
413 def_id: LocalDefId,
414) -> &'tcx [Ty<'tcx>] {
415 let sig_id = tcx.hir_opt_delegation_sig_id(def_id).unwrap();
416 let caller_sig = tcx.fn_sig(sig_id);
417 if let Err(err) = check_constraints(tcx, def_id, sig_id) {
418 let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
419 let err_type = Ty::new_error(tcx, err);
420 return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
421 }
422 let args = create_generic_args(tcx, def_id, sig_id);
423
424 let sig = caller_sig.instantiate(tcx, args).skip_binder();
427 let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output()));
428 tcx.arena.alloc_from_iter(sig_iter)
429}