@@ -535,40 +535,41 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
535535 id : AllocId ,
536536 liveness : AllocCheck ,
537537 ) -> InterpResult < ' static , ( Size , Align ) > {
538- // Allocations of `static` items
539- // Can't do this in the match argument, we may get cycle errors since the lock would
540- // be held throughout the match.
541- let alloc = self . tcx . alloc_map . lock ( ) . get ( id) ;
542- match alloc {
543- Some ( GlobalAlloc :: Static ( did) ) => {
544- // Use size and align of the type
545- let ty = self . tcx . type_of ( did) ;
546- let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
547- return Ok ( ( layout. size , layout. align . abi ) ) ;
548- }
549- _ => { }
550- }
551- // Regular allocations.
552- if let Ok ( alloc) = self . get ( id) {
553- return Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ;
554- }
555- // Function pointers.
556- if let Ok ( _) = self . get_fn_alloc ( id) {
557- return if let AllocCheck :: Dereferencable = liveness {
558- // The caller requested no function pointers.
559- err ! ( DerefFunctionPointer )
560- } else {
561- Ok ( ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) )
562- } ;
563- }
564- // The rest must be dead.
565- if let AllocCheck :: MaybeDead = liveness {
566- // Deallocated pointers are allowed, we should be able to find
567- // them in the map.
568- Ok ( * self . dead_alloc_map . get ( & id)
569- . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) )
570- } else {
571- err ! ( DanglingPointerDeref )
538+ let alloc_or_size_align = self . alloc_map . get_or ( id, || -> Result < _ , InterpResult < ' static , ( Size , Align ) > > {
539+ // Can't do this in the match argument, we may get cycle errors since the lock would
540+ // be held throughout the match.
541+ let alloc = self . tcx . alloc_map . lock ( ) . get ( id) ;
542+ Err ( match alloc {
543+ Some ( GlobalAlloc :: Static ( did) ) => {
544+ // Use size and align of the type
545+ let ty = self . tcx . type_of ( did) ;
546+ let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
547+ Ok ( ( layout. size , layout. align . abi ) )
548+ } ,
549+ Some ( GlobalAlloc :: Memory ( alloc) ) =>
550+ // this duplicates the logic on the `match alloc_or_size_align`, but due to the
551+ // API of `get_or` there's no way around that.
552+ Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ,
553+ Some ( GlobalAlloc :: Function ( _) ) => if let AllocCheck :: Dereferencable = liveness {
554+ // The caller requested no function pointers.
555+ err ! ( DerefFunctionPointer )
556+ } else {
557+ Ok ( ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) )
558+ } ,
559+ // The rest must be dead.
560+ None => if let AllocCheck :: MaybeDead = liveness {
561+ // Deallocated pointers are allowed, we should be able to find
562+ // them in the map.
563+ Ok ( * self . dead_alloc_map . get ( & id)
564+ . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) )
565+ } else {
566+ err ! ( DanglingPointerDeref )
567+ } ,
568+ } )
569+ } ) ;
570+ match alloc_or_size_align {
571+ Ok ( ( _, alloc) ) => Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ,
572+ Err ( done) => done,
572573 }
573574 }
574575
0 commit comments