11use crate :: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
22use crate :: ty:: print:: { FmtPrinter , Printer } ;
33use crate :: ty:: { self , Ty , TyCtxt , TypeFoldable , TypeSuperFoldable } ;
4- use crate :: ty:: { EarlyBinder , GenericArgs , GenericArgsRef , TypeVisitableExt } ;
4+ use crate :: ty:: { EarlyBinder , GenericArgs , GenericArgsRef , Lift , TypeVisitableExt } ;
55use rustc_errors:: ErrorGuaranteed ;
66use rustc_hir as hir;
77use rustc_hir:: def:: Namespace ;
@@ -135,6 +135,14 @@ pub enum InstanceDef<'tcx> {
135135 ///
136136 /// The `DefId` is for `FnPtr::addr`, the `Ty` is the type `T`.
137137 FnPtrAddrShim ( DefId , Ty < ' tcx > ) ,
138+
139+ /// Typecast shim which replaces the `Self` type with the provided type.
140+ /// This is used in vtable calls, where the type of `Self` is abstract as of the time of
141+ /// the call.
142+ ///
143+ /// `target_instance` will be an instantiable `InstanceDef`, either an `Item` for which
144+ /// we have MIR available or a generatable shim.
145+ CfiShim { target_instance : & ' tcx InstanceDef < ' tcx > , invoke_ty : Ty < ' tcx > } ,
138146}
139147
140148impl < ' tcx > Instance < ' tcx > {
@@ -198,6 +206,7 @@ impl<'tcx> InstanceDef<'tcx> {
198206 | InstanceDef :: DropGlue ( def_id, _)
199207 | InstanceDef :: CloneShim ( def_id, _)
200208 | InstanceDef :: FnPtrAddrShim ( def_id, _) => def_id,
209+ InstanceDef :: CfiShim { target_instance, .. } => target_instance. def_id ( ) ,
201210 }
202211 }
203212
@@ -209,6 +218,7 @@ impl<'tcx> InstanceDef<'tcx> {
209218 Some ( def_id)
210219 }
211220 InstanceDef :: VTableShim ( ..)
221+ | InstanceDef :: CfiShim { .. }
212222 | InstanceDef :: ReifyShim ( ..)
213223 | InstanceDef :: FnPtrShim ( ..)
214224 | InstanceDef :: Virtual ( ..)
@@ -319,6 +329,17 @@ impl<'tcx> InstanceDef<'tcx> {
319329 | InstanceDef :: ReifyShim ( ..)
320330 | InstanceDef :: Virtual ( ..)
321331 | InstanceDef :: VTableShim ( ..) => true ,
332+ InstanceDef :: CfiShim { target_instance, .. } => {
333+ target_instance. has_polymorphic_mir_body ( )
334+ }
335+ }
336+ }
337+
338+ pub fn is_vtable_shim ( & self ) -> bool {
339+ match self {
340+ InstanceDef :: VTableShim ( ..) => true ,
341+ InstanceDef :: CfiShim { target_instance, .. } => target_instance. is_vtable_shim ( ) ,
342+ _ => false ,
322343 }
323344 }
324345}
@@ -339,6 +360,10 @@ fn fmt_instance_def(f: &mut fmt::Formatter<'_>, instance_def: &InstanceDef<'_>)
339360 InstanceDef :: DropGlue ( _, Some ( ty) ) => write ! ( f, " - shim(Some({ty}))" ) ,
340361 InstanceDef :: CloneShim ( _, ty) => write ! ( f, " - shim({ty})" ) ,
341362 InstanceDef :: FnPtrAddrShim ( _, ty) => write ! ( f, " - shim({ty})" ) ,
363+ InstanceDef :: CfiShim { invoke_ty, target_instance } => {
364+ fmt_instance_def ( f, target_instance) ?;
365+ write ! ( f, " - cfi-shim({invoke_ty})" )
366+ }
342367 }
343368}
344369
@@ -579,6 +604,34 @@ impl<'tcx> Instance<'tcx> {
579604 Instance :: expect_resolve ( tcx, ty:: ParamEnv :: reveal_all ( ) , def_id, args)
580605 }
581606
607+ pub fn cfi_shim (
608+ mut self ,
609+ tcx : TyCtxt < ' tcx > ,
610+ invoke_trait : Option < ty:: PolyTraitRef < ' tcx > > ,
611+ ) -> ty:: Instance < ' tcx > {
612+ if tcx. sess . cfi_shims ( ) {
613+ let invoke_ty = if let Some ( poly_trait_ref) = invoke_trait {
614+ tcx. trait_object_ty ( poly_trait_ref)
615+ } else {
616+ Ty :: new_dynamic ( tcx, ty:: List :: empty ( ) , tcx. lifetimes . re_erased , ty:: Dyn )
617+ } ;
618+ // If we're an Item and the `def_id` is not local, we may not have MIR available.
619+ // If it's a closure, we can't ReifyShim it, just use it directly.
620+ if let InstanceDef :: Item ( def_id) = self . def
621+ && !def_id. is_local ( )
622+ && !tcx. is_closure_like ( def_id)
623+ {
624+ self . def = InstanceDef :: ReifyShim ( def_id) ;
625+ }
626+
627+ self . def = InstanceDef :: CfiShim {
628+ target_instance : ( & self . def ) . lift_to_tcx ( tcx) . expect ( "Could not lift for shimming" ) ,
629+ invoke_ty,
630+ } ;
631+ }
632+ self
633+ }
634+
582635 #[ instrument( level = "debug" , skip( tcx) , ret) ]
583636 pub fn fn_once_adapter_instance (
584637 tcx : TyCtxt < ' tcx > ,
0 commit comments