@@ -407,25 +407,41 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
407
407
}
408
408
// cannot use the shim here, because that will only result in infinite recursion
409
409
ty:: InstanceDef :: Virtual ( _, idx) => {
410
+ let mut args = args. to_vec ( ) ;
410
411
let ptr_size = self . pointer_size ( ) ;
411
- let ptr = self . deref_operand ( args[ 0 ] ) ?;
412
- let vtable = ptr. vtable ( ) ?;
412
+ // We have to implement all "object safe receivers". Currently we
413
+ // support built-in pointers (&, &mut, Box) as well as unsized-self. We do
414
+ // not yet support custom self types.
415
+ // Also see librustc_codegen_llvm/abi.rs and librustc_codegen_llvm/mir/block.rs.
416
+ let receiver_place = match args[ 0 ] . layout . ty . builtin_deref ( true ) {
417
+ Some ( _) => {
418
+ // Built-in pointer.
419
+ self . deref_operand ( args[ 0 ] ) ?
420
+ }
421
+ None => {
422
+ // Unsized self.
423
+ args[ 0 ] . to_mem_place ( )
424
+ }
425
+ } ;
426
+ // Find and consult vtable
427
+ let vtable = receiver_place. vtable ( ) ?;
413
428
self . memory . check_align ( vtable. into ( ) , self . tcx . data_layout . pointer_align . abi ) ?;
414
429
let fn_ptr = self . memory . get ( vtable. alloc_id ) ?. read_ptr_sized (
415
430
self ,
416
431
vtable. offset ( ptr_size * ( idx as u64 + 3 ) , self ) ?,
417
432
) ?. to_ptr ( ) ?;
418
433
let instance = self . memory . get_fn ( fn_ptr) ?;
419
434
420
- // We have to patch the self argument, in particular get the layout
421
- // expected by the actual function. Cannot just use "field 0" due to
422
- // Box<self>.
423
- let mut args = args. to_vec ( ) ;
424
- let pointee = args[ 0 ] . layout . ty . builtin_deref ( true ) . unwrap ( ) . ty ;
425
- let fake_fat_ptr_ty = self . tcx . mk_mut_ptr ( pointee) ;
426
- args[ 0 ] = OpTy :: from ( ImmTy { // strip vtable
427
- layout : self . layout_of ( fake_fat_ptr_ty) ?. field ( self , 0 ) ?,
428
- imm : Immediate :: Scalar ( ptr. ptr . into ( ) )
435
+ // `*mut receiver_place.layout.ty` is almost the layout that we
436
+ // want for args[0]: We have to project to field 0 because we want
437
+ // a thin pointer.
438
+ assert ! ( receiver_place. layout. is_unsized( ) ) ;
439
+ let receiver_ptr_ty = self . tcx . mk_mut_ptr ( receiver_place. layout . ty ) ;
440
+ let this_receiver_ptr = self . layout_of ( receiver_ptr_ty) ?. field ( self , 0 ) ?;
441
+ // Adjust receiver argument.
442
+ args[ 0 ] = OpTy :: from ( ImmTy {
443
+ layout : this_receiver_ptr,
444
+ imm : Immediate :: Scalar ( receiver_place. ptr . into ( ) )
429
445
} ) ;
430
446
trace ! ( "Patched self operand to {:#?}" , args[ 0 ] ) ;
431
447
// recurse with concrete function
0 commit comments