@@ -938,7 +938,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
938
938
// that is understood elsewhere in the compiler as a method on
939
939
// `dyn Trait`.
940
940
// To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until
941
- // we get a value of a built-in pointer type
941
+ // we get a value of a built-in pointer type.
942
+ //
943
+ // This is also relevant for `Pin<&mut Self>`, where we need to peel the `Pin`.
942
944
' descend_newtypes: while !op. layout . ty . is_unsafe_ptr ( )
943
945
&& !op. layout . ty . is_region_ptr ( )
944
946
{
@@ -980,13 +982,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
980
982
continue ;
981
983
}
982
984
Immediate ( _) => {
983
- let ty:: Ref ( _, ty, _) = op. layout . ty . kind ( ) else {
984
- span_bug ! ( span, "can't codegen a virtual call on {:#?}" , op) ;
985
- } ;
986
- if !ty. is_dyn_star ( ) {
985
+ // See comment above explaining why we peel these newtypes
986
+ ' descend_newtypes: while !op. layout . ty . is_unsafe_ptr ( )
987
+ && !op. layout . ty . is_region_ptr ( )
988
+ {
989
+ for i in 0 ..op. layout . fields . count ( ) {
990
+ let field = op. extract_field ( bx, i) ;
991
+ if !field. layout . is_zst ( ) {
992
+ // we found the one non-zero-sized field that is allowed
993
+ // now find *its* non-zero-sized field, or stop if it's a
994
+ // pointer
995
+ op = field;
996
+ continue ' descend_newtypes;
997
+ }
998
+ }
999
+
1000
+ span_bug ! ( span, "receiver has no non-zero-sized fields {:?}" , op) ;
1001
+ }
1002
+
1003
+ // Make sure that we've actually unwrapped the rcvr down
1004
+ // to a pointer or ref to `dyn* Trait`.
1005
+ if !op. layout . ty . builtin_deref ( true ) . unwrap ( ) . ty . is_dyn_star ( ) {
987
1006
span_bug ! ( span, "can't codegen a virtual call on {:#?}" , op) ;
988
1007
}
989
- // FIXME(dyn-star): Make sure this is done on a &dyn* receiver
990
1008
let place = op. deref ( bx. cx ( ) ) ;
991
1009
let data_ptr = place. project_field ( bx, 0 ) ;
992
1010
let meta_ptr = place. project_field ( bx, 1 ) ;
0 commit comments