about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--miri/lib.rs15
-rw-r--r--src/librustc_mir/interpret/eval_context.rs7
-rw-r--r--src/librustc_mir/interpret/lvalue.rs5
-rw-r--r--tests/run-pass/issue-34571.rs20
4 files changed, 43 insertions, 4 deletions
diff --git a/miri/lib.rs b/miri/lib.rs
index 852a4cbe2aa..a824f47a509 100644
--- a/miri/lib.rs
+++ b/miri/lib.rs
@@ -15,6 +15,7 @@ use rustc::ty::layout::Layout;
 use rustc::hir::def_id::DefId;
 use rustc::mir;
 
+use syntax::ast::Mutability;
 use syntax::codemap::Span;
 
 use std::collections::{HashMap, BTreeMap};
@@ -98,15 +99,21 @@ pub fn eval_main<'a, 'tcx: 'a>(
                 dest,
             )?;
 
-            // Second argument (argc): 0
+            // Second argument (argc): 1
             let dest = ecx.eval_lvalue(&mir::Lvalue::Local(args.next().unwrap()))?;
             let ty = ecx.tcx.types.isize;
-            ecx.write_null(dest, ty)?;
+            ecx.write_primval(dest, PrimVal::Bytes(1), ty)?;
 
-            // Third argument (argv): 0
+            // FIXME: extract main source file path
+            // Third argument (argv): &[b"foo"]
             let dest = ecx.eval_lvalue(&mir::Lvalue::Local(args.next().unwrap()))?;
             let ty = ecx.tcx.mk_imm_ptr(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8));
-            ecx.write_null(dest, ty)?;
+            let foo = ecx.memory.allocate_cached(b"foo\0")?;
+            let ptr_size = ecx.memory.pointer_size();
+            let foo_ptr = ecx.memory.allocate(ptr_size * 1, ptr_size, MemoryKind::UninitializedStatic)?;
+            ecx.memory.write_primval(foo_ptr.into(), PrimVal::Ptr(foo.into()), ptr_size, false)?;
+            ecx.memory.mark_static_initalized(foo_ptr.alloc_id, Mutability::Immutable)?;
+            ecx.write_ptr(dest, foo_ptr.into(), ty)?;
         } else {
             ecx.push_stack_frame(
                 main_instance,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 2a4515959d1..b123ad7fd0b 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -1138,6 +1138,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                             packed: nonnull.packed,
                         })
                     }
+                    // mir optimizations treat single variant enums as structs
+                    General { .. } if adt_def.variants.len() == 1 => Ok(TyAndPacked {
+                        ty: adt_def.variants[0].fields[field_index].ty(self.tcx, substs),
+                        packed: false,
+                    }),
                     _ => {
                         err!(Unimplemented(format!(
                             "get_field_ty can't handle enum type: {:?}, {:?}",
@@ -1211,6 +1216,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             }
             StructWrappedNullablePointer { ref nonnull, .. } => Ok(nonnull.offsets[field_index]),
             UntaggedUnion { .. } => Ok(Size::from_bytes(0)),
+            // mir optimizations treat single variant enums as structs
+            General { ref variants, .. } if variants.len() == 1 => Ok(variants[0].offsets[field_index]),
             _ => {
                 let msg = format!(
                     "get_field_offset: can't handle type: {:?}, with layout: {:?}",
diff --git a/src/librustc_mir/interpret/lvalue.rs b/src/librustc_mir/interpret/lvalue.rs
index c4ec2aa795e..f26f5adfff9 100644
--- a/src/librustc_mir/interpret/lvalue.rs
+++ b/src/librustc_mir/interpret/lvalue.rs
@@ -227,6 +227,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
         let (offset, packed) = match *base_layout {
             Univariant { ref variant, .. } => (variant.offsets[field_index], variant.packed),
 
+            // mir optimizations treat single variant enums as structs
+            General { ref variants, .. } if variants.len() == 1 => {
+                (variants[0].offsets[field_index], variants[0].packed)
+            }
+
             General { ref variants, .. } => {
                 let (_, base_extra) = base.to_ptr_extra_aligned();
                 if let LvalueExtra::DowncastVariant(variant_idx) = base_extra {
diff --git a/tests/run-pass/issue-34571.rs b/tests/run-pass/issue-34571.rs
new file mode 100644
index 00000000000..7d804156576
--- /dev/null
+++ b/tests/run-pass/issue-34571.rs
@@ -0,0 +1,20 @@
+// Copyright 2017 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.
+
+#[repr(u8)]
+enum Foo {
+    Foo(u8),
+}
+
+fn main() {
+    match Foo::Foo(1) {
+        _ => ()
+    }
+}