@@ -2339,6 +2339,76 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> {
2339
2339
}
2340
2340
}
2341
2341
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
+
2342
2412
pub trait FnAbiExt < ' tcx , C >
2343
2413
where
2344
2414
C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
@@ -2347,12 +2417,22 @@ where
2347
2417
+ HasTyCtxt < ' tcx >
2348
2418
+ HasParamEnv < ' tcx > ,
2349
2419
{
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
+
2353
2433
fn new_internal (
2354
2434
cx : & C ,
2355
- sig : ty:: FnSig < ' tcx > ,
2435
+ sig : ty:: PolyFnSig < ' tcx > ,
2356
2436
extra_args : & [ Ty < ' tcx > ] ,
2357
2437
mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
2358
2438
) -> Self ;
@@ -2367,25 +2447,19 @@ where
2367
2447
+ HasTyCtxt < ' tcx >
2368
2448
+ HasParamEnv < ' tcx > ,
2369
2449
{
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 {
2379
2451
call:: FnAbi :: new_internal ( cx, sig, extra_args, |ty, _| ArgAbi :: new ( cx. layout_of ( ty) ) )
2380
2452
}
2381
2453
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| {
2384
2458
let mut layout = cx. layout_of ( ty) ;
2385
2459
// Don't pass the vtable, it's not an argument of the virtual fn.
2386
2460
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
2387
2461
// 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 ) {
2389
2463
let fat_pointer_ty = if layout. is_unsized ( ) {
2390
2464
// unsized `self` is passed as a pointer to `self`
2391
2465
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
@@ -2436,15 +2510,19 @@ where
2436
2510
2437
2511
fn new_internal (
2438
2512
cx : & C ,
2439
- sig : ty:: FnSig < ' tcx > ,
2513
+ sig : ty:: PolyFnSig < ' tcx > ,
2440
2514
extra_args : & [ Ty < ' tcx > ] ,
2441
2515
mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
2442
2516
) -> Self {
2443
2517
debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
2444
2518
2519
+ let sig = cx
2520
+ . tcx ( )
2521
+ . normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , & sig) ;
2522
+
2445
2523
use rustc_target:: spec:: abi:: Abi :: * ;
2446
2524
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 ,
2448
2526
2449
2527
// It's the ABI's job to select this, not ours.
2450
2528
System => bug ! ( "system abi should be selected elsewhere" ) ,
0 commit comments