Fix try_read_value not working for enums

This commit is contained in:
Oliver Schneider 2018-07-26 14:05:32 +02:00
parent c6c06854c0
commit d0b315f262
2 changed files with 37 additions and 8 deletions

View File

@ -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 /// ensures this Value is not a ByRef
pub fn follow_by_ref_value( pub fn follow_by_ref_value(
&self, &mut self,
value: Value, value: Value,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> EvalResult<'tcx, Value> { ) -> 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( pub fn value_to_scalar(
&self, &mut self,
ValTy { value, ty } : ValTy<'tcx>, ValTy { value, ty } : ValTy<'tcx>,
) -> EvalResult<'tcx, Scalar> { ) -> EvalResult<'tcx, Scalar> {
match self.follow_by_ref_value(value, ty)? { 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 // Convert to ByVal or ScalarPair if possible
if let Value::ByRef(ptr, align) = val { if let Value::ByRef(ptr, align) = val {
if let Some(read_val) = self.try_read_value(ptr, align, ty)? { 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) Ok(val)
} }
pub fn try_read_value(&self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> { pub fn try_read_value(&mut self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
let layout = self.layout_of(ty)?; let mut layout = self.layout_of(ty)?;
self.memory.check_align(ptr, ptr_align)?; self.memory.check_align(ptr, ptr_align)?;
if layout.size.bytes() == 0 { 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()?; 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 { match layout.abi {
layout::Abi::Scalar(..) => { layout::Abi::Scalar(..) => {
let scalar = self.memory.read_scalar(ptr, ptr_align, layout.size)?; 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) => { layout::Abi::ScalarPair(ref a, ref b) => {
let (a, b) = (&a.value, &b.value); 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 a_ptr = ptr;
let b_offset = a_size.abi_align(b.align(self)); let b_offset = a_size.abi_align(b.align(&self));
let b_ptr = ptr.offset(b_offset, self)?.into(); let b_ptr = ptr.offset(b_offset, &self)?.into();
let a_val = self.memory.read_scalar(a_ptr, ptr_align, a_size)?; 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)?; let b_val = self.memory.read_scalar(b_ptr, ptr_align, b_size)?;
Ok(Some(Value::ScalarPair(a_val, b_val))) Ok(Some(Value::ScalarPair(a_val, b_val)))

View File

@ -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() {}