Skip to content

Commit edf27f0

Browse files
committed
visit_aggregate with an iterator; fix some comment typos
1 parent 25f5afa commit edf27f0

File tree

2 files changed

+65
-40
lines changed

2 files changed

+65
-40
lines changed

src/librustc_mir/interpret/validity.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,11 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
470470
}
471471
}
472472

473-
fn visit_array(&mut self, op: OpTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
474-
{
473+
fn visit_aggregate(
474+
&mut self,
475+
op: OpTy<'tcx, M::PointerTag>,
476+
fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
477+
) -> EvalResult<'tcx> {
475478
match op.layout.ty.sty {
476479
ty::Str => {
477480
let mplace = op.to_mem_place(); // strings are never immediate
@@ -538,7 +541,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
538541
}
539542
}
540543
_ => {
541-
self.walk_array(op)? // default handler
544+
self.walk_aggregate(op, fields)? // default handler
542545
}
543546
}
544547
Ok(())

src/librustc_mir/interpret/visitor.rs

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,29 @@ use super::{
1313

1414
// A thing that we can project into, and that has a layout.
1515
// This wouldn't have to depend on `Machine` but with the current type inference,
16-
// that's just more convenient to work with (avoids repeading all the `Machine` bounds).
16+
// that's just more convenient to work with (avoids repeating all the `Machine` bounds).
1717
pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
1818
{
19-
// Get this value's layout.
19+
/// Get this value's layout.
2020
fn layout(&self) -> TyLayout<'tcx>;
2121

22-
// Make this into an `OpTy`.
22+
/// Make this into an `OpTy`.
2323
fn to_op(
2424
self,
2525
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
2626
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>>;
2727

28-
// Create this from an `MPlaceTy`.
28+
/// Create this from an `MPlaceTy`.
2929
fn from_mem_place(MPlaceTy<'tcx, M::PointerTag>) -> Self;
3030

31-
// Project to the given enum variant.
31+
/// Project to the given enum variant.
3232
fn project_downcast(
3333
self,
3434
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
3535
variant: usize,
3636
) -> EvalResult<'tcx, Self>;
3737

38-
// Project to the n-th field.
38+
/// Project to the n-th field.
3939
fn project_field(
4040
self,
4141
ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
@@ -166,27 +166,32 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
166166
pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized {
167167
type V: Value<'a, 'mir, 'tcx, M>;
168168

169-
// The visitor must have an `EvalContext` in it.
169+
/// The visitor must have an `EvalContext` in it.
170170
fn ecx(&mut self) -> &mut EvalContext<'a, 'mir, 'tcx, M>;
171171

172-
// Recursie actions, ready to be overloaded.
173-
/// Visit the given value, dispatching as appropriate to more speicalized visitors.
172+
// Recursive actions, ready to be overloaded.
173+
/// Visit the given value, dispatching as appropriate to more specialized visitors.
174174
#[inline(always)]
175175
fn visit_value(&mut self, v: Self::V) -> EvalResult<'tcx>
176176
{
177177
self.walk_value(v)
178178
}
179-
/// Visit the given value as a union.
179+
/// Visit the given value as a union. No automatic recursion can happen here.
180180
#[inline(always)]
181181
fn visit_union(&mut self, _v: Self::V) -> EvalResult<'tcx>
182182
{
183183
Ok(())
184184
}
185-
/// Visit the given value as an array.
185+
/// Visit this vale as an aggregate, you are even getting an iterator yielding
186+
/// all the fields (still in an `EvalResult`, you have to do error handling yourself).
187+
/// Recurses into the fields.
186188
#[inline(always)]
187-
fn visit_array(&mut self, v: Self::V) -> EvalResult<'tcx>
188-
{
189-
self.walk_array(v)
189+
fn visit_aggregate(
190+
&mut self,
191+
v: Self::V,
192+
fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
193+
) -> EvalResult<'tcx> {
194+
self.walk_aggregate(v, fields)
190195
}
191196
/// Called each time we recurse down to a field, passing in old and new value.
192197
/// This gives the visitor the chance to track the stack of nested fields that
@@ -201,39 +206,39 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
201206
self.visit_value(new_val)
202207
}
203208

204-
// Actions on the leaves, ready to be overloaded.
205209
/// Called whenever we reach a value with uninhabited layout.
206-
/// Recursing to fields will continue after this!
210+
/// Recursing to fields will *always* continue after this! This is not meant to control
211+
/// whether and how we descend recursively/ into the scalar's fields if there are any, it is
212+
/// meant to provide the chance for additional checks when a value of uninhabited layout is
213+
/// detected.
207214
#[inline(always)]
208215
fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
209216
{ Ok(()) }
210217
/// Called whenever we reach a value with scalar layout.
211-
/// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory
212-
/// if the visitor is not even interested in scalars.
213-
/// Recursing to fields will continue after this!
218+
/// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the visitor is not
219+
/// even interested in scalars.
220+
/// Recursing to fields will *always* continue after this! This is not meant to control
221+
/// whether and how we descend recursively/ into the scalar's fields if there are any, it is
222+
/// meant to provide the chance for additional checks when a value of scalar layout is detected.
214223
#[inline(always)]
215224
fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<'tcx>
216225
{ Ok(()) }
226+
217227
/// Called whenever we reach a value of primitive type. There can be no recursion
218-
/// below such a value.
228+
/// below such a value. This is the leave function.
219229
#[inline(always)]
220230
fn visit_primitive(&mut self, _val: ValTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
221231
{ Ok(()) }
222232

223233
// Default recursors. Not meant to be overloaded.
224-
fn walk_array(&mut self, v: Self::V) -> EvalResult<'tcx>
225-
{
226-
// Let's get an mplace first.
227-
let mplace = if v.layout().is_zst() {
228-
// it's a ZST, the memory content cannot matter
229-
MPlaceTy::dangling(v.layout(), &self.ecx())
230-
} else {
231-
// non-ZST array/slice/str cannot be immediate
232-
v.to_op(self.ecx())?.to_mem_place()
233-
};
234+
fn walk_aggregate(
235+
&mut self,
236+
v: Self::V,
237+
fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
238+
) -> EvalResult<'tcx> {
234239
// Now iterate over it.
235-
for (i, field) in self.ecx().mplace_array_fields(mplace)?.enumerate() {
236-
self.visit_field(v, i, Value::from_mem_place(field?))?;
240+
for (idx, field_val) in fields.enumerate() {
241+
self.visit_field(v, idx, field_val?)?;
237242
}
238243
Ok(())
239244
}
@@ -312,13 +317,30 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
312317
self.visit_union(v)?;
313318
},
314319
layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
315-
for i in 0..offsets.len() {
316-
let val = v.project_field(self.ecx(), i as u64)?;
317-
self.visit_field(v, i, val)?;
318-
}
320+
// We collect in a vec because otherwise there are lifetime errors:
321+
// Projecting to a field needs (mutable!) access to `ecx`.
322+
let fields: Vec<EvalResult<'tcx, Self::V>> =
323+
(0..offsets.len()).map(|i| {
324+
v.project_field(self.ecx(), i as u64)
325+
})
326+
.collect();
327+
self.visit_aggregate(v, fields.into_iter())?;
319328
},
320329
layout::FieldPlacement::Array { .. } => {
321-
self.visit_array(v)?;
330+
// Let's get an mplace first.
331+
let mplace = if v.layout().is_zst() {
332+
// it's a ZST, the memory content cannot matter
333+
MPlaceTy::dangling(v.layout(), &self.ecx())
334+
} else {
335+
// non-ZST array/slice/str cannot be immediate
336+
v.to_op(self.ecx())?.to_mem_place()
337+
};
338+
// Now we can go over all the fields.
339+
let iter = self.ecx().mplace_array_fields(mplace)?
340+
.map(|f| f.and_then(|f| {
341+
Ok(Value::from_mem_place(f))
342+
}));
343+
self.visit_aggregate(v, iter)?;
322344
}
323345
}
324346
Ok(())

0 commit comments

Comments
 (0)