about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-11-20 15:08:26 +0100
committerRalf Jung <post@ralfj.de>2018-11-20 15:22:43 +0100
commit6eeedbcd70855b45cf41ef14bc91a15f0ee67c7c (patch)
tree1657a3c71167b17a6c2649354dfe625312ef85b1 /src
parent046e054a995c7b293e26968774ff88b38661cd3c (diff)
downloadrust-6eeedbcd70855b45cf41ef14bc91a15f0ee67c7c.tar.gz
rust-6eeedbcd70855b45cf41ef14bc91a15f0ee67c7c.zip
generator fields are not necessarily initialized
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/interpret/visitor.rs33
1 files changed, 22 insertions, 11 deletions
diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs
index f0a71242599..505195763d0 100644
--- a/src/librustc_mir/interpret/visitor.rs
+++ b/src/librustc_mir/interpret/visitor.rs
@@ -142,6 +142,7 @@ macro_rules! make_value_visitor {
                 self.walk_value(v)
             }
             /// Visit the given value as a union.  No automatic recursion can happen here.
+            /// Also called for the fields of a generator, which may or may not be initialized.
             #[inline(always)]
             fn visit_union(&mut self, _v: Self::V) -> EvalResult<'tcx>
             {
@@ -291,17 +292,28 @@ macro_rules! make_value_visitor {
                         // use that as an unambiguous signal for detecting primitives.  Make sure
                         // we did not miss any primitive.
                         debug_assert!(fields > 0);
-                        self.visit_union(v)?;
+                        self.visit_union(v)
                     },
                     layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
-                        // FIXME: We collect in a vec because otherwise there are lifetime errors:
-                        // Projecting to a field needs (mutable!) access to `ecx`.
-                        let fields: Vec<EvalResult<'tcx, Self::V>> =
-                            (0..offsets.len()).map(|i| {
-                                v.project_field(self.ecx(), i as u64)
-                            })
-                            .collect();
-                        self.visit_aggregate(v, fields.into_iter())?;
+                        // Special handling needed for generators: All but the first field
+                        // (which is the state) are actually implicitly `MaybeUninit`, i.e.,
+                        // they may or may not be initialized, so we cannot visit them.
+                        match v.layout().ty.sty {
+                            ty::Generator(..) => {
+                                let field = v.project_field(self.ecx(), 0)?;
+                                self.visit_aggregate(v, std::iter::once(Ok(field)))
+                            }
+                            _ => {
+                                // FIXME: We collect in a vec because otherwise there are lifetime
+                                // errors: Projecting to a field needs access to `ecx`.
+                                let fields: Vec<EvalResult<'tcx, Self::V>> =
+                                    (0..offsets.len()).map(|i| {
+                                        v.project_field(self.ecx(), i as u64)
+                                    })
+                                    .collect();
+                                self.visit_aggregate(v, fields.into_iter())
+                            }
+                        }
                     },
                     layout::FieldPlacement::Array { .. } => {
                         // Let's get an mplace first.
@@ -317,10 +329,9 @@ macro_rules! make_value_visitor {
                             .map(|f| f.and_then(|f| {
                                 Ok(Value::from_mem_place(f))
                             }));
-                        self.visit_aggregate(v, iter)?;
+                        self.visit_aggregate(v, iter)
                     }
                 }
-                Ok(())
             }
         }
     }