1use std::assert_matches::assert_matches;
2use std::fmt;
3use std::path::PathBuf;
4
5use rustc_data_structures::fx::FxHashMap;
6use rustc_errors::ErrorGuaranteed;
7use rustc_hir as hir;
8use rustc_hir::def::{CtorKind, DefKind, Namespace};
9use rustc_hir::def_id::{CrateNum, DefId};
10use rustc_hir::lang_items::LangItem;
11use rustc_index::bit_set::FiniteBitSet;
12use rustc_macros::{Decodable, Encodable, HashStable, Lift, TyDecodable, TyEncodable};
13use rustc_span::def_id::LOCAL_CRATE;
14use rustc_span::{DUMMY_SP, Span, Symbol};
15use tracing::{debug, instrument};
16
17use crate::error;
18use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
19use crate::ty::normalize_erasing_regions::NormalizationError;
20use crate::ty::print::{FmtPrinter, Printer, shrunk_instance_name};
21use crate::ty::{
22 self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
23 TypeVisitable, TypeVisitableExt, TypeVisitor,
24};
25
26#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
35#[derive(HashStable, Lift, TypeFoldable, TypeVisitable)]
36pub struct Instance<'tcx> {
37 pub def: InstanceKind<'tcx>,
38 pub args: GenericArgsRef<'tcx>,
39}
40
41#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
47#[derive(TyEncodable, TyDecodable, HashStable)]
48pub enum ReifyReason {
49 FnPtr,
57 Vtable,
61}
62
63#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
64#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
65pub enum InstanceKind<'tcx> {
66 Item(DefId),
73
74 Intrinsic(DefId),
80
81 VTableShim(DefId),
87
88 ReifyShim(DefId, Option<ReifyReason>),
106
107 FnPtrShim(DefId, Ty<'tcx>),
111
112 Virtual(DefId, usize),
121
122 ClosureOnceShim { call_once: DefId, track_caller: bool },
129
130 ConstructCoroutineInClosureShim {
136 coroutine_closure_def_id: DefId,
137 receiver_by_ref: bool,
143 },
144
145 ThreadLocalShim(DefId),
149
150 DropGlue(DefId, Option<Ty<'tcx>>),
156
157 CloneShim(DefId, Ty<'tcx>),
164
165 FnPtrAddrShim(DefId, Ty<'tcx>),
171
172 AsyncDropGlueCtorShim(DefId, Option<Ty<'tcx>>),
177}
178
179impl<'tcx> Instance<'tcx> {
180 pub fn ty(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> {
183 let ty = tcx.type_of(self.def.def_id());
184 tcx.instantiate_and_normalize_erasing_regions(self.args, typing_env, ty)
185 }
186
187 pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> {
194 if self.def_id().is_local() {
197 return None;
198 }
199
200 if !tcx.sess.opts.share_generics()
204 && tcx.codegen_fn_attrs(self.def_id()).inline != rustc_attr_parsing::InlineAttr::Never
207 {
208 return None;
209 }
210
211 self.args.non_erasable_generics().next()?;
213
214 if tcx.is_compiler_builtins(LOCAL_CRATE) {
216 return None;
217 }
218
219 match self.def {
220 InstanceKind::Item(def) => tcx
221 .upstream_monomorphizations_for(def)
222 .and_then(|monos| monos.get(&self.args).cloned()),
223 InstanceKind::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args),
224 InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => {
225 tcx.upstream_async_drop_glue_for(self.args)
226 }
227 _ => None,
228 }
229 }
230}
231
232impl<'tcx> InstanceKind<'tcx> {
233 #[inline]
234 pub fn def_id(self) -> DefId {
235 match self {
236 InstanceKind::Item(def_id)
237 | InstanceKind::VTableShim(def_id)
238 | InstanceKind::ReifyShim(def_id, _)
239 | InstanceKind::FnPtrShim(def_id, _)
240 | InstanceKind::Virtual(def_id, _)
241 | InstanceKind::Intrinsic(def_id)
242 | InstanceKind::ThreadLocalShim(def_id)
243 | InstanceKind::ClosureOnceShim { call_once: def_id, track_caller: _ }
244 | ty::InstanceKind::ConstructCoroutineInClosureShim {
245 coroutine_closure_def_id: def_id,
246 receiver_by_ref: _,
247 }
248 | InstanceKind::DropGlue(def_id, _)
249 | InstanceKind::CloneShim(def_id, _)
250 | InstanceKind::FnPtrAddrShim(def_id, _)
251 | InstanceKind::AsyncDropGlueCtorShim(def_id, _) => def_id,
252 }
253 }
254
255 pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
257 match self {
258 ty::InstanceKind::Item(def) => Some(def),
259 ty::InstanceKind::DropGlue(def_id, Some(_))
260 | InstanceKind::AsyncDropGlueCtorShim(def_id, Some(_))
261 | InstanceKind::ThreadLocalShim(def_id) => Some(def_id),
262 InstanceKind::VTableShim(..)
263 | InstanceKind::ReifyShim(..)
264 | InstanceKind::FnPtrShim(..)
265 | InstanceKind::Virtual(..)
266 | InstanceKind::Intrinsic(..)
267 | InstanceKind::ClosureOnceShim { .. }
268 | ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
269 | InstanceKind::DropGlue(..)
270 | InstanceKind::AsyncDropGlueCtorShim(..)
271 | InstanceKind::CloneShim(..)
272 | InstanceKind::FnPtrAddrShim(..) => None,
273 }
274 }
275
276 #[inline]
277 pub fn get_attrs(
278 &self,
279 tcx: TyCtxt<'tcx>,
280 attr: Symbol,
281 ) -> impl Iterator<Item = &'tcx hir::Attribute> {
282 tcx.get_attrs(self.def_id(), attr)
283 }
284
285 pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
291 use rustc_hir::definitions::DefPathData;
292 let def_id = match *self {
293 ty::InstanceKind::Item(def) => def,
294 ty::InstanceKind::DropGlue(_, Some(_)) => return false,
295 ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => return false,
296 ty::InstanceKind::ThreadLocalShim(_) => return false,
297 _ => return true,
298 };
299 matches!(
300 tcx.def_key(def_id).disambiguated_data.data,
301 DefPathData::Ctor | DefPathData::Closure
302 )
303 }
304
305 pub fn generates_cgu_internal_copy(&self, tcx: TyCtxt<'tcx>) -> bool {
313 if self.requires_inline(tcx) {
314 return true;
315 }
316 if let ty::InstanceKind::DropGlue(.., Some(ty))
317 | ty::InstanceKind::AsyncDropGlueCtorShim(.., Some(ty)) = *self
318 {
319 if tcx.sess.opts.incremental.is_none() {
323 return true;
324 }
325 return ty.ty_adt_def().is_none_or(|adt_def| {
333 match *self {
334 ty::InstanceKind::DropGlue(..) => adt_def.destructor(tcx).map(|dtor| dtor.did),
335 ty::InstanceKind::AsyncDropGlueCtorShim(..) => {
336 adt_def.async_destructor(tcx).map(|dtor| dtor.ctor)
337 }
338 _ => unreachable!(),
339 }
340 .map_or_else(|| adt_def.is_enum(), |did| tcx.cross_crate_inlinable(did))
341 });
342 }
343 if let ty::InstanceKind::ThreadLocalShim(..) = *self {
344 return false;
345 }
346 tcx.cross_crate_inlinable(self.def_id())
347 }
348
349 pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
350 match *self {
351 InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => {
352 tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
353 }
354 InstanceKind::ClosureOnceShim { call_once: _, track_caller } => track_caller,
355 _ => false,
356 }
357 }
358
359 pub fn has_polymorphic_mir_body(&self) -> bool {
366 match *self {
367 InstanceKind::CloneShim(..)
368 | InstanceKind::ThreadLocalShim(..)
369 | InstanceKind::FnPtrAddrShim(..)
370 | InstanceKind::FnPtrShim(..)
371 | InstanceKind::DropGlue(_, Some(_))
372 | InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => false,
373 InstanceKind::ClosureOnceShim { .. }
374 | InstanceKind::ConstructCoroutineInClosureShim { .. }
375 | InstanceKind::DropGlue(..)
376 | InstanceKind::AsyncDropGlueCtorShim(..)
377 | InstanceKind::Item(_)
378 | InstanceKind::Intrinsic(..)
379 | InstanceKind::ReifyShim(..)
380 | InstanceKind::Virtual(..)
381 | InstanceKind::VTableShim(..) => true,
382 }
383 }
384}
385
386fn type_length<'tcx>(item: impl TypeVisitable<TyCtxt<'tcx>>) -> usize {
387 struct Visitor<'tcx> {
388 type_length: usize,
389 cache: FxHashMap<Ty<'tcx>, usize>,
390 }
391 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'tcx> {
392 fn visit_ty(&mut self, t: Ty<'tcx>) {
393 if let Some(&value) = self.cache.get(&t) {
394 self.type_length += value;
395 return;
396 }
397
398 let prev = self.type_length;
399 self.type_length += 1;
400 t.super_visit_with(self);
401
402 if self.type_length > 16 {
404 self.cache.insert(t, self.type_length - prev);
405 }
406 }
407
408 fn visit_const(&mut self, ct: ty::Const<'tcx>) {
409 self.type_length += 1;
410 ct.super_visit_with(self);
411 }
412 }
413 let mut visitor = Visitor { type_length: 0, cache: Default::default() };
414 item.visit_with(&mut visitor);
415
416 visitor.type_length
417}
418
419pub fn fmt_instance(
420 f: &mut fmt::Formatter<'_>,
421 instance: Instance<'_>,
422 type_length: Option<rustc_session::Limit>,
423) -> fmt::Result {
424 ty::tls::with(|tcx| {
425 let args = tcx.lift(instance.args).expect("could not lift for printing");
426
427 let mut cx = if let Some(type_length) = type_length {
428 FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length)
429 } else {
430 FmtPrinter::new(tcx, Namespace::ValueNS)
431 };
432 cx.print_def_path(instance.def_id(), args)?;
433 let s = cx.into_buffer();
434 f.write_str(&s)
435 })?;
436
437 match instance.def {
438 InstanceKind::Item(_) => Ok(()),
439 InstanceKind::VTableShim(_) => write!(f, " - shim(vtable)"),
440 InstanceKind::ReifyShim(_, None) => write!(f, " - shim(reify)"),
441 InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => write!(f, " - shim(reify-fnptr)"),
442 InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => write!(f, " - shim(reify-vtable)"),
443 InstanceKind::ThreadLocalShim(_) => write!(f, " - shim(tls)"),
444 InstanceKind::Intrinsic(_) => write!(f, " - intrinsic"),
445 InstanceKind::Virtual(_, num) => write!(f, " - virtual#{num}"),
446 InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"),
447 InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"),
448 InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"),
449 InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"),
450 InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
451 InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"),
452 InstanceKind::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
453 InstanceKind::AsyncDropGlueCtorShim(_, None) => write!(f, " - shim(None)"),
454 InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
455 }
456}
457
458pub struct ShortInstance<'tcx>(pub Instance<'tcx>, pub usize);
459
460impl<'tcx> fmt::Display for ShortInstance<'tcx> {
461 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
462 fmt_instance(f, self.0, Some(rustc_session::Limit(self.1)))
463 }
464}
465
466impl<'tcx> fmt::Display for Instance<'tcx> {
467 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
468 fmt_instance(f, *self, None)
469 }
470}
471
472impl<'tcx> Instance<'tcx> {
473 pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> {
474 assert!(
475 !args.has_escaping_bound_vars(),
476 "args of instance {def_id:?} has escaping bound vars: {args:?}"
477 );
478 Instance { def: InstanceKind::Item(def_id), args }
479 }
480
481 pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
482 let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
483 ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
484 ty::GenericParamDefKind::Type { .. } => {
485 bug!("Instance::mono: {:?} has type parameters", def_id)
486 }
487 ty::GenericParamDefKind::Const { .. } => {
488 bug!("Instance::mono: {:?} has const parameters", def_id)
489 }
490 });
491
492 Instance::new(def_id, args)
493 }
494
495 #[inline]
496 pub fn def_id(&self) -> DefId {
497 self.def.def_id()
498 }
499
500 #[instrument(level = "debug", skip(tcx), ret)]
526 pub fn try_resolve(
527 tcx: TyCtxt<'tcx>,
528 typing_env: ty::TypingEnv<'tcx>,
529 def_id: DefId,
530 args: GenericArgsRef<'tcx>,
531 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
532 assert_matches!(
533 tcx.def_kind(def_id),
534 DefKind::Fn
535 | DefKind::AssocFn
536 | DefKind::Const
537 | DefKind::AssocConst
538 | DefKind::AnonConst
539 | DefKind::InlineConst
540 | DefKind::Static { .. }
541 | DefKind::Ctor(_, CtorKind::Fn)
542 | DefKind::Closure
543 | DefKind::SyntheticCoroutineBody,
544 "`Instance::try_resolve` should only be used to resolve instances of \
545 functions, statics, and consts; to resolve associated types, use \
546 `try_normalize_erasing_regions`."
547 );
548
549 if tcx.sess.opts.unstable_opts.enforce_type_length_limit
556 && !tcx.type_length_limit().value_within_limit(type_length(args))
557 {
558 return Ok(None);
559 }
560
561 tcx.resolve_instance_raw(tcx.erase_regions(typing_env.as_query_input((def_id, args))))
564 }
565
566 pub fn expect_resolve(
567 tcx: TyCtxt<'tcx>,
568 typing_env: ty::TypingEnv<'tcx>,
569 def_id: DefId,
570 args: GenericArgsRef<'tcx>,
571 span: Span,
572 ) -> Instance<'tcx> {
573 let span_or_local_def_span =
577 || if span.is_dummy() && def_id.is_local() { tcx.def_span(def_id) } else { span };
578
579 match ty::Instance::try_resolve(tcx, typing_env, def_id, args) {
580 Ok(Some(instance)) => instance,
581 Ok(None) => {
582 let type_length = type_length(args);
583 if !tcx.type_length_limit().value_within_limit(type_length) {
584 let (shrunk, written_to_path) =
585 shrunk_instance_name(tcx, Instance::new(def_id, args));
586 let mut path = PathBuf::new();
587 let was_written = if let Some(path2) = written_to_path {
588 path = path2;
589 true
590 } else {
591 false
592 };
593 tcx.dcx().emit_fatal(error::TypeLengthLimit {
594 span: span_or_local_def_span(),
598 shrunk,
599 was_written,
600 path,
601 type_length,
602 });
603 } else {
604 span_bug!(
605 span_or_local_def_span(),
606 "failed to resolve instance for {}",
607 tcx.def_path_str_with_args(def_id, args)
608 )
609 }
610 }
611 instance => span_bug!(
612 span_or_local_def_span(),
613 "failed to resolve instance for {}: {instance:#?}",
614 tcx.def_path_str_with_args(def_id, args)
615 ),
616 }
617 }
618
619 pub fn resolve_for_fn_ptr(
620 tcx: TyCtxt<'tcx>,
621 typing_env: ty::TypingEnv<'tcx>,
622 def_id: DefId,
623 args: GenericArgsRef<'tcx>,
624 ) -> Option<Instance<'tcx>> {
625 debug!("resolve(def_id={:?}, args={:?})", def_id, args);
626 assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}");
628 let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr);
629 Instance::try_resolve(tcx, typing_env, def_id, args).ok().flatten().map(|mut resolved| {
630 match resolved.def {
631 InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => {
632 debug!(" => fn pointer created for function with #[track_caller]");
633 resolved.def = InstanceKind::ReifyShim(def, reason);
634 }
635 InstanceKind::Virtual(def_id, _) => {
636 debug!(" => fn pointer created for virtual call");
637 resolved.def = InstanceKind::ReifyShim(def_id, reason);
638 }
639 _ if tcx.sess.is_sanitizer_kcfi_enabled()
642 && tcx
643 .opt_associated_item(def_id)
644 .and_then(|assoc| assoc.trait_item_def_id)
645 .is_some() =>
646 {
647 resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason)
650 }
651 _ if tcx.sess.is_sanitizer_kcfi_enabled()
653 && tcx.is_closure_like(resolved.def_id()) =>
654 {
655 resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
659 }
660 _ => {}
661 }
662
663 resolved
664 })
665 }
666
667 pub fn expect_resolve_for_vtable(
668 tcx: TyCtxt<'tcx>,
669 typing_env: ty::TypingEnv<'tcx>,
670 def_id: DefId,
671 args: GenericArgsRef<'tcx>,
672 span: Span,
673 ) -> Instance<'tcx> {
674 debug!("resolve_for_vtable(def_id={:?}, args={:?})", def_id, args);
675 let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
676 let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
677 && fn_sig.input(0).skip_binder().is_param(0)
678 && tcx.generics_of(def_id).has_self;
679
680 if is_vtable_shim {
681 debug!(" => associated item with unsizeable self: Self");
682 return Instance { def: InstanceKind::VTableShim(def_id), args };
683 }
684
685 let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span);
686
687 let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable);
688 match resolved.def {
689 InstanceKind::Item(def) => {
690 let needs_track_caller_shim = resolved.def.requires_caller_location(tcx)
700 && !tcx.should_inherit_track_caller(def)
703 && !matches!(
709 tcx.opt_associated_item(def),
710 Some(ty::AssocItem {
711 container: ty::AssocItemContainer::Trait,
712 ..
713 })
714 );
715 let needs_rpitit_shim =
717 tcx.return_position_impl_trait_in_trait_shim_data(def).is_some();
718 if needs_track_caller_shim || needs_rpitit_shim {
719 if tcx.is_closure_like(def) {
720 debug!(
721 " => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
722 def, def_id, args
723 );
724
725 resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args };
729 } else {
730 debug!(
731 " => vtable fn pointer created for function with #[track_caller]: {:?}",
732 def
733 );
734 resolved.def = InstanceKind::ReifyShim(def, reason);
735 }
736 }
737 }
738 InstanceKind::Virtual(def_id, _) => {
739 debug!(" => vtable fn pointer created for virtual call");
740 resolved.def = InstanceKind::ReifyShim(def_id, reason)
741 }
742 _ => {}
743 }
744
745 resolved
746 }
747
748 pub fn resolve_closure(
749 tcx: TyCtxt<'tcx>,
750 def_id: DefId,
751 args: ty::GenericArgsRef<'tcx>,
752 requested_kind: ty::ClosureKind,
753 ) -> Instance<'tcx> {
754 let actual_kind = args.as_closure().kind();
755
756 match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
757 Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args),
758 _ => Instance::new(def_id, args),
759 }
760 }
761
762 pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
763 let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
764 let args = tcx.mk_args(&[ty.into()]);
765 Instance::expect_resolve(
766 tcx,
767 ty::TypingEnv::fully_monomorphized(),
768 def_id,
769 args,
770 ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
771 )
772 }
773
774 pub fn resolve_async_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
775 let def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, None);
776 let args = tcx.mk_args(&[ty.into()]);
777 Instance::expect_resolve(
778 tcx,
779 ty::TypingEnv::fully_monomorphized(),
780 def_id,
781 args,
782 ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
783 )
784 }
785
786 #[instrument(level = "debug", skip(tcx), ret)]
787 pub fn fn_once_adapter_instance(
788 tcx: TyCtxt<'tcx>,
789 closure_did: DefId,
790 args: ty::GenericArgsRef<'tcx>,
791 ) -> Instance<'tcx> {
792 let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
793 let call_once = tcx
794 .associated_items(fn_once)
795 .in_definition_order()
796 .find(|it| it.kind == ty::AssocKind::Fn)
797 .unwrap()
798 .def_id;
799 let track_caller =
800 tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
801 let def = ty::InstanceKind::ClosureOnceShim { call_once, track_caller };
802
803 let self_ty = Ty::new_closure(tcx, closure_did, args);
804
805 let tupled_inputs_ty = args.as_closure().sig().map_bound(|sig| sig.inputs()[0]);
806 let tupled_inputs_ty = tcx.instantiate_bound_regions_with_erased(tupled_inputs_ty);
807 let args = tcx.mk_args_trait(self_ty, [tupled_inputs_ty.into()]);
808
809 debug!(?self_ty, args=?tupled_inputs_ty.tuple_fields());
810 Instance { def, args }
811 }
812
813 pub fn try_resolve_item_for_coroutine(
814 tcx: TyCtxt<'tcx>,
815 trait_item_id: DefId,
816 trait_id: DefId,
817 rcvr_args: ty::GenericArgsRef<'tcx>,
818 ) -> Option<Instance<'tcx>> {
819 let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
820 return None;
821 };
822 let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
823
824 let coroutine_callable_item = if tcx.is_lang_item(trait_id, LangItem::Future) {
825 assert_matches!(
826 coroutine_kind,
827 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
828 );
829 hir::LangItem::FuturePoll
830 } else if tcx.is_lang_item(trait_id, LangItem::Iterator) {
831 assert_matches!(
832 coroutine_kind,
833 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
834 );
835 hir::LangItem::IteratorNext
836 } else if tcx.is_lang_item(trait_id, LangItem::AsyncIterator) {
837 assert_matches!(
838 coroutine_kind,
839 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
840 );
841 hir::LangItem::AsyncIteratorPollNext
842 } else if tcx.is_lang_item(trait_id, LangItem::Coroutine) {
843 assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
844 hir::LangItem::CoroutineResume
845 } else {
846 return None;
847 };
848
849 if tcx.is_lang_item(trait_item_id, coroutine_callable_item) {
850 let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
851 else {
852 bug!()
853 };
854
855 if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() {
858 Some(Instance { def: ty::InstanceKind::Item(coroutine_def_id), args })
859 } else {
860 Some(Instance {
861 def: ty::InstanceKind::Item(
862 tcx.coroutine_by_move_body_def_id(coroutine_def_id),
863 ),
864 args,
865 })
866 }
867 } else {
868 debug_assert!(tcx.defaultness(trait_item_id).has_value());
872 Some(Instance::new(trait_item_id, rcvr_args))
873 }
874 }
875
876 fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> {
887 self.def.has_polymorphic_mir_body().then_some(self.args)
888 }
889
890 pub fn instantiate_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, &T>) -> T
891 where
892 T: TypeFoldable<TyCtxt<'tcx>> + Copy,
893 {
894 let v = v.map_bound(|v| *v);
895 if let Some(args) = self.args_for_mir_body() {
896 v.instantiate(tcx, args)
897 } else {
898 v.instantiate_identity()
899 }
900 }
901
902 #[inline(always)]
903 pub fn instantiate_mir_and_normalize_erasing_regions<T>(
905 &self,
906 tcx: TyCtxt<'tcx>,
907 typing_env: ty::TypingEnv<'tcx>,
908 v: EarlyBinder<'tcx, T>,
909 ) -> T
910 where
911 T: TypeFoldable<TyCtxt<'tcx>>,
912 {
913 if let Some(args) = self.args_for_mir_body() {
914 tcx.instantiate_and_normalize_erasing_regions(args, typing_env, v)
915 } else {
916 tcx.normalize_erasing_regions(typing_env, v.instantiate_identity())
917 }
918 }
919
920 #[inline(always)]
921 pub fn try_instantiate_mir_and_normalize_erasing_regions<T>(
923 &self,
924 tcx: TyCtxt<'tcx>,
925 typing_env: ty::TypingEnv<'tcx>,
926 v: EarlyBinder<'tcx, T>,
927 ) -> Result<T, NormalizationError<'tcx>>
928 where
929 T: TypeFoldable<TyCtxt<'tcx>>,
930 {
931 if let Some(args) = self.args_for_mir_body() {
932 tcx.try_instantiate_and_normalize_erasing_regions(args, typing_env, v)
933 } else {
934 tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity())
940 }
941 }
942}
943
944fn needs_fn_once_adapter_shim(
945 actual_closure_kind: ty::ClosureKind,
946 trait_closure_kind: ty::ClosureKind,
947) -> Result<bool, ()> {
948 match (actual_closure_kind, trait_closure_kind) {
949 (ty::ClosureKind::Fn, ty::ClosureKind::Fn)
950 | (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut)
951 | (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
952 Ok(false)
954 }
955 (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
956 Ok(false)
960 }
961 (ty::ClosureKind::Fn | ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
962 Ok(true)
971 }
972 (ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce, _) => Err(()),
973 }
974}
975
976#[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)]
979pub struct UnusedGenericParams(FiniteBitSet<u32>);
980
981impl Default for UnusedGenericParams {
982 fn default() -> Self {
983 UnusedGenericParams::new_all_used()
984 }
985}
986
987impl UnusedGenericParams {
988 pub fn new_all_unused(amount: u32) -> Self {
989 let mut bitset = FiniteBitSet::new_empty();
990 bitset.set_range(0..amount);
991 Self(bitset)
992 }
993
994 pub fn new_all_used() -> Self {
995 Self(FiniteBitSet::new_empty())
996 }
997
998 pub fn mark_used(&mut self, idx: u32) {
999 self.0.clear(idx);
1000 }
1001
1002 pub fn is_unused(&self, idx: u32) -> bool {
1003 self.0.contains(idx).unwrap_or(false)
1004 }
1005
1006 pub fn is_used(&self, idx: u32) -> bool {
1007 !self.is_unused(idx)
1008 }
1009
1010 pub fn all_used(&self) -> bool {
1011 self.0.is_empty()
1012 }
1013
1014 pub fn bits(&self) -> u32 {
1015 self.0.0
1016 }
1017
1018 pub fn from_bits(bits: u32) -> UnusedGenericParams {
1019 UnusedGenericParams(FiniteBitSet(bits))
1020 }
1021}