1
1
use std:: mem;
2
2
3
- use rustc:: ty;
3
+ use rustc:: ty:: { self , layout } ;
4
4
use rustc:: hir:: def_id:: { DefId , CRATE_DEF_INDEX } ;
5
5
6
6
use crate :: * ;
@@ -124,8 +124,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
124
124
let ( unsafe_cell_size, _) = self . size_and_align_of_mplace ( place) ?
125
125
// for extern types, just cover what we can
126
126
. unwrap_or_else ( || place. layout . size_and_align ( ) ) ;
127
- // Now handle this `UnsafeCell`.
128
- unsafe_cell_action ( place. ptr . get_ptr_offset ( self ) , unsafe_cell_size)
127
+ // Now handle this `UnsafeCell`, unless it is empty.
128
+ if unsafe_cell_size != Size :: ZERO {
129
+ unsafe_cell_action ( place. ptr . get_ptr_offset ( self ) , unsafe_cell_size)
130
+ } else {
131
+ Ok ( ( ) )
132
+ }
129
133
} ,
130
134
} ;
131
135
visitor. visit_value ( place) ?;
@@ -152,8 +156,6 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
152
156
{
153
157
type V = MPlaceTy < ' tcx , Borrow > ;
154
158
155
- const WANT_FIELDS_SORTED : bool = true ; // sorted? yes please!
156
-
157
159
#[ inline( always) ]
158
160
fn ecx ( & self ) -> & MiriEvalContext < ' a , ' mir , ' tcx > {
159
161
& self . ecx
@@ -179,6 +181,31 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
179
181
}
180
182
}
181
183
184
+ // Make sure we visit aggregrates in increasing offset order
185
+ fn visit_aggregate (
186
+ & mut self ,
187
+ place : MPlaceTy < ' tcx , Borrow > ,
188
+ fields : impl Iterator < Item =EvalResult < ' tcx , MPlaceTy < ' tcx , Borrow > > > ,
189
+ ) -> EvalResult < ' tcx > {
190
+ match place. layout . fields {
191
+ layout:: FieldPlacement :: Array { .. } => {
192
+ // For the array layout, we know the iterator will yield sorted elements so
193
+ // we can avoid the allocation.
194
+ self . walk_aggregate ( place, fields)
195
+ }
196
+ layout:: FieldPlacement :: Arbitrary { .. } => {
197
+ // Gather the subplaces and sort them before visiting.
198
+ let mut places = fields. collect :: < EvalResult < ' tcx , Vec < MPlaceTy < ' tcx , Borrow > > > > ( ) ?;
199
+ places[ ..] . sort_by_key ( |place| place. ptr . get_ptr_offset ( self . ecx ( ) ) ) ;
200
+ self . walk_aggregate ( place, places. into_iter ( ) . map ( Ok ) )
201
+ }
202
+ layout:: FieldPlacement :: Union { .. } => {
203
+ // Uh, what?
204
+ bug ! ( "A union is not an aggregate we should ever visit" )
205
+ }
206
+ }
207
+ }
208
+
182
209
// We have to do *something* for unions
183
210
fn visit_union ( & mut self , v : MPlaceTy < ' tcx , Borrow > ) -> EvalResult < ' tcx >
184
211
{
0 commit comments