Skip to content

Commit c6b1698

Browse files
committed
Auto merge of #60541 - RalfJung:miri-visitor-generators, r=oli-obk
fix Miri visiting generators Fixes fall-out caused by #59897. r? @oli-obk
2 parents 5d8fd98 + c5c161e commit c6b1698

File tree

2 files changed

+29
-42
lines changed

2 files changed

+29
-42
lines changed

src/librustc_mir/interpret/validity.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ macro_rules! try_validation {
6666
pub enum PathElem {
6767
Field(Symbol),
6868
Variant(Symbol),
69+
GeneratoreState(VariantIdx),
6970
ClosureVar(Symbol),
7071
ArrayElem(usize),
7172
TupleElem(usize),
@@ -100,6 +101,7 @@ fn path_format(path: &Vec<PathElem>) -> String {
100101
match elem {
101102
Field(name) => write!(out, ".{}", name),
102103
Variant(name) => write!(out, ".<downcast-variant({})>", name),
104+
GeneratoreState(idx) => write!(out, ".<generator-state({})>", idx.index()),
103105
ClosureVar(name) => write!(out, ".<closure-var({})>", name),
104106
TupleElem(idx) => write!(out, ".{}", idx),
105107
ArrayElem(idx) => write!(out, "[{}]", idx),
@@ -262,8 +264,13 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
262264
variant_id: VariantIdx,
263265
new_op: OpTy<'tcx, M::PointerTag>
264266
) -> EvalResult<'tcx> {
265-
let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].ident.name;
266-
self.visit_elem(new_op, PathElem::Variant(name))
267+
let name = match old_op.layout.ty.sty {
268+
ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name),
269+
// Generators also have variants
270+
ty::Generator(..) => PathElem::GeneratoreState(variant_id),
271+
_ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
272+
};
273+
self.visit_elem(new_op, name)
267274
}
268275

269276
#[inline]

src/librustc_mir/interpret/visitor.rs

+20-40
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ macro_rules! make_value_visitor {
147147
{
148148
Ok(())
149149
}
150-
/// Visits this vale as an aggregate, you are even getting an iterator yielding
150+
/// Visits this value as an aggregate, you are getting an iterator yielding
151151
/// all the fields (still in an `EvalResult`, you have to do error handling yourself).
152152
/// Recurses into the fields.
153153
#[inline(always)]
@@ -160,7 +160,8 @@ macro_rules! make_value_visitor {
160160
}
161161

162162
/// Called each time we recurse down to a field of a "product-like" aggregate
163-
/// (structs, tuples, arrays and the like, but not enums), passing in old and new value.
163+
/// (structs, tuples, arrays and the like, but not enums), passing in old (outer)
164+
/// and new (inner) value.
164165
/// This gives the visitor the chance to track the stack of nested fields that
165166
/// we are descending through.
166167
#[inline(always)]
@@ -173,18 +174,6 @@ macro_rules! make_value_visitor {
173174
self.visit_value(new_val)
174175
}
175176

176-
/// Called for recursing into the field of a generator. These are not known to be
177-
/// initialized, so we treat them like unions.
178-
#[inline(always)]
179-
fn visit_generator_field(
180-
&mut self,
181-
_old_val: Self::V,
182-
_field: usize,
183-
new_val: Self::V,
184-
) -> EvalResult<'tcx> {
185-
self.visit_union(new_val)
186-
}
187-
188177
/// Called when recursing into an enum variant.
189178
#[inline(always)]
190179
fn visit_variant(
@@ -238,7 +227,7 @@ macro_rules! make_value_visitor {
238227
fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
239228
{
240229
trace!("walk_value: type: {}", v.layout().ty);
241-
// If this is a multi-variant layout, we have find the right one and proceed with
230+
// If this is a multi-variant layout, we have to find the right one and proceed with
242231
// that.
243232
match v.layout().variants {
244233
layout::Variants::Multiple { .. } => {
@@ -263,6 +252,13 @@ macro_rules! make_value_visitor {
263252
// recurse with the inner type
264253
return self.visit_field(v, 0, Value::from_mem_place(inner));
265254
},
255+
ty::Generator(..) => {
256+
// FIXME: Generator layout is lying: it claims a whole bunch of fields exist
257+
// when really many of them can be uninitialized.
258+
// Just treat them as a union for now, until hopefully the layout
259+
// computation is fixed.
260+
return self.visit_union(v);
261+
}
266262
_ => {},
267263
};
268264

@@ -304,34 +300,18 @@ macro_rules! make_value_visitor {
304300
// Empty unions are not accepted by rustc. That's great, it means we can
305301
// use that as an unambiguous signal for detecting primitives. Make sure
306302
// we did not miss any primitive.
307-
debug_assert!(fields > 0);
303+
assert!(fields > 0);
308304
self.visit_union(v)
309305
},
310306
layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
311-
// Special handling needed for generators: All but the first field
312-
// (which is the state) are actually implicitly `MaybeUninit`, i.e.,
313-
// they may or may not be initialized, so we cannot visit them.
314-
match v.layout().ty.sty {
315-
ty::Generator(..) => {
316-
let field = v.project_field(self.ecx(), 0)?;
317-
self.visit_aggregate(v, std::iter::once(Ok(field)))?;
318-
for i in 1..offsets.len() {
319-
let field = v.project_field(self.ecx(), i as u64)?;
320-
self.visit_generator_field(v, i, field)?;
321-
}
322-
Ok(())
323-
}
324-
_ => {
325-
// FIXME: We collect in a vec because otherwise there are lifetime
326-
// errors: Projecting to a field needs access to `ecx`.
327-
let fields: Vec<EvalResult<'tcx, Self::V>> =
328-
(0..offsets.len()).map(|i| {
329-
v.project_field(self.ecx(), i as u64)
330-
})
331-
.collect();
332-
self.visit_aggregate(v, fields.into_iter())
333-
}
334-
}
307+
// FIXME: We collect in a vec because otherwise there are lifetime
308+
// errors: Projecting to a field needs access to `ecx`.
309+
let fields: Vec<EvalResult<'tcx, Self::V>> =
310+
(0..offsets.len()).map(|i| {
311+
v.project_field(self.ecx(), i as u64)
312+
})
313+
.collect();
314+
self.visit_aggregate(v, fields.into_iter())
335315
},
336316
layout::FieldPlacement::Array { .. } => {
337317
// Let's get an mplace first.

0 commit comments

Comments
 (0)