11use std:: mem;
22
3- use rustc:: ty;
3+ use rustc:: ty:: { self , layout } ;
44use rustc:: hir:: def_id:: { DefId , CRATE_DEF_INDEX } ;
55
66use crate :: * ;
@@ -124,8 +124,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
124124 let ( unsafe_cell_size, _) = self . size_and_align_of_mplace ( place) ?
125125 // for extern types, just cover what we can
126126 . 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+ }
129133 } ,
130134 } ;
131135 visitor. visit_value ( place) ?;
@@ -152,8 +156,6 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
152156 {
153157 type V = MPlaceTy < ' tcx , Borrow > ;
154158
155- const WANT_FIELDS_SORTED : bool = true ; // sorted? yes please!
156-
157159 #[ inline( always) ]
158160 fn ecx ( & self ) -> & MiriEvalContext < ' a , ' mir , ' tcx > {
159161 & self . ecx
@@ -179,6 +181,31 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
179181 }
180182 }
181183
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+
182209 // We have to do *something* for unions
183210 fn visit_union ( & mut self , v : MPlaceTy < ' tcx , Borrow > ) -> EvalResult < ' tcx >
184211 {
0 commit comments