@@ -20,6 +20,45 @@ use super::{
2020 RawConst , Scalar , ScalarMaybeUndef ,
2121} ;
2222
23+ #[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq , HashStable ) ]
24+ pub enum MemPlaceMeta < Tag = ( ) , Id = AllocId > {
25+ Unsized ( Scalar < Tag , Id > ) ,
26+ /// `Sized` types or unsized `extern type`
27+ None ,
28+ /// The address of this place may not be taken. This protects the `MemPlace` from coming from
29+ /// a ZST Operand with a backing allocation and being converted to an integer address. This
30+ /// should be impossible, because you can't take the address of an operand, but this is a second
31+ /// protection layer ensuring that we don't mess up.
32+ Poison ,
33+ }
34+
35+ impl < Tag , Id > MemPlaceMeta < Tag , Id > {
36+ pub fn unwrap_unsized ( self ) -> Scalar < Tag , Id > {
37+ match self {
38+ Self :: Unsized ( s) => s,
39+ Self :: None | Self :: Poison => {
40+ bug ! ( "expected wide pointer extra data (e.g. slice length or trait object vtable)" )
41+ }
42+ }
43+ }
44+ fn is_unsized ( self ) -> bool {
45+ match self {
46+ Self :: Unsized ( _) => true ,
47+ Self :: None | Self :: Poison => false ,
48+ }
49+ }
50+ }
51+
52+ impl < Tag > MemPlaceMeta < Tag > {
53+ pub fn erase_tag ( self ) -> MemPlaceMeta < ( ) > {
54+ match self {
55+ Self :: Unsized ( s) => MemPlaceMeta :: Unsized ( s. erase_tag ( ) ) ,
56+ Self :: None => MemPlaceMeta :: None ,
57+ Self :: Poison => MemPlaceMeta :: Poison ,
58+ }
59+ }
60+ }
61+
2362#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq , HashStable ) ]
2463pub struct MemPlace < Tag = ( ) , Id = AllocId > {
2564 /// A place may have an integral pointer for ZSTs, and since it might
@@ -30,7 +69,7 @@ pub struct MemPlace<Tag = (), Id = AllocId> {
3069 /// Metadata for unsized places. Interpretation is up to the type.
3170 /// Must not be present for sized types, but can be missing for unsized types
3271 /// (e.g., `extern type`).
33- pub meta : Option < Scalar < Tag , Id > > ,
72+ pub meta : MemPlaceMeta < Tag , Id > ,
3473}
3574
3675#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq , HashStable ) ]
@@ -88,16 +127,12 @@ impl<Tag> MemPlace<Tag> {
88127
89128 #[ inline]
90129 pub fn erase_tag ( self ) -> MemPlace {
91- MemPlace {
92- ptr : self . ptr . erase_tag ( ) ,
93- align : self . align ,
94- meta : self . meta . map ( Scalar :: erase_tag) ,
95- }
130+ MemPlace { ptr : self . ptr . erase_tag ( ) , align : self . align , meta : self . meta . erase_tag ( ) }
96131 }
97132
98133 #[ inline( always) ]
99134 pub fn from_scalar_ptr ( ptr : Scalar < Tag > , align : Align ) -> Self {
100- MemPlace { ptr, align, meta : None }
135+ MemPlace { ptr, align, meta : MemPlaceMeta :: None }
101136 }
102137
103138 /// Produces a Place that will error if attempted to be read from or written to
@@ -116,15 +151,19 @@ impl<Tag> MemPlace<Tag> {
116151 #[ inline( always) ]
117152 pub fn to_ref ( self ) -> Immediate < Tag > {
118153 match self . meta {
119- None => Immediate :: Scalar ( self . ptr . into ( ) ) ,
120- Some ( meta) => Immediate :: ScalarPair ( self . ptr . into ( ) , meta. into ( ) ) ,
154+ MemPlaceMeta :: None => Immediate :: Scalar ( self . ptr . into ( ) ) ,
155+ MemPlaceMeta :: Unsized ( meta) => Immediate :: ScalarPair ( self . ptr . into ( ) , meta. into ( ) ) ,
156+ MemPlaceMeta :: Poison => bug ! (
157+ "MPlaceTy::dangling may never be used to produce a \
158+ place that will have the address of its pointee taken"
159+ ) ,
121160 }
122161 }
123162
124163 pub fn offset (
125164 self ,
126165 offset : Size ,
127- meta : Option < Scalar < Tag > > ,
166+ meta : MemPlaceMeta < Tag > ,
128167 cx : & impl HasDataLayout ,
129168 ) -> InterpResult < ' tcx , Self > {
130169 Ok ( MemPlace {
@@ -158,7 +197,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
158197 pub fn offset (
159198 self ,
160199 offset : Size ,
161- meta : Option < Scalar < Tag > > ,
200+ meta : MemPlaceMeta < Tag > ,
162201 layout : TyLayout < ' tcx > ,
163202 cx : & impl HasDataLayout ,
164203 ) -> InterpResult < ' tcx , Self > {
@@ -175,7 +214,9 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
175214 if self . layout . is_unsized ( ) {
176215 // We need to consult `meta` metadata
177216 match self . layout . ty . kind {
178- ty:: Slice ( ..) | ty:: Str => return self . mplace . meta . unwrap ( ) . to_machine_usize ( cx) ,
217+ ty:: Slice ( ..) | ty:: Str => {
218+ return self . mplace . meta . unwrap_unsized ( ) . to_machine_usize ( cx) ;
219+ }
179220 _ => bug ! ( "len not supported on unsized type {:?}" , self . layout. ty) ,
180221 }
181222 } else {
@@ -191,7 +232,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
191232 #[ inline]
192233 pub ( super ) fn vtable ( self ) -> Scalar < Tag > {
193234 match self . layout . ty . kind {
194- ty:: Dynamic ( ..) => self . mplace . meta . unwrap ( ) ,
235+ ty:: Dynamic ( ..) => self . mplace . meta . unwrap_unsized ( ) ,
195236 _ => bug ! ( "vtable not supported on type {:?}" , self . layout. ty) ,
196237 }
197238 }
@@ -276,8 +317,10 @@ where
276317 val. layout . ty . builtin_deref ( true ) . expect ( "`ref_to_mplace` called on non-ptr type" ) . ty ;
277318 let layout = self . layout_of ( pointee_type) ?;
278319 let ( ptr, meta) = match * val {
279- Immediate :: Scalar ( ptr) => ( ptr. not_undef ( ) ?, None ) ,
280- Immediate :: ScalarPair ( ptr, meta) => ( ptr. not_undef ( ) ?, Some ( meta. not_undef ( ) ?) ) ,
320+ Immediate :: Scalar ( ptr) => ( ptr. not_undef ( ) ?, MemPlaceMeta :: None ) ,
321+ Immediate :: ScalarPair ( ptr, meta) => {
322+ ( ptr. not_undef ( ) ?, MemPlaceMeta :: Unsized ( meta. not_undef ( ) ?) )
323+ }
281324 } ;
282325
283326 let mplace = MemPlace {
@@ -318,7 +361,7 @@ where
318361 ) -> InterpResult < ' tcx , Option < Pointer < M :: PointerTag > > > {
319362 let size = size. unwrap_or_else ( || {
320363 assert ! ( !place. layout. is_unsized( ) ) ;
321- assert ! ( place. meta. is_none ( ) ) ;
364+ assert ! ( ! place. meta. is_unsized ( ) ) ;
322365 place. layout . size
323366 } ) ;
324367 self . memory . check_ptr_access ( place. ptr , size, place. align )
@@ -411,7 +454,7 @@ where
411454 } else {
412455 // base.meta could be present; we might be accessing a sized field of an unsized
413456 // struct.
414- ( None , offset)
457+ ( MemPlaceMeta :: None , offset)
415458 } ;
416459
417460 // We do not look at `base.layout.align` nor `field_layout.align`, unlike
@@ -433,7 +476,7 @@ where
433476 } ;
434477 let layout = base. layout . field ( self , 0 ) ?;
435478 let dl = & self . tcx . data_layout ;
436- Ok ( ( 0 ..len) . map ( move |i| base. offset ( i * stride, None , layout, dl) ) )
479+ Ok ( ( 0 ..len) . map ( move |i| base. offset ( i * stride, MemPlaceMeta :: None , layout, dl) ) )
437480 }
438481
439482 fn mplace_subslice (
@@ -466,10 +509,10 @@ where
466509 let ( meta, ty) = match base. layout . ty . kind {
467510 // It is not nice to match on the type, but that seems to be the only way to
468511 // implement this.
469- ty:: Array ( inner, _) => ( None , self . tcx . mk_array ( inner, inner_len) ) ,
512+ ty:: Array ( inner, _) => ( MemPlaceMeta :: None , self . tcx . mk_array ( inner, inner_len) ) ,
470513 ty:: Slice ( ..) => {
471514 let len = Scalar :: from_uint ( inner_len, self . pointer_size ( ) ) ;
472- ( Some ( len) , base. layout . ty )
515+ ( MemPlaceMeta :: Unsized ( len) , base. layout . ty )
473516 }
474517 _ => bug ! ( "cannot subslice non-array type: `{:?}`" , base. layout. ty) ,
475518 } ;
@@ -483,7 +526,7 @@ where
483526 variant : VariantIdx ,
484527 ) -> InterpResult < ' tcx , MPlaceTy < ' tcx , M :: PointerTag > > {
485528 // Downcasts only change the layout
486- assert ! ( base. meta. is_none ( ) ) ;
529+ assert ! ( ! base. meta. is_unsized ( ) ) ;
487530 Ok ( MPlaceTy { layout : base. layout . for_variant ( self , variant) , ..base } )
488531 }
489532
@@ -977,7 +1020,7 @@ where
9771020 pub fn force_allocation_maybe_sized (
9781021 & mut self ,
9791022 place : PlaceTy < ' tcx , M :: PointerTag > ,
980- meta : Option < Scalar < M :: PointerTag > > ,
1023+ meta : MemPlaceMeta < M :: PointerTag > ,
9811024 ) -> InterpResult < ' tcx , ( MPlaceTy < ' tcx , M :: PointerTag > , Option < Size > ) > {
9821025 let ( mplace, size) = match place. place {
9831026 Place :: Local { frame, local } => {
@@ -1022,7 +1065,7 @@ where
10221065 & mut self ,
10231066 place : PlaceTy < ' tcx , M :: PointerTag > ,
10241067 ) -> InterpResult < ' tcx , MPlaceTy < ' tcx , M :: PointerTag > > {
1025- Ok ( self . force_allocation_maybe_sized ( place, None ) ?. 0 )
1068+ Ok ( self . force_allocation_maybe_sized ( place, MemPlaceMeta :: None ) ?. 0 )
10261069 }
10271070
10281071 pub fn allocate (
@@ -1042,8 +1085,11 @@ where
10421085 ) -> MPlaceTy < ' tcx , M :: PointerTag > {
10431086 let ptr = self . memory . allocate_static_bytes ( str. as_bytes ( ) , kind) ;
10441087 let meta = Scalar :: from_uint ( str. len ( ) as u128 , self . pointer_size ( ) ) ;
1045- let mplace =
1046- MemPlace { ptr : ptr. into ( ) , align : Align :: from_bytes ( 1 ) . unwrap ( ) , meta : Some ( meta) } ;
1088+ let mplace = MemPlace {
1089+ ptr : ptr. into ( ) ,
1090+ align : Align :: from_bytes ( 1 ) . unwrap ( ) ,
1091+ meta : MemPlaceMeta :: Unsized ( meta) ,
1092+ } ;
10471093
10481094 let layout = self . layout_of ( self . tcx . mk_static_str ( ) ) . unwrap ( ) ;
10491095 MPlaceTy { mplace, layout }
@@ -1151,7 +1197,7 @@ where
11511197 assert_eq ! ( align, layout. align. abi) ;
11521198 }
11531199
1154- let mplace = MPlaceTy { mplace : MemPlace { meta : None , ..* mplace } , layout } ;
1200+ let mplace = MPlaceTy { mplace : MemPlace { meta : MemPlaceMeta :: None , ..* mplace } , layout } ;
11551201 Ok ( ( instance, mplace) )
11561202 }
11571203}
0 commit comments