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_data_structures::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 requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
306 match *self {
307 InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => {
308 tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
309 }
310 InstanceKind::ClosureOnceShim { call_once: _, track_caller } => track_caller,
311 _ => false,
312 }
313 }
314
315 pub fn has_polymorphic_mir_body(&self) -> bool {
322 match *self {
323 InstanceKind::CloneShim(..)
324 | InstanceKind::ThreadLocalShim(..)
325 | InstanceKind::FnPtrAddrShim(..)
326 | InstanceKind::FnPtrShim(..)
327 | InstanceKind::DropGlue(_, Some(_))
328 | InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => false,
329 InstanceKind::ClosureOnceShim { .. }
330 | InstanceKind::ConstructCoroutineInClosureShim { .. }
331 | InstanceKind::DropGlue(..)
332 | InstanceKind::AsyncDropGlueCtorShim(..)
333 | InstanceKind::Item(_)
334 | InstanceKind::Intrinsic(..)
335 | InstanceKind::ReifyShim(..)
336 | InstanceKind::Virtual(..)
337 | InstanceKind::VTableShim(..) => true,
338 }
339 }
340}
341
342fn type_length<'tcx>(item: impl TypeVisitable<TyCtxt<'tcx>>) -> usize {
343 struct Visitor<'tcx> {
344 type_length: usize,
345 cache: FxHashMap<Ty<'tcx>, usize>,
346 }
347 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'tcx> {
348 fn visit_ty(&mut self, t: Ty<'tcx>) {
349 if let Some(&value) = self.cache.get(&t) {
350 self.type_length += value;
351 return;
352 }
353
354 let prev = self.type_length;
355 self.type_length += 1;
356 t.super_visit_with(self);
357
358 if self.type_length > 16 {
360 self.cache.insert(t, self.type_length - prev);
361 }
362 }
363
364 fn visit_const(&mut self, ct: ty::Const<'tcx>) {
365 self.type_length += 1;
366 ct.super_visit_with(self);
367 }
368 }
369 let mut visitor = Visitor { type_length: 0, cache: Default::default() };
370 item.visit_with(&mut visitor);
371
372 visitor.type_length
373}
374
375pub fn fmt_instance(
376 f: &mut fmt::Formatter<'_>,
377 instance: Instance<'_>,
378 type_length: Option<rustc_session::Limit>,
379) -> fmt::Result {
380 ty::tls::with(|tcx| {
381 let args = tcx.lift(instance.args).expect("could not lift for printing");
382
383 let mut cx = if let Some(type_length) = type_length {
384 FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length)
385 } else {
386 FmtPrinter::new(tcx, Namespace::ValueNS)
387 };
388 cx.print_def_path(instance.def_id(), args)?;
389 let s = cx.into_buffer();
390 f.write_str(&s)
391 })?;
392
393 match instance.def {
394 InstanceKind::Item(_) => Ok(()),
395 InstanceKind::VTableShim(_) => write!(f, " - shim(vtable)"),
396 InstanceKind::ReifyShim(_, None) => write!(f, " - shim(reify)"),
397 InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => write!(f, " - shim(reify-fnptr)"),
398 InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => write!(f, " - shim(reify-vtable)"),
399 InstanceKind::ThreadLocalShim(_) => write!(f, " - shim(tls)"),
400 InstanceKind::Intrinsic(_) => write!(f, " - intrinsic"),
401 InstanceKind::Virtual(_, num) => write!(f, " - virtual#{num}"),
402 InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"),
403 InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"),
404 InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"),
405 InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"),
406 InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
407 InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"),
408 InstanceKind::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
409 InstanceKind::AsyncDropGlueCtorShim(_, None) => write!(f, " - shim(None)"),
410 InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
411 }
412}
413
414pub struct ShortInstance<'tcx>(pub Instance<'tcx>, pub usize);
415
416impl<'tcx> fmt::Display for ShortInstance<'tcx> {
417 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418 fmt_instance(f, self.0, Some(rustc_session::Limit(self.1)))
419 }
420}
421
422impl<'tcx> fmt::Display for Instance<'tcx> {
423 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
424 fmt_instance(f, *self, None)
425 }
426}
427
428impl<'tcx> Instance<'tcx> {
429 pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> {
430 assert!(
431 !args.has_escaping_bound_vars(),
432 "args of instance {def_id:?} has escaping bound vars: {args:?}"
433 );
434 Instance { def: InstanceKind::Item(def_id), args }
435 }
436
437 pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
438 let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
439 ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
440 ty::GenericParamDefKind::Type { .. } => {
441 bug!("Instance::mono: {:?} has type parameters", def_id)
442 }
443 ty::GenericParamDefKind::Const { .. } => {
444 bug!("Instance::mono: {:?} has const parameters", def_id)
445 }
446 });
447
448 Instance::new(def_id, args)
449 }
450
451 #[inline]
452 pub fn def_id(&self) -> DefId {
453 self.def.def_id()
454 }
455
456 #[instrument(level = "debug", skip(tcx), ret)]
482 pub fn try_resolve(
483 tcx: TyCtxt<'tcx>,
484 typing_env: ty::TypingEnv<'tcx>,
485 def_id: DefId,
486 args: GenericArgsRef<'tcx>,
487 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
488 assert_matches!(
489 tcx.def_kind(def_id),
490 DefKind::Fn
491 | DefKind::AssocFn
492 | DefKind::Const
493 | DefKind::AssocConst
494 | DefKind::AnonConst
495 | DefKind::InlineConst
496 | DefKind::Static { .. }
497 | DefKind::Ctor(_, CtorKind::Fn)
498 | DefKind::Closure
499 | DefKind::SyntheticCoroutineBody,
500 "`Instance::try_resolve` should only be used to resolve instances of \
501 functions, statics, and consts; to resolve associated types, use \
502 `try_normalize_erasing_regions`."
503 );
504
505 if tcx.sess.opts.unstable_opts.enforce_type_length_limit
512 && !tcx.type_length_limit().value_within_limit(type_length(args))
513 {
514 return Ok(None);
515 }
516
517 tcx.resolve_instance_raw(tcx.erase_regions(typing_env.as_query_input((def_id, args))))
520 }
521
522 pub fn expect_resolve(
523 tcx: TyCtxt<'tcx>,
524 typing_env: ty::TypingEnv<'tcx>,
525 def_id: DefId,
526 args: GenericArgsRef<'tcx>,
527 span: Span,
528 ) -> Instance<'tcx> {
529 let span_or_local_def_span =
533 || if span.is_dummy() && def_id.is_local() { tcx.def_span(def_id) } else { span };
534
535 match ty::Instance::try_resolve(tcx, typing_env, def_id, args) {
536 Ok(Some(instance)) => instance,
537 Ok(None) => {
538 let type_length = type_length(args);
539 if !tcx.type_length_limit().value_within_limit(type_length) {
540 let (shrunk, written_to_path) =
541 shrunk_instance_name(tcx, Instance::new(def_id, args));
542 let mut path = PathBuf::new();
543 let was_written = if let Some(path2) = written_to_path {
544 path = path2;
545 true
546 } else {
547 false
548 };
549 tcx.dcx().emit_fatal(error::TypeLengthLimit {
550 span: span_or_local_def_span(),
554 shrunk,
555 was_written,
556 path,
557 type_length,
558 });
559 } else {
560 span_bug!(
561 span_or_local_def_span(),
562 "failed to resolve instance for {}",
563 tcx.def_path_str_with_args(def_id, args)
564 )
565 }
566 }
567 instance => span_bug!(
568 span_or_local_def_span(),
569 "failed to resolve instance for {}: {instance:#?}",
570 tcx.def_path_str_with_args(def_id, args)
571 ),
572 }
573 }
574
575 pub fn resolve_for_fn_ptr(
576 tcx: TyCtxt<'tcx>,
577 typing_env: ty::TypingEnv<'tcx>,
578 def_id: DefId,
579 args: GenericArgsRef<'tcx>,
580 ) -> Option<Instance<'tcx>> {
581 debug!("resolve(def_id={:?}, args={:?})", def_id, args);
582 assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}");
584 let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr);
585 Instance::try_resolve(tcx, typing_env, def_id, args).ok().flatten().map(|mut resolved| {
586 match resolved.def {
587 InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => {
588 debug!(" => fn pointer created for function with #[track_caller]");
589 resolved.def = InstanceKind::ReifyShim(def, reason);
590 }
591 InstanceKind::Virtual(def_id, _) => {
592 debug!(" => fn pointer created for virtual call");
593 resolved.def = InstanceKind::ReifyShim(def_id, reason);
594 }
595 _ if tcx.sess.is_sanitizer_kcfi_enabled()
598 && tcx
599 .opt_associated_item(def_id)
600 .and_then(|assoc| assoc.trait_item_def_id)
601 .is_some() =>
602 {
603 resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason)
606 }
607 _ if tcx.sess.is_sanitizer_kcfi_enabled()
609 && tcx.is_closure_like(resolved.def_id()) =>
610 {
611 resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
615 }
616 _ => {}
617 }
618
619 resolved
620 })
621 }
622
623 pub fn expect_resolve_for_vtable(
624 tcx: TyCtxt<'tcx>,
625 typing_env: ty::TypingEnv<'tcx>,
626 def_id: DefId,
627 args: GenericArgsRef<'tcx>,
628 span: Span,
629 ) -> Instance<'tcx> {
630 debug!("resolve_for_vtable(def_id={:?}, args={:?})", def_id, args);
631 let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
632 let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
633 && fn_sig.input(0).skip_binder().is_param(0)
634 && tcx.generics_of(def_id).has_self;
635
636 if is_vtable_shim {
637 debug!(" => associated item with unsizeable self: Self");
638 return Instance { def: InstanceKind::VTableShim(def_id), args };
639 }
640
641 let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span);
642
643 let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable);
644 match resolved.def {
645 InstanceKind::Item(def) => {
646 let needs_track_caller_shim = resolved.def.requires_caller_location(tcx)
656 && !tcx.should_inherit_track_caller(def)
659 && !matches!(
665 tcx.opt_associated_item(def),
666 Some(ty::AssocItem {
667 container: ty::AssocItemContainer::Trait,
668 ..
669 })
670 );
671 if needs_track_caller_shim {
672 if tcx.is_closure_like(def) {
673 debug!(
674 " => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
675 def, def_id, args
676 );
677
678 resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args };
682 } else {
683 debug!(
684 " => vtable fn pointer created for function with #[track_caller]: {:?}",
685 def
686 );
687 resolved.def = InstanceKind::ReifyShim(def, reason);
688 }
689 }
690 }
691 InstanceKind::Virtual(def_id, _) => {
692 debug!(" => vtable fn pointer created for virtual call");
693 resolved.def = InstanceKind::ReifyShim(def_id, reason)
694 }
695 _ => {}
696 }
697
698 resolved
699 }
700
701 pub fn resolve_closure(
702 tcx: TyCtxt<'tcx>,
703 def_id: DefId,
704 args: ty::GenericArgsRef<'tcx>,
705 requested_kind: ty::ClosureKind,
706 ) -> Instance<'tcx> {
707 let actual_kind = args.as_closure().kind();
708
709 match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
710 Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args),
711 _ => Instance::new(def_id, args),
712 }
713 }
714
715 pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
716 let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
717 let args = tcx.mk_args(&[ty.into()]);
718 Instance::expect_resolve(
719 tcx,
720 ty::TypingEnv::fully_monomorphized(),
721 def_id,
722 args,
723 ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
724 )
725 }
726
727 pub fn resolve_async_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
728 let def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, None);
729 let args = tcx.mk_args(&[ty.into()]);
730 Instance::expect_resolve(
731 tcx,
732 ty::TypingEnv::fully_monomorphized(),
733 def_id,
734 args,
735 ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP),
736 )
737 }
738
739 #[instrument(level = "debug", skip(tcx), ret)]
740 pub fn fn_once_adapter_instance(
741 tcx: TyCtxt<'tcx>,
742 closure_did: DefId,
743 args: ty::GenericArgsRef<'tcx>,
744 ) -> Instance<'tcx> {
745 let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
746 let call_once = tcx
747 .associated_items(fn_once)
748 .in_definition_order()
749 .find(|it| it.kind == ty::AssocKind::Fn)
750 .unwrap()
751 .def_id;
752 let track_caller =
753 tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
754 let def = ty::InstanceKind::ClosureOnceShim { call_once, track_caller };
755
756 let self_ty = Ty::new_closure(tcx, closure_did, args);
757
758 let tupled_inputs_ty = args.as_closure().sig().map_bound(|sig| sig.inputs()[0]);
759 let tupled_inputs_ty = tcx.instantiate_bound_regions_with_erased(tupled_inputs_ty);
760 let args = tcx.mk_args_trait(self_ty, [tupled_inputs_ty.into()]);
761
762 debug!(?self_ty, args=?tupled_inputs_ty.tuple_fields());
763 Instance { def, args }
764 }
765
766 pub fn try_resolve_item_for_coroutine(
767 tcx: TyCtxt<'tcx>,
768 trait_item_id: DefId,
769 trait_id: DefId,
770 rcvr_args: ty::GenericArgsRef<'tcx>,
771 ) -> Option<Instance<'tcx>> {
772 let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
773 return None;
774 };
775 let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
776
777 let coroutine_callable_item = if tcx.is_lang_item(trait_id, LangItem::Future) {
778 assert_matches!(
779 coroutine_kind,
780 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
781 );
782 hir::LangItem::FuturePoll
783 } else if tcx.is_lang_item(trait_id, LangItem::Iterator) {
784 assert_matches!(
785 coroutine_kind,
786 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
787 );
788 hir::LangItem::IteratorNext
789 } else if tcx.is_lang_item(trait_id, LangItem::AsyncIterator) {
790 assert_matches!(
791 coroutine_kind,
792 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
793 );
794 hir::LangItem::AsyncIteratorPollNext
795 } else if tcx.is_lang_item(trait_id, LangItem::Coroutine) {
796 assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
797 hir::LangItem::CoroutineResume
798 } else {
799 return None;
800 };
801
802 if tcx.is_lang_item(trait_item_id, coroutine_callable_item) {
803 let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
804 else {
805 bug!()
806 };
807
808 if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() {
811 Some(Instance { def: ty::InstanceKind::Item(coroutine_def_id), args })
812 } else {
813 Some(Instance {
814 def: ty::InstanceKind::Item(
815 tcx.coroutine_by_move_body_def_id(coroutine_def_id),
816 ),
817 args,
818 })
819 }
820 } else {
821 debug_assert!(tcx.defaultness(trait_item_id).has_value());
825 Some(Instance::new(trait_item_id, rcvr_args))
826 }
827 }
828
829 fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> {
840 self.def.has_polymorphic_mir_body().then_some(self.args)
841 }
842
843 pub fn instantiate_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, &T>) -> T
844 where
845 T: TypeFoldable<TyCtxt<'tcx>> + Copy,
846 {
847 let v = v.map_bound(|v| *v);
848 if let Some(args) = self.args_for_mir_body() {
849 v.instantiate(tcx, args)
850 } else {
851 v.instantiate_identity()
852 }
853 }
854
855 #[inline(always)]
856 pub fn instantiate_mir_and_normalize_erasing_regions<T>(
858 &self,
859 tcx: TyCtxt<'tcx>,
860 typing_env: ty::TypingEnv<'tcx>,
861 v: EarlyBinder<'tcx, T>,
862 ) -> T
863 where
864 T: TypeFoldable<TyCtxt<'tcx>>,
865 {
866 if let Some(args) = self.args_for_mir_body() {
867 tcx.instantiate_and_normalize_erasing_regions(args, typing_env, v)
868 } else {
869 tcx.normalize_erasing_regions(typing_env, v.instantiate_identity())
870 }
871 }
872
873 #[inline(always)]
874 pub fn try_instantiate_mir_and_normalize_erasing_regions<T>(
876 &self,
877 tcx: TyCtxt<'tcx>,
878 typing_env: ty::TypingEnv<'tcx>,
879 v: EarlyBinder<'tcx, T>,
880 ) -> Result<T, NormalizationError<'tcx>>
881 where
882 T: TypeFoldable<TyCtxt<'tcx>>,
883 {
884 if let Some(args) = self.args_for_mir_body() {
885 tcx.try_instantiate_and_normalize_erasing_regions(args, typing_env, v)
886 } else {
887 tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity())
893 }
894 }
895}
896
897fn needs_fn_once_adapter_shim(
898 actual_closure_kind: ty::ClosureKind,
899 trait_closure_kind: ty::ClosureKind,
900) -> Result<bool, ()> {
901 match (actual_closure_kind, trait_closure_kind) {
902 (ty::ClosureKind::Fn, ty::ClosureKind::Fn)
903 | (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut)
904 | (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
905 Ok(false)
907 }
908 (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
909 Ok(false)
913 }
914 (ty::ClosureKind::Fn | ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
915 Ok(true)
924 }
925 (ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce, _) => Err(()),
926 }
927}
928
929#[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)]
932pub struct UnusedGenericParams(FiniteBitSet<u32>);
933
934impl Default for UnusedGenericParams {
935 fn default() -> Self {
936 UnusedGenericParams::new_all_used()
937 }
938}
939
940impl UnusedGenericParams {
941 pub fn new_all_unused(amount: u32) -> Self {
942 let mut bitset = FiniteBitSet::new_empty();
943 bitset.set_range(0..amount);
944 Self(bitset)
945 }
946
947 pub fn new_all_used() -> Self {
948 Self(FiniteBitSet::new_empty())
949 }
950
951 pub fn mark_used(&mut self, idx: u32) {
952 self.0.clear(idx);
953 }
954
955 pub fn is_unused(&self, idx: u32) -> bool {
956 self.0.contains(idx).unwrap_or(false)
957 }
958
959 pub fn is_used(&self, idx: u32) -> bool {
960 !self.is_unused(idx)
961 }
962
963 pub fn all_used(&self) -> bool {
964 self.0.is_empty()
965 }
966
967 pub fn bits(&self) -> u32 {
968 self.0.0
969 }
970
971 pub fn from_bits(bits: u32) -> UnusedGenericParams {
972 UnusedGenericParams(FiniteBitSet(bits))
973 }
974}