Skip to content

Commit 0b64cee

Browse files
committed
sort the fields ourselves
1 parent 0760454 commit 0b64cee

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

src/helpers.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::mem;
22

3-
use rustc::ty;
3+
use rustc::ty::{self, layout};
44
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
55

66
use 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

Comments
 (0)