@@ -72,6 +72,21 @@ pub enum AllocKind {
7272 Dead ,
7373}
7474
75+ /// Metadata about an `AllocId`.
76+ #[ derive( Copy , Clone , PartialEq , Debug ) ]
77+ pub struct AllocInfo {
78+ pub size : Size ,
79+ pub align : Align ,
80+ pub kind : AllocKind ,
81+ pub mutbl : Mutability ,
82+ }
83+
84+ impl AllocInfo {
85+ fn new ( size : Size , align : Align , kind : AllocKind , mutbl : Mutability ) -> Self {
86+ Self { size, align, kind, mutbl }
87+ }
88+ }
89+
7590/// The value of a function pointer.
7691#[ derive( Debug , Copy , Clone ) ]
7792pub enum FnVal < ' tcx , Other > {
@@ -524,17 +539,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
524539 match self . ptr_try_get_alloc_id ( ptr, 0 ) {
525540 Err ( addr) => is_offset_misaligned ( addr, align) ,
526541 Ok ( ( alloc_id, offset, _prov) ) => {
527- let ( _size, alloc_align, kind, _mutbl) = self . get_alloc_info ( alloc_id) ;
528- if let Some ( misalign) =
529- M :: alignment_check ( self , alloc_id, alloc_align, kind, offset, align)
530- {
542+ let alloc_info = self . get_alloc_info ( alloc_id) ;
543+ if let Some ( misalign) = M :: alignment_check (
544+ self ,
545+ alloc_id,
546+ alloc_info. align ,
547+ alloc_info. kind ,
548+ offset,
549+ align,
550+ ) {
531551 Some ( misalign)
532552 } else if M :: Provenance :: OFFSET_IS_ADDR {
533553 is_offset_misaligned ( ptr. addr ( ) . bytes ( ) , align)
534554 } else {
535555 // Check allocation alignment and offset alignment.
536- if alloc_align . bytes ( ) < align. bytes ( ) {
537- Some ( Misalignment { has : alloc_align , required : align } )
556+ if alloc_info . align . bytes ( ) < align. bytes ( ) {
557+ Some ( Misalignment { has : alloc_info . align , required : align } )
538558 } else {
539559 is_offset_misaligned ( offset. bytes ( ) , align)
540560 }
@@ -818,19 +838,24 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
818838
819839 /// Obtain the size and alignment of an allocation, even if that allocation has
820840 /// been deallocated.
821- pub fn get_alloc_info ( & self , id : AllocId ) -> ( Size , Align , AllocKind , Mutability ) {
841+ pub fn get_alloc_info ( & self , id : AllocId ) -> AllocInfo {
822842 // # Regular allocations
823843 // Don't use `self.get_raw` here as that will
824844 // a) cause cycles in case `id` refers to a static
825845 // b) duplicate a global's allocation in miri
826846 if let Some ( ( _, alloc) ) = self . memory . alloc_map . get ( id) {
827- return ( alloc. size ( ) , alloc. align , AllocKind :: LiveData , alloc. mutability ) ;
847+ return AllocInfo :: new (
848+ alloc. size ( ) ,
849+ alloc. align ,
850+ AllocKind :: LiveData ,
851+ alloc. mutability ,
852+ ) ;
828853 }
829854
830855 // # Function pointers
831856 // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
832857 if self . get_fn_alloc ( id) . is_some ( ) {
833- return ( Size :: ZERO , Align :: ONE , AllocKind :: Function , Mutability :: Not ) ;
858+ return AllocInfo :: new ( Size :: ZERO , Align :: ONE , AllocKind :: Function , Mutability :: Not ) ;
834859 }
835860
836861 // # Statics
@@ -852,7 +877,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
852877 // succeeds, as the query is fed at DefId creation time, so no
853878 // evaluation actually occurs.
854879 let alloc = self . tcx . eval_static_initializer ( def_id) . unwrap ( ) ;
855- ( alloc. 0 . size ( ) , alloc. 0 . align , alloc. 0 . mutability )
880+ // Nested statics in a `static` are never interior mutable, so just use the
881+ // declared mutability, which should be equal to the allocation's mutability.
882+ assert_eq ! ( mutability, alloc. 0 . mutability) ;
883+ ( alloc. 0 . size ( ) , alloc. 0 . align , mutability)
856884 } else {
857885 // Use size and align of the type for everything else. We need
858886 // to do that to
@@ -873,20 +901,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
873901 } ;
874902 ( layout. size , layout. align . abi , mutability)
875903 } ;
876- ( size, align, AllocKind :: LiveData , mutability)
904+ AllocInfo :: new ( size, align, AllocKind :: LiveData , mutability)
877905 }
878906 Some ( GlobalAlloc :: Memory ( alloc) ) => {
879907 // Need to duplicate the logic here, because the global allocations have
880908 // different associated types than the interpreter-local ones.
881909 let alloc = alloc. inner ( ) ;
882- ( alloc. size ( ) , alloc. align , AllocKind :: LiveData , alloc. mutability )
910+ AllocInfo :: new ( alloc. size ( ) , alloc. align , AllocKind :: LiveData , alloc. mutability )
883911 }
884912 Some ( GlobalAlloc :: Function { .. } ) => {
885913 bug ! ( "We already checked function pointers above" )
886914 }
887915 Some ( GlobalAlloc :: VTable ( ..) ) => {
888916 // No data to be accessed here. But vtables are pointer-aligned.
889- return (
917+ return AllocInfo :: new (
890918 Size :: ZERO ,
891919 self . tcx . data_layout . pointer_align . abi ,
892920 AllocKind :: VTable ,
@@ -902,7 +930,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
902930 . dead_alloc_map
903931 . get ( & id)
904932 . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) ;
905- ( size, align, AllocKind :: Dead , Mutability :: Not )
933+ AllocInfo :: new ( size, align, AllocKind :: Dead , Mutability :: Not )
906934 }
907935 }
908936 }
@@ -913,11 +941,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
913941 id : AllocId ,
914942 msg : CheckInAllocMsg ,
915943 ) -> InterpResult < ' tcx , ( Size , Align ) > {
916- let ( size , align , kind , _mutbl ) = self . get_alloc_info ( id) ;
917- if matches ! ( kind, AllocKind :: Dead ) {
944+ let info = self . get_alloc_info ( id) ;
945+ if matches ! ( info . kind, AllocKind :: Dead ) {
918946 throw_ub ! ( PointerUseAfterFree ( id, msg) )
919947 }
920- interp_ok ( ( size, align) )
948+ interp_ok ( ( info . size , info . align ) )
921949 }
922950
923951 fn get_fn_alloc ( & self , id : AllocId ) -> Option < FnVal < ' tcx , M :: ExtraFnVal > > {
@@ -1469,7 +1497,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
14691497 let ptr = scalar. to_pointer ( self ) ?;
14701498 match self . ptr_try_get_alloc_id ( ptr, 0 ) {
14711499 Ok ( ( alloc_id, offset, _) ) => {
1472- let ( size, _align , _kind , _mutbl ) = self . get_alloc_info ( alloc_id) ;
1500+ let size = self . get_alloc_info ( alloc_id) . size ;
14731501 // If the pointer is out-of-bounds, it may be null.
14741502 // Note that one-past-the-end (offset == size) is still inbounds, and never null.
14751503 offset > size
0 commit comments