@@ -771,11 +771,25 @@ where
771771 } ) ;
772772 }
773773
774- let mk_dyn_vtable = || {
774+ let mk_dyn_vtable = |principal : Option < ty:: PolyExistentialTraitRef < ' tcx > > | {
775+ let min_count = TyCtxt :: COMMON_VTABLE_ENTRIES . len ( )
776+ // As the comment below notes, it's hard to get access to supertraits
777+ // here. Supertraits currently are determined by resolving predicates.
778+ // It's not clear that it's easy to do that here. So, for now, we're
779+ // just increasing the vtable size by the local, direct vtable entries.
780+ // We know that *at least* that many pointers will be needed,
781+ // which is already a win for some cases. As an example, this lets LLVM
782+ // better hoist vtable loads out of loops for calls to `&mut dyn FnMut`
783+ // function arguments.
784+ + principal
785+ . map ( |principal| {
786+ tcx. own_existential_vtable_entries ( principal. def_id ( ) ) . len ( )
787+ } )
788+ . unwrap_or ( 0 ) ;
775789 Ty :: new_imm_ref (
776790 tcx,
777791 tcx. lifetimes . re_static ,
778- Ty :: new_array ( tcx, tcx. types . usize , 3 ) ,
792+ Ty :: new_array ( tcx, tcx. types . usize , min_count . try_into ( ) . unwrap ( ) ) ,
779793 )
780794 /* FIXME: use actual fn pointers
781795 Warning: naively computing the number of entries in the
@@ -808,16 +822,16 @@ where
808822 // `std::mem::uninitialized::<&dyn Trait>()`, for example.
809823 if let ty:: Adt ( def, args) = metadata. kind ( )
810824 && Some ( def. did ( ) ) == tcx. lang_items ( ) . dyn_metadata ( )
811- && args. type_at ( 0 ) . is_trait ( )
825+ && let ty :: Dynamic ( data , _ , ty :: Dyn ) = args. type_at ( 0 ) . kind ( )
812826 {
813- mk_dyn_vtable ( )
827+ mk_dyn_vtable ( data . principal ( ) )
814828 } else {
815829 metadata
816830 }
817831 } else {
818832 match tcx. struct_tail_erasing_lifetimes ( pointee, cx. param_env ( ) ) . kind ( ) {
819833 ty:: Slice ( _) | ty:: Str => tcx. types . usize ,
820- ty:: Dynamic ( _ , _, ty:: Dyn ) => mk_dyn_vtable ( ) ,
834+ ty:: Dynamic ( data , _, ty:: Dyn ) => mk_dyn_vtable ( data . principal ( ) ) ,
821835 _ => bug ! ( "TyAndLayout::field({:?}): not applicable" , this) ,
822836 }
823837 } ;
0 commit comments