about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <github35764891676564198441@oli-obk.de>2018-07-26 14:05:32 +0200
committerOliver Schneider <github35764891676564198441@oli-obk.de>2018-08-01 15:29:35 +0200
commitd0b315f262d95a6a95292d638aa7697c21513db4 (patch)
tree071081af1d7fe65a7824d559462d8935f42e7423
parentc6c06854c0cf800519bbc42cc1b08afbd4bdf90a (diff)
downloadrust-d0b315f262d95a6a95292d638aa7697c21513db4.tar.gz
rust-d0b315f262d95a6a95292d638aa7697c21513db4.zip
Fix `try_read_value` not working for enums
-rw-r--r--src/librustc_mir/interpret/eval_context.rs29
-rw-r--r--src/test/ui/const-eval/simple_with_undef.rs16
2 files changed, 37 insertions, 8 deletions
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index b6b593b15a6..ada304b6997 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -1120,7 +1120,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
 
     /// ensures this Value is not a ByRef
     pub fn follow_by_ref_value(
-        &self,
+        &mut self,
         value: Value,
         ty: Ty<'tcx>,
     ) -> EvalResult<'tcx, Value> {
@@ -1133,7 +1133,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
     }
 
     pub fn value_to_scalar(
-        &self,
+        &mut self,
         ValTy { value, ty } : ValTy<'tcx>,
     ) -> EvalResult<'tcx, Scalar> {
         match self.follow_by_ref_value(value, ty)? {
@@ -1540,7 +1540,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
         }
     }
 
-    pub fn try_read_by_ref(&self, mut val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
+    pub fn try_read_by_ref(&mut self, mut val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
         // Convert to ByVal or ScalarPair if possible
         if let Value::ByRef(ptr, align) = val {
             if let Some(read_val) = self.try_read_value(ptr, align, ty)? {
@@ -1550,8 +1550,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
         Ok(val)
     }
 
-    pub fn try_read_value(&self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
-        let layout = self.layout_of(ty)?;
+    pub fn try_read_value(&mut self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
+        let mut layout = self.layout_of(ty)?;
         self.memory.check_align(ptr, ptr_align)?;
 
         if layout.size.bytes() == 0 {
@@ -1560,6 +1560,19 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
 
         let ptr = ptr.to_ptr()?;
 
+        match layout.variants {
+            layout::Variants::NicheFilling { .. } |
+            layout::Variants::Tagged { .. } => {
+                let variant_index = self.read_discriminant_as_variant_index(
+                    Place::from_ptr(ptr, ptr_align),
+                    layout.ty,
+                )?;
+                layout = layout.for_variant(&self, variant_index);
+                trace!("variant layout: {:#?}", layout);
+            },
+            layout::Variants::Single { .. } => {},
+        }
+
         match layout.abi {
             layout::Abi::Scalar(..) => {
                 let scalar = self.memory.read_scalar(ptr, ptr_align, layout.size)?;
@@ -1567,10 +1580,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             }
             layout::Abi::ScalarPair(ref a, ref b) => {
                 let (a, b) = (&a.value, &b.value);
-                let (a_size, b_size) = (a.size(self), b.size(self));
+                let (a_size, b_size) = (a.size(&self), b.size(&self));
                 let a_ptr = ptr;
-                let b_offset = a_size.abi_align(b.align(self));
-                let b_ptr = ptr.offset(b_offset, self)?.into();
+                let b_offset = a_size.abi_align(b.align(&self));
+                let b_ptr = ptr.offset(b_offset, &self)?.into();
                 let a_val = self.memory.read_scalar(a_ptr, ptr_align, a_size)?;
                 let b_val = self.memory.read_scalar(b_ptr, ptr_align, b_size)?;
                 Ok(Some(Value::ScalarPair(a_val, b_val)))
diff --git a/src/test/ui/const-eval/simple_with_undef.rs b/src/test/ui/const-eval/simple_with_undef.rs
new file mode 100644
index 00000000000..d18059fafd5
--- /dev/null
+++ b/src/test/ui/const-eval/simple_with_undef.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+const PARSE_BOOL: Option<&'static str> = None;
+static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42);
+
+fn main() {}