@@ -20,6 +20,45 @@ use super::{
20
20
RawConst , Scalar , ScalarMaybeUndef ,
21
21
} ;
22
22
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
+
23
62
#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq , HashStable ) ]
24
63
pub struct MemPlace < Tag = ( ) , Id = AllocId > {
25
64
/// A place may have an integral pointer for ZSTs, and since it might
@@ -30,7 +69,7 @@ pub struct MemPlace<Tag = (), Id = AllocId> {
30
69
/// Metadata for unsized places. Interpretation is up to the type.
31
70
/// Must not be present for sized types, but can be missing for unsized types
32
71
/// (e.g., `extern type`).
33
- pub meta : Option < Scalar < Tag , Id > > ,
72
+ pub meta : MemPlaceMeta < Tag , Id > ,
34
73
}
35
74
36
75
#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq , HashStable ) ]
@@ -88,16 +127,12 @@ impl<Tag> MemPlace<Tag> {
88
127
89
128
#[ inline]
90
129
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 ( ) }
96
131
}
97
132
98
133
#[ inline( always) ]
99
134
pub fn from_scalar_ptr ( ptr : Scalar < Tag > , align : Align ) -> Self {
100
- MemPlace { ptr, align, meta : None }
135
+ MemPlace { ptr, align, meta : MemPlaceMeta :: None }
101
136
}
102
137
103
138
/// Produces a Place that will error if attempted to be read from or written to
@@ -116,15 +151,19 @@ impl<Tag> MemPlace<Tag> {
116
151
#[ inline( always) ]
117
152
pub fn to_ref ( self ) -> Immediate < Tag > {
118
153
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
+ ) ,
121
160
}
122
161
}
123
162
124
163
pub fn offset (
125
164
self ,
126
165
offset : Size ,
127
- meta : Option < Scalar < Tag > > ,
166
+ meta : MemPlaceMeta < Tag > ,
128
167
cx : & impl HasDataLayout ,
129
168
) -> InterpResult < ' tcx , Self > {
130
169
Ok ( MemPlace {
@@ -158,7 +197,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
158
197
pub fn offset (
159
198
self ,
160
199
offset : Size ,
161
- meta : Option < Scalar < Tag > > ,
200
+ meta : MemPlaceMeta < Tag > ,
162
201
layout : TyLayout < ' tcx > ,
163
202
cx : & impl HasDataLayout ,
164
203
) -> InterpResult < ' tcx , Self > {
@@ -175,7 +214,9 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
175
214
if self . layout . is_unsized ( ) {
176
215
// We need to consult `meta` metadata
177
216
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
+ }
179
220
_ => bug ! ( "len not supported on unsized type {:?}" , self . layout. ty) ,
180
221
}
181
222
} else {
@@ -191,7 +232,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
191
232
#[ inline]
192
233
pub ( super ) fn vtable ( self ) -> Scalar < Tag > {
193
234
match self . layout . ty . kind {
194
- ty:: Dynamic ( ..) => self . mplace . meta . unwrap ( ) ,
235
+ ty:: Dynamic ( ..) => self . mplace . meta . unwrap_unsized ( ) ,
195
236
_ => bug ! ( "vtable not supported on type {:?}" , self . layout. ty) ,
196
237
}
197
238
}
@@ -276,8 +317,10 @@ where
276
317
val. layout . ty . builtin_deref ( true ) . expect ( "`ref_to_mplace` called on non-ptr type" ) . ty ;
277
318
let layout = self . layout_of ( pointee_type) ?;
278
319
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
+ }
281
324
} ;
282
325
283
326
let mplace = MemPlace {
@@ -318,7 +361,7 @@ where
318
361
) -> InterpResult < ' tcx , Option < Pointer < M :: PointerTag > > > {
319
362
let size = size. unwrap_or_else ( || {
320
363
assert ! ( !place. layout. is_unsized( ) ) ;
321
- assert ! ( place. meta. is_none ( ) ) ;
364
+ assert ! ( ! place. meta. is_unsized ( ) ) ;
322
365
place. layout . size
323
366
} ) ;
324
367
self . memory . check_ptr_access ( place. ptr , size, place. align )
@@ -411,7 +454,7 @@ where
411
454
} else {
412
455
// base.meta could be present; we might be accessing a sized field of an unsized
413
456
// struct.
414
- ( None , offset)
457
+ ( MemPlaceMeta :: None , offset)
415
458
} ;
416
459
417
460
// We do not look at `base.layout.align` nor `field_layout.align`, unlike
@@ -433,7 +476,7 @@ where
433
476
} ;
434
477
let layout = base. layout . field ( self , 0 ) ?;
435
478
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) ) )
437
480
}
438
481
439
482
fn mplace_subslice (
@@ -466,10 +509,10 @@ where
466
509
let ( meta, ty) = match base. layout . ty . kind {
467
510
// It is not nice to match on the type, but that seems to be the only way to
468
511
// 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) ) ,
470
513
ty:: Slice ( ..) => {
471
514
let len = Scalar :: from_uint ( inner_len, self . pointer_size ( ) ) ;
472
- ( Some ( len) , base. layout . ty )
515
+ ( MemPlaceMeta :: Unsized ( len) , base. layout . ty )
473
516
}
474
517
_ => bug ! ( "cannot subslice non-array type: `{:?}`" , base. layout. ty) ,
475
518
} ;
@@ -483,7 +526,7 @@ where
483
526
variant : VariantIdx ,
484
527
) -> InterpResult < ' tcx , MPlaceTy < ' tcx , M :: PointerTag > > {
485
528
// Downcasts only change the layout
486
- assert ! ( base. meta. is_none ( ) ) ;
529
+ assert ! ( ! base. meta. is_unsized ( ) ) ;
487
530
Ok ( MPlaceTy { layout : base. layout . for_variant ( self , variant) , ..base } )
488
531
}
489
532
@@ -977,7 +1020,7 @@ where
977
1020
pub fn force_allocation_maybe_sized (
978
1021
& mut self ,
979
1022
place : PlaceTy < ' tcx , M :: PointerTag > ,
980
- meta : Option < Scalar < M :: PointerTag > > ,
1023
+ meta : MemPlaceMeta < M :: PointerTag > ,
981
1024
) -> InterpResult < ' tcx , ( MPlaceTy < ' tcx , M :: PointerTag > , Option < Size > ) > {
982
1025
let ( mplace, size) = match place. place {
983
1026
Place :: Local { frame, local } => {
@@ -1022,7 +1065,7 @@ where
1022
1065
& mut self ,
1023
1066
place : PlaceTy < ' tcx , M :: PointerTag > ,
1024
1067
) -> 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 )
1026
1069
}
1027
1070
1028
1071
pub fn allocate (
@@ -1042,8 +1085,11 @@ where
1042
1085
) -> MPlaceTy < ' tcx , M :: PointerTag > {
1043
1086
let ptr = self . memory . allocate_static_bytes ( str. as_bytes ( ) , kind) ;
1044
1087
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
+ } ;
1047
1093
1048
1094
let layout = self . layout_of ( self . tcx . mk_static_str ( ) ) . unwrap ( ) ;
1049
1095
MPlaceTy { mplace, layout }
@@ -1151,7 +1197,7 @@ where
1151
1197
assert_eq ! ( align, layout. align. abi) ;
1152
1198
}
1153
1199
1154
- let mplace = MPlaceTy { mplace : MemPlace { meta : None , ..* mplace } , layout } ;
1200
+ let mplace = MPlaceTy { mplace : MemPlace { meta : MemPlaceMeta :: None , ..* mplace } , layout } ;
1155
1201
Ok ( ( instance, mplace) )
1156
1202
}
1157
1203
}
0 commit comments