@@ -2339,6 +2339,76 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> {
23392339 }
23402340}
23412341
2342+
2343+ impl < ' tcx > ty:: Instance < ' tcx > {
2344+ // NOTE(eddyb) this is private to avoid using it from outside of
2345+ // `FnAbi::of_instance` - any other uses are either too high-level
2346+ // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
2347+ // or should go through `FnAbi` instead, to avoid losing any
2348+ // adjustments `FnAbi::of_instance` might be performing.
2349+ fn fn_sig_for_fn_abi ( & self , tcx : TyCtxt < ' tcx > ) -> ty:: PolyFnSig < ' tcx > {
2350+ let ty = self . ty ( tcx) ;
2351+ match ty. kind {
2352+ ty:: FnDef ( ..) |
2353+ // Shims currently have type FnPtr. Not sure this should remain.
2354+ ty:: FnPtr ( _) => {
2355+ let mut sig = ty. fn_sig ( tcx) ;
2356+ if let ty:: InstanceDef :: VtableShim ( ..) = self . def {
2357+ // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
2358+ sig = sig. map_bound ( |mut sig| {
2359+ let mut inputs_and_output = sig. inputs_and_output . to_vec ( ) ;
2360+ inputs_and_output[ 0 ] = tcx. mk_mut_ptr ( inputs_and_output[ 0 ] ) ;
2361+ sig. inputs_and_output = tcx. intern_type_list ( & inputs_and_output) ;
2362+ sig
2363+ } ) ;
2364+ }
2365+ sig
2366+ }
2367+ ty:: Closure ( def_id, substs) => {
2368+ let sig = substs. as_closure ( ) . sig ( def_id, tcx) ;
2369+
2370+ let env_ty = tcx. closure_env_ty ( def_id, substs) . unwrap ( ) ;
2371+ sig. map_bound ( |sig| tcx. mk_fn_sig (
2372+ iter:: once ( * env_ty. skip_binder ( ) ) . chain ( sig. inputs ( ) . iter ( ) . cloned ( ) ) ,
2373+ sig. output ( ) ,
2374+ sig. c_variadic ,
2375+ sig. unsafety ,
2376+ sig. abi
2377+ ) )
2378+ }
2379+ ty:: Generator ( def_id, substs, _) => {
2380+ let sig = substs. as_generator ( ) . poly_sig ( def_id, tcx) ;
2381+
2382+ let env_region = ty:: ReLateBound ( ty:: INNERMOST , ty:: BrEnv ) ;
2383+ let env_ty = tcx. mk_mut_ref ( tcx. mk_region ( env_region) , ty) ;
2384+
2385+ let pin_did = tcx. lang_items ( ) . pin_type ( ) . unwrap ( ) ;
2386+ let pin_adt_ref = tcx. adt_def ( pin_did) ;
2387+ let pin_substs = tcx. intern_substs ( & [ env_ty. into ( ) ] ) ;
2388+ let env_ty = tcx. mk_adt ( pin_adt_ref, pin_substs) ;
2389+
2390+ sig. map_bound ( |sig| {
2391+ let state_did = tcx. lang_items ( ) . gen_state ( ) . unwrap ( ) ;
2392+ let state_adt_ref = tcx. adt_def ( state_did) ;
2393+ let state_substs = tcx. intern_substs ( & [
2394+ sig. yield_ty . into ( ) ,
2395+ sig. return_ty . into ( ) ,
2396+ ] ) ;
2397+ let ret_ty = tcx. mk_adt ( state_adt_ref, state_substs) ;
2398+
2399+ tcx. mk_fn_sig ( iter:: once ( env_ty) ,
2400+ ret_ty,
2401+ false ,
2402+ hir:: Unsafety :: Normal ,
2403+ rustc_target:: spec:: abi:: Abi :: Rust
2404+ )
2405+ } )
2406+ }
2407+ _ => bug ! ( "unexpected type {:?} in Instance::fn_sig" , ty)
2408+ }
2409+ }
2410+ }
2411+
23422412pub trait FnAbiExt < ' tcx , C >
23432413where
23442414 C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
@@ -2347,12 +2417,22 @@ where
23472417 + HasTyCtxt < ' tcx >
23482418 + HasParamEnv < ' tcx > ,
23492419{
2350- fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > ) -> Self ;
2351- fn new ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self ;
2352- fn new_vtable ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self ;
2420+ /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
2421+ ///
2422+ /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance`
2423+ /// instead, where the instance is a `InstanceDef::Virtual`.
2424+ fn of_fn_ptr ( cx : & C , sig : ty:: PolyFnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self ;
2425+
2426+ /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
2427+ /// direct calls to an `fn`.
2428+ ///
2429+ /// NB: that includes virtual calls, which are represented by "direct calls"
2430+ /// to a `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
2431+ fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self ;
2432+
23532433 fn new_internal (
23542434 cx : & C ,
2355- sig : ty:: FnSig < ' tcx > ,
2435+ sig : ty:: PolyFnSig < ' tcx > ,
23562436 extra_args : & [ Ty < ' tcx > ] ,
23572437 mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
23582438 ) -> Self ;
@@ -2367,25 +2447,19 @@ where
23672447 + HasTyCtxt < ' tcx >
23682448 + HasParamEnv < ' tcx > ,
23692449{
2370- fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > ) -> Self {
2371- let sig = instance. fn_sig ( cx. tcx ( ) ) ;
2372- let sig = cx
2373- . tcx ( )
2374- . normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , & sig) ;
2375- call:: FnAbi :: new ( cx, sig, & [ ] )
2376- }
2377-
2378- fn new ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
2450+ fn of_fn_ptr ( cx : & C , sig : ty:: PolyFnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
23792451 call:: FnAbi :: new_internal ( cx, sig, extra_args, |ty, _| ArgAbi :: new ( cx. layout_of ( ty) ) )
23802452 }
23812453
2382- fn new_vtable ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
2383- FnAbiExt :: new_internal ( cx, sig, extra_args, |ty, arg_idx| {
2454+ fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
2455+ let sig = instance. fn_sig_for_fn_abi ( cx. tcx ( ) ) ;
2456+
2457+ call:: FnAbi :: new_internal ( cx, sig, extra_args, |ty, arg_idx| {
23842458 let mut layout = cx. layout_of ( ty) ;
23852459 // Don't pass the vtable, it's not an argument of the virtual fn.
23862460 // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
23872461 // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
2388- if arg_idx == Some ( 0 ) {
2462+ if let ( ty :: InstanceDef :: Virtual ( .. ) , Some ( 0 ) ) = ( & instance . def , arg_idx ) {
23892463 let fat_pointer_ty = if layout. is_unsized ( ) {
23902464 // unsized `self` is passed as a pointer to `self`
23912465 // FIXME (mikeyhew) change this to use &own if it is ever added to the language
@@ -2436,15 +2510,19 @@ where
24362510
24372511 fn new_internal (
24382512 cx : & C ,
2439- sig : ty:: FnSig < ' tcx > ,
2513+ sig : ty:: PolyFnSig < ' tcx > ,
24402514 extra_args : & [ Ty < ' tcx > ] ,
24412515 mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
24422516 ) -> Self {
24432517 debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
24442518
2519+ let sig = cx
2520+ . tcx ( )
2521+ . normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , & sig) ;
2522+
24452523 use rustc_target:: spec:: abi:: Abi :: * ;
24462524 let conv = match cx. tcx ( ) . sess . target . target . adjust_abi ( sig. abi ) {
2447- RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv :: C ,
2525+ RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv :: Rust ,
24482526
24492527 // It's the ABI's job to select this, not ours.
24502528 System => bug ! ( "system abi should be selected elsewhere" ) ,
0 commit comments