From 506a5c79102298ac21d7b2498a874f2f5b4581fa Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 29 Aug 2017 12:24:23 +0200 Subject: [PATCH 1/2] Mir optimizations treat single variant enums as structs --- src/librustc_mir/interpret/eval_context.rs | 7 +++++++ src/librustc_mir/interpret/lvalue.rs | 5 +++++ tests/run-pass/issue-34571.rs | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 tests/run-pass/issue-34571.rs diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 2a4515959d1fe..b123ad7fd0b65 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 c4ec2aa795e89..f26f5adfff965 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 0000000000000..7d80415657655 --- /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 or the MIT license +// , 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) { + _ => () + } +} From 446ed26412eeb7263b0474b3c9468cc075309c27 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 29 Aug 2017 12:24:58 +0200 Subject: [PATCH 2/2] Add at least the program name argument in order to get rustc tests a little further --- miri/lib.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/miri/lib.rs b/miri/lib.rs index 852a4cbe2aa8a..a824f47a509f5 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,