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 FutureDropPollShim(DefId, Ty<'tcx>, Ty<'tcx>),
152
153 DropGlue(DefId, Option<Ty<'tcx>>),
159
160 CloneShim(DefId, Ty<'tcx>),
167
168 FnPtrAddrShim(DefId, Ty<'tcx>),
174
175 AsyncDropGlueCtorShim(DefId, Ty<'tcx>),
180
181 AsyncDropGlue(DefId, Ty<'tcx>),
186}
187
188impl<'tcx> Instance<'tcx> {
189 pub fn ty(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> {
192 let ty = tcx.type_of(self.def.def_id());
193 tcx.instantiate_and_normalize_erasing_regions(self.args, typing_env, ty)
194 }
195
196 pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> {
203 if self.def_id().is_local() {
206 return None;
207 }
208
209 if !tcx.sess.opts.share_generics()
213 && tcx.codegen_fn_attrs(self.def_id()).inline != rustc_attr_data_structures::InlineAttr::Never
216 {
217 return None;
218 }
219
220 self.args.non_erasable_generics().next()?;
222
223 if tcx.is_compiler_builtins(LOCAL_CRATE) {
225 return None;
226 }
227
228 match self.def {
229 InstanceKind::Item(def) => tcx
230 .upstream_monomorphizations_for(def)
231 .and_then(|monos| monos.get(&self.args).cloned()),
232 InstanceKind::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args),
233 InstanceKind::AsyncDropGlue(_, _) => None,
234 InstanceKind::FutureDropPollShim(_, _, _) => None,
235 InstanceKind::AsyncDropGlueCtorShim(_, _) => {
236 tcx.upstream_async_drop_glue_for(self.args)
237 }
238 _ => None,
239 }
240 }
241}
242
243impl<'tcx> InstanceKind<'tcx> {
244 #[inline]
245 pub fn def_id(self) -> DefId {
246 match self {
247 InstanceKind::Item(def_id)
248 | InstanceKind::VTableShim(def_id)
249 | InstanceKind::ReifyShim(def_id, _)
250 | InstanceKind::FnPtrShim(def_id, _)
251 | InstanceKind::Virtual(def_id, _)
252 | InstanceKind::Intrinsic(def_id)
253 | InstanceKind::ThreadLocalShim(def_id)
254 | InstanceKind::ClosureOnceShim { call_once: def_id, track_caller: _ }
255 | ty::InstanceKind::ConstructCoroutineInClosureShim {
256 coroutine_closure_def_id: def_id,
257 receiver_by_ref: _,
258 }
259 | InstanceKind::DropGlue(def_id, _)
260 | InstanceKind::CloneShim(def_id, _)
261 | InstanceKind::FnPtrAddrShim(def_id, _)
262 | InstanceKind::FutureDropPollShim(def_id, _, _)
263 | InstanceKind::AsyncDropGlue(def_id, _)
264 | InstanceKind::AsyncDropGlueCtorShim(def_id, _) => def_id,
265 }
266 }
267
268 pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
270 match self {
271 ty::InstanceKind::Item(def) => Some(def),
272 ty::InstanceKind::DropGlue(def_id, Some(_))
273 | InstanceKind::AsyncDropGlueCtorShim(def_id, _)
274 | InstanceKind::AsyncDropGlue(def_id, _)
275 | InstanceKind::FutureDropPollShim(def_id, ..)
276 | InstanceKind::ThreadLocalShim(def_id) => Some(def_id),
277 InstanceKind::VTableShim(..)
278 | InstanceKind::ReifyShim(..)
279 | InstanceKind::FnPtrShim(..)
280 | InstanceKind::Virtual(..)
281 | InstanceKind::Intrinsic(..)
282 | InstanceKind::ClosureOnceShim { .. }
283 | ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
284 | InstanceKind::DropGlue(..)
285 | InstanceKind::CloneShim(..)
286 | InstanceKind::FnPtrAddrShim(..) => None,
287 }
288 }
289
290 #[inline]
291 pub fn get_attrs(
292 &self,
293 tcx: TyCtxt<'tcx>,
294 attr: Symbol,
295 ) -> impl Iterator<Item = &'tcx hir::Attribute> {
296 tcx.get_attrs(self.def_id(), attr)
297 }
298
299 pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
305 use rustc_hir::definitions::DefPathData;
306 let def_id = match *self {
307 ty::InstanceKind::Item(def) => def,
308 ty::InstanceKind::DropGlue(_, Some(_)) => return false,
309 ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => return ty.is_coroutine(),
310 ty::InstanceKind::FutureDropPollShim(_, _, _) => return false,
311 ty::InstanceKind::AsyncDropGlue(_, _) => return false,
312 ty::InstanceKind::ThreadLocalShim(_) => return false,
313 _ => return true,
314 };
315 matches!(
316 tcx.def_key(def_id).disambiguated_data.data,
317 DefPathData::Ctor | DefPathData::Closure
318 )
319 }
320
321 pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
322 match *self {
323 InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => {
324 tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
325 }
326 InstanceKind::ClosureOnceShim { call_once: _, track_caller } => track_caller,
327 _ => false,
328 }
329 }
330
331 pub fn has_polymorphic_mir_body(&self) -> bool {
338 match *self {
339 InstanceKind::CloneShim(..)
340 | InstanceKind::ThreadLocalShim(..)
341 | InstanceKind::FnPtrAddrShim(..)
342 | InstanceKind::FnPtrShim(..)
343 | InstanceKind::DropGlue(_, Some(_))
344 | InstanceKind::FutureDropPollShim(..)
345 | InstanceKind::AsyncDropGlue(_, _) => false,
346 InstanceKind::AsyncDropGlueCtorShim(_, _) => false,
347 InstanceKind::ClosureOnceShim { .. }
348 | InstanceKind::ConstructCoroutineInClosureShim { .. }
349 | InstanceKind::DropGlue(..)
350 | InstanceKind::Item(_)
351 | InstanceKind::Intrinsic(..)
352 | InstanceKind::ReifyShim(..)
353 | InstanceKind::Virtual(..)
354 | InstanceKind::VTableShim(..) => true,
355 }
356 }
357}
358
359fn type_length<'tcx>(item: impl TypeVisitable<TyCtxt<'tcx>>) -> usize {
360 struct Visitor<'tcx> {
361 type_length: usize,
362 cache: FxHashMap<Ty<'tcx>, usize>,
363 }
364 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'tcx> {
365 fn visit_ty(&mut self, t: Ty<'tcx>) {
366 if let Some(&value) = self.cache.get(&t) {
367 self.type_length += value;
368 return;
369 }
370
371 let prev = self.type_length;
372 self.type_length += 1;
373 t.super_visit_with(self);
374
375 if self.type_length > 16 {
377 self.cache.insert(t, self.type_length - prev);
378 }
379 }
380
381 fn visit_const(&mut self, ct: ty::Const<'tcx>) {
382 self.type_length += 1;
383 ct.super_visit_with(self);
384 }
385 }
386 let mut visitor = Visitor { type_length: 0, cache: Default::default() };
387 item.visit_with(&mut visitor);
388
389 visitor.type_length
390}
391
392pub fn fmt_instance(
393 f: &mut fmt::Formatter<'_>,
394 instance: Instance<'_>,
395 type_length: Option<rustc_session::Limit>,
396) -> fmt::Result {
397 ty::tls::with(|tcx| {
398 let args = tcx.lift(instance.args).expect("could not lift for printing");
399
400 let mut cx = if let Some(type_length) = type_length {
401 FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length)
402 } else {
403 FmtPrinter::new(tcx, Namespace::ValueNS)
404 };
405 cx.print_def_path(instance.def_id(), args)?;
406 let s = cx.into_buffer();
407 f.write_str(&s)
408 })?;
409
410 match instance.def {
411 InstanceKind::Item(_) => Ok(()),
412 InstanceKind::VTableShim(_) => write!(f, " - shim(vtable)"),
413 InstanceKind::ReifyShim(_, None) => write!(f, " - shim(reify)"),
414 InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => write!(f, " - shim(reify-fnptr)"),
415 InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => write!(f, " - shim(reify-vtable)"),
416 InstanceKind::ThreadLocalShim(_) => write!(f, " - shim(tls)"),
417 InstanceKind::Intrinsic(_) => write!(f, " - intrinsic"),
418 InstanceKind::Virtual(_, num) => write!(f, " - virtual#{num}"),
419 InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"),
420 InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"),
421 InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"),
422 InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"),
423 InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
424 InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"),
425 InstanceKind::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
426 InstanceKind::FutureDropPollShim(_, proxy_ty, impl_ty) => {
427 write!(f, " - dropshim({proxy_ty}-{impl_ty})")
428 }
429 InstanceKind::AsyncDropGlue(_, ty) => write!(f, " - shim({ty})"),
430 InstanceKind::AsyncDropGlueCtorShim(_, ty) => write!(f, " - shim(Some({ty}))"),
431 }
432}
433
434pub struct ShortInstance<'tcx>(pub Instance<'tcx>, pub usize);
435
436impl<'tcx> fmt::Display for ShortInstance<'tcx> {
437 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
438 fmt_instance(f, self.0, Some(rustc_session::Limit(self.1)))
439 }
440}
441
442impl<'tcx> fmt::Display for Instance<'tcx> {
443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444 fmt_instance(f, *self, None)
445 }
446}
447
448fn resolve_async_drop_poll<'tcx>(mut cor_ty: Ty<'tcx>) -> Instance<'tcx> {
456 let first_cor = cor_ty;
457 let ty::Coroutine(poll_def_id, proxy_args) = first_cor.kind() else {
458 bug!();
459 };
460 let poll_def_id = *poll_def_id;
461 let mut child_ty = cor_ty;
462 loop {
463 if let ty::Coroutine(child_def, child_args) = child_ty.kind() {
464 cor_ty = child_ty;
465 if *child_def == poll_def_id {
466 child_ty = child_args.first().unwrap().expect_ty();
467 continue;
468 } else {
469 return Instance {
470 def: ty::InstanceKind::FutureDropPollShim(poll_def_id, first_cor, cor_ty),
471 args: proxy_args,
472 };
473 }
474 } else {
475 let ty::Coroutine(_, child_args) = cor_ty.kind() else {
476 bug!();
477 };
478 if first_cor != cor_ty {
479 return Instance {
480 def: ty::InstanceKind::FutureDropPollShim(poll_def_id, first_cor, cor_ty),
481 args: proxy_args,
482 };
483 } else {
484 return Instance {
485 def: ty::InstanceKind::AsyncDropGlue(poll_def_id, cor_ty),
486 args: child_args,
487 };
488 }
489 }
490 }
491}
492
493impl<'tcx> Instance<'tcx> {
494 pub fn new_raw(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> {
503 assert!(
504 !args.has_escaping_bound_vars(),
505 "args of instance {def_id:?} has escaping bound vars: {args:?}"
506 );
507 Instance { def: InstanceKind::Item(def_id), args }
508 }
509
510 pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
511 let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
512 ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
513 ty::GenericParamDefKind::Type { .. } => {
514 bug!("Instance::mono: {:?} has type parameters", def_id)
515 }
516 ty::GenericParamDefKind::Const { .. } => {
517 bug!("Instance::mono: {:?} has const parameters", def_id)
518 }
519 });
520
521 Instance::new_raw(def_id, args)
522 }
523
524 #[inline]
525 pub fn def_id(&self) -> DefId {
526 self.def.def_id()
527 }
528
529 #[instrument(level = "debug", skip(tcx), ret)]
555 pub fn try_resolve(
556 tcx: TyCtxt<'tcx>,
557 typing_env: ty::TypingEnv<'tcx>,
558 def_id: DefId,
559 args: GenericArgsRef<'tcx>,
560 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
561 assert_matches!(
562 tcx.def_kind(def_id),
563 DefKind::Fn
564 | DefKind::AssocFn
565 | DefKind::Const
566 | DefKind::AssocConst
567 | DefKind::AnonConst
568 | DefKind::InlineConst
569 | DefKind::Static { .. }
570 | DefKind::Ctor(_, CtorKind::Fn)
571 | DefKind::Closure
572 | DefKind::SyntheticCoroutineBody,
573 "`Instance::try_resolve` should only be used to resolve instances of \
574 functions, statics, and consts; to resolve associated types, use \
575 `try_normalize_erasing_regions`."
576 );
577
578 if tcx.sess.opts.unstable_opts.enforce_type_length_limit
585 && !tcx.type_length_limit().value_within_limit(type_length(args))
586 {
587 return Ok(None);
588 }
589
590 tcx.resolve_instance_raw(tcx.erase_regions(typing_env.as_query_input((def_id, args))))
593 }
594
595 pub fn expect_resolve(
596 tcx: TyCtxt<'tcx>,
597 typing_env: ty::TypingEnv<'tcx>,
598 def_id: DefId,
599 args: GenericArgsRef<'tcx>,
600 span: Span,
601 ) -> Instance<'tcx> {
602 let span_or_local_def_span =
606 || if span.is_dummy() && def_id.is_local() { tcx.def_span(def_id) } else { span };
607
608 match ty::Instance::try_resolve(tcx, typing_env, def_id, args) {
609 Ok(Some(instance)) => instance,
610 Ok(None) => {
611 let type_length = type_length(args);
612 if !tcx.type_length_limit().value_within_limit(type_length) {
613 let (shrunk, written_to_path) =
614 shrunk_instance_name(tcx, Instance::new_raw(def_id, args));
615 let mut path = PathBuf::new();
616 let was_written = if let Some(path2) = written_to_path {
617 path = path2;
618 true
619 } else {
620 false
621 };
622 tcx.dcx().emit_fatal(error::TypeLengthLimit {
623 span: span_or_local_def_span(),
627 shrunk,
628 was_written,
629 path,
630 type_length,
631 });
632 } else {
633 span_bug!(
634 span_or_local_def_span(),
635 "failed to resolve instance for {}",
636 tcx.def_path_str_with_args(def_id, args)
637 )
638 }
639 }
640 instance => span_bug!(
641 span_or_local_def_span(),
642 "failed to resolve instance for {}: {instance:#?}",
643 tcx.def_path_str_with_args(def_id, args)
644 ),
645 }
646 }
647
648 pub fn resolve_for_fn_ptr(
649 tcx: TyCtxt<'tcx>,
650 typing_env: ty::TypingEnv<'tcx>,
651 def_id: DefId,
652 args: GenericArgsRef<'tcx>,
653 ) -> Option<Instance<'tcx>> {
654 debug!("resolve(def_id={:?}, args={:?})", def_id, args);
655 assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}");
657 let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr);
658 Instance::try_resolve(tcx, typing_env, def_id, args).ok().flatten().map(|mut resolved| {
659 match resolved.def {
660 InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => {
661 debug!(" => fn pointer created for function with #[track_caller]");
662 resolved.def = InstanceKind::ReifyShim(def, reason);
663 }
664 InstanceKind::Virtual(def_id, _) => {
665 debug!(" => fn pointer created for virtual call");
666 resolved.def = InstanceKind::ReifyShim(def_id, reason);
667 }
668 _ if tcx.sess.is_sanitizer_kcfi_enabled()
671 && tcx
672 .opt_associated_item(def_id)
673 .and_then(|assoc| assoc.trait_item_def_id)
674 .is_some() =>
675 {
676 resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason)
679 }
680 _ if tcx.sess.is_sanitizer_kcfi_enabled()
682 && tcx.is_closure_like(resolved.def_id()) =>
683 {
684 resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
688 }
689 _ => {}
690 }
691
692 resolved
693 })
694 }
695
696 pub fn expect_resolve_for_vtable(
697 tcx: TyCtxt<'tcx>,
698 typing_env: ty::TypingEnv<'tcx>,
699 def_id: DefId,
700 args: GenericArgsRef<'tcx>,
701 span: Span,
702 ) -> Instance<'tcx> {
703 debug!("resolve_for_vtable(def_id={:?}, args={:?})", def_id, args);
704 let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
705 let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
706 && fn_sig.input(0).skip_binder().is_param(0)
707 && tcx.generics_of(def_id).has_self;
708
709 if is_vtable_shim {
710 debug!(" => associated item with unsizeable self: Self");
711 return Instance { def: InstanceKind::VTableShim(def_id), args };
712 }
713
714 let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span);
715
716 let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable);
717 match resolved.def {
718 InstanceKind::Item(def) => {
719 let needs_track_caller_shim = resolved.def.requires_caller_location(tcx)
729 && !tcx.should_inherit_track_caller(def)
732 && !matches!(
738 tcx.opt_associated_item(def),
739 Some(ty::AssocItem {
740 container: ty::AssocItemContainer::Trait,
741 ..
742 })
743 );
744 if needs_track_caller_shim {
745 if tcx.is_closure_like(def) {
746 debug!(
747 " => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
748 def, def_id, args
749 );
750
751 resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args };
755 } else {
756 debug!(
757 " => vtable fn pointer created for function with #[track_caller]: {:?}",
758 def
759 );
760 resolved.def = InstanceKind::ReifyShim(def, reason);
761 }
762 }
763 }
764 InstanceKind::Virtual(def_id, _) => {
765 debug!(" => vtable fn pointer created for virtual call");
766 resolved.def = InstanceKind::ReifyShim(def_id, reason)
767 }
768 _ => {}
769 }
770
771 resolved
772 }
773
774 pub fn resolve_closure(
775 tcx: TyCtxt<'tcx>,
776 def_id: DefId,
777 args: ty::GenericArgsRef<'tcx>,
778 requested_kind: ty::ClosureKind,
779 ) -> Instance<'tcx> {
780 let actual_kind = args.as_closure().kind();
781
782 match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
783 Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args),
784 _ => Instance::new_raw(def_id, args),
785 }
786 }
787
788 pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
789 let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
790 let args = tcx.mk_args(&[ty.into()]);
791 Instance::expect_resolve(
792 tcx,
793 ty::TypingEnv::fully_monomorphized(),
794 def_id,
795 args,
796 ty.ty_adt_def().and_then(|adt| tcx.hir_span_if_local(adt.did())).unwrap_or(DUMMY_SP),
797 )
798 }
799
800 pub fn resolve_async_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
801 let def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, None);
802 let args = tcx.mk_args(&[ty.into()]);
803 Instance::expect_resolve(
804 tcx,
805 ty::TypingEnv::fully_monomorphized(),
806 def_id,
807 args,
808 ty.ty_adt_def().and_then(|adt| tcx.hir_span_if_local(adt.did())).unwrap_or(DUMMY_SP),
809 )
810 }
811
812 pub fn resolve_async_drop_in_place_poll(
813 tcx: TyCtxt<'tcx>,
814 def_id: DefId,
815 ty: Ty<'tcx>,
816 ) -> ty::Instance<'tcx> {
817 let args = tcx.mk_args(&[ty.into()]);
818 Instance::expect_resolve(tcx, ty::TypingEnv::fully_monomorphized(), def_id, args, DUMMY_SP)
819 }
820
821 #[instrument(level = "debug", skip(tcx), ret)]
822 pub fn fn_once_adapter_instance(
823 tcx: TyCtxt<'tcx>,
824 closure_did: DefId,
825 args: ty::GenericArgsRef<'tcx>,
826 ) -> Instance<'tcx> {
827 let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
828 let call_once = tcx
829 .associated_items(fn_once)
830 .in_definition_order()
831 .find(|it| it.is_fn())
832 .unwrap()
833 .def_id;
834 let track_caller =
835 tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
836 let def = ty::InstanceKind::ClosureOnceShim { call_once, track_caller };
837
838 let self_ty = Ty::new_closure(tcx, closure_did, args);
839
840 let tupled_inputs_ty = args.as_closure().sig().map_bound(|sig| sig.inputs()[0]);
841 let tupled_inputs_ty = tcx.instantiate_bound_regions_with_erased(tupled_inputs_ty);
842 let args = tcx.mk_args_trait(self_ty, [tupled_inputs_ty.into()]);
843
844 debug!(?self_ty, args=?tupled_inputs_ty.tuple_fields());
845 Instance { def, args }
846 }
847
848 pub fn try_resolve_item_for_coroutine(
849 tcx: TyCtxt<'tcx>,
850 trait_item_id: DefId,
851 trait_id: DefId,
852 rcvr_args: ty::GenericArgsRef<'tcx>,
853 ) -> Option<Instance<'tcx>> {
854 let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
855 return None;
856 };
857 let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
858
859 let coroutine_callable_item = if tcx.is_lang_item(trait_id, LangItem::Future) {
860 assert_matches!(
861 coroutine_kind,
862 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
863 );
864 hir::LangItem::FuturePoll
865 } else if tcx.is_lang_item(trait_id, LangItem::Iterator) {
866 assert_matches!(
867 coroutine_kind,
868 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
869 );
870 hir::LangItem::IteratorNext
871 } else if tcx.is_lang_item(trait_id, LangItem::AsyncIterator) {
872 assert_matches!(
873 coroutine_kind,
874 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
875 );
876 hir::LangItem::AsyncIteratorPollNext
877 } else if tcx.is_lang_item(trait_id, LangItem::Coroutine) {
878 assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
879 hir::LangItem::CoroutineResume
880 } else {
881 return None;
882 };
883
884 if tcx.is_lang_item(trait_item_id, coroutine_callable_item) {
885 if tcx.is_async_drop_in_place_coroutine(coroutine_def_id) {
886 return Some(resolve_async_drop_poll(rcvr_args.type_at(0)));
887 }
888 let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
889 else {
890 bug!()
891 };
892
893 if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() {
896 Some(Instance { def: ty::InstanceKind::Item(coroutine_def_id), args })
897 } else {
898 Some(Instance {
899 def: ty::InstanceKind::Item(
900 tcx.coroutine_by_move_body_def_id(coroutine_def_id),
901 ),
902 args,
903 })
904 }
905 } else {
906 debug_assert!(tcx.defaultness(trait_item_id).has_value());
910 Some(Instance::new_raw(trait_item_id, rcvr_args))
911 }
912 }
913
914 fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> {
925 self.def.has_polymorphic_mir_body().then_some(self.args)
926 }
927
928 pub fn instantiate_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, &T>) -> T
929 where
930 T: TypeFoldable<TyCtxt<'tcx>> + Copy,
931 {
932 let v = v.map_bound(|v| *v);
933 if let Some(args) = self.args_for_mir_body() {
934 v.instantiate(tcx, args)
935 } else {
936 v.instantiate_identity()
937 }
938 }
939
940 #[inline(always)]
941 pub fn instantiate_mir_and_normalize_erasing_regions<T>(
943 &self,
944 tcx: TyCtxt<'tcx>,
945 typing_env: ty::TypingEnv<'tcx>,
946 v: EarlyBinder<'tcx, T>,
947 ) -> T
948 where
949 T: TypeFoldable<TyCtxt<'tcx>>,
950 {
951 if let Some(args) = self.args_for_mir_body() {
952 tcx.instantiate_and_normalize_erasing_regions(args, typing_env, v)
953 } else {
954 tcx.normalize_erasing_regions(typing_env, v.instantiate_identity())
955 }
956 }
957
958 #[inline(always)]
959 pub fn try_instantiate_mir_and_normalize_erasing_regions<T>(
961 &self,
962 tcx: TyCtxt<'tcx>,
963 typing_env: ty::TypingEnv<'tcx>,
964 v: EarlyBinder<'tcx, T>,
965 ) -> Result<T, NormalizationError<'tcx>>
966 where
967 T: TypeFoldable<TyCtxt<'tcx>>,
968 {
969 if let Some(args) = self.args_for_mir_body() {
970 tcx.try_instantiate_and_normalize_erasing_regions(args, typing_env, v)
971 } else {
972 tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity())
978 }
979 }
980}
981
982fn needs_fn_once_adapter_shim(
983 actual_closure_kind: ty::ClosureKind,
984 trait_closure_kind: ty::ClosureKind,
985) -> Result<bool, ()> {
986 match (actual_closure_kind, trait_closure_kind) {
987 (ty::ClosureKind::Fn, ty::ClosureKind::Fn)
988 | (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut)
989 | (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
990 Ok(false)
992 }
993 (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
994 Ok(false)
998 }
999 (ty::ClosureKind::Fn | ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
1000 Ok(true)
1009 }
1010 (ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce, _) => Err(()),
1011 }
1012}
1013
1014#[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)]
1017pub struct UnusedGenericParams(FiniteBitSet<u32>);
1018
1019impl Default for UnusedGenericParams {
1020 fn default() -> Self {
1021 UnusedGenericParams::new_all_used()
1022 }
1023}
1024
1025impl UnusedGenericParams {
1026 pub fn new_all_unused(amount: u32) -> Self {
1027 let mut bitset = FiniteBitSet::new_empty();
1028 bitset.set_range(0..amount);
1029 Self(bitset)
1030 }
1031
1032 pub fn new_all_used() -> Self {
1033 Self(FiniteBitSet::new_empty())
1034 }
1035
1036 pub fn mark_used(&mut self, idx: u32) {
1037 self.0.clear(idx);
1038 }
1039
1040 pub fn is_unused(&self, idx: u32) -> bool {
1041 self.0.contains(idx).unwrap_or(false)
1042 }
1043
1044 pub fn is_used(&self, idx: u32) -> bool {
1045 !self.is_unused(idx)
1046 }
1047
1048 pub fn all_used(&self) -> bool {
1049 self.0.is_empty()
1050 }
1051
1052 pub fn bits(&self) -> u32 {
1053 self.0.0
1054 }
1055
1056 pub fn from_bits(bits: u32) -> UnusedGenericParams {
1057 UnusedGenericParams(FiniteBitSet(bits))
1058 }
1059}