From 37e18e7a304a1c013c59babc69ad9af4f54d8b03 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 2 Aug 2018 13:16:53 +0200 Subject: [PATCH] Second field of ScalarPair can be undef in some cases --- src/librustc/mir/interpret/value.rs | 11 +++++------ src/librustc_codegen_llvm/mir/operand.rs | 18 +++++++++++------- src/librustc_mir/hair/pattern/mod.rs | 7 +++++++ src/librustc_mir/interpret/const_eval.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 6 +++--- src/test/compile-fail/const-err4.rs | 2 +- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index c9bb48d2756..71e3ac48d5b 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -18,7 +18,9 @@ pub enum ConstValue<'tcx> { /// Used only for types with layout::abi::Scalar ABI and ZSTs Scalar(Scalar), /// Used only for types with layout::abi::ScalarPair - ScalarPair(Scalar, Scalar), + /// + /// The second field may be undef in case of `Option::None` + ScalarPair(Scalar, ScalarMaybeUndef), /// Used only for the remaining cases. An allocation + offset into the allocation ByRef(&'tcx Allocation, Size), } @@ -28,10 +30,7 @@ impl<'tcx> ConstValue<'tcx> { pub fn from_byval_value(val: Value) -> EvalResult<'static, Self> { Ok(match val { Value::ByRef(..) => bug!(), - Value::ScalarPair(a, b) => ConstValue::ScalarPair( - a.unwrap_or_err()?, - b.unwrap_or_err()?, - ), + Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b), Value::Scalar(val) => ConstValue::Scalar(val.unwrap_or_err()?), }) } @@ -41,7 +40,7 @@ impl<'tcx> ConstValue<'tcx> { match *self { ConstValue::Unevaluated(..) | ConstValue::ByRef(..) => None, - ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a.into(), b.into())), + ConstValue::ScalarPair(a, b) => Some(Value::ScalarPair(a.into(), b)), ConstValue::Scalar(val) => Some(Value::Scalar(val.into())), } } diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs index 1296f5e4b14..f8166ee6491 100644 --- a/src/librustc_codegen_llvm/mir/operand.rs +++ b/src/librustc_codegen_llvm/mir/operand.rs @@ -10,7 +10,7 @@ use rustc::mir::interpret::ConstEvalErr; use rustc::mir; -use rustc::mir::interpret::ConstValue; +use rustc::mir::interpret::{ConstValue, ScalarMaybeUndef}; use rustc::ty; use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; use rustc_data_structures::indexed_vec::Idx; @@ -110,12 +110,16 @@ impl OperandRef<'ll, 'tcx> { a_scalar, layout.scalar_pair_element_llvm_type(bx.cx, 0, true), ); - let b_llval = scalar_to_llvm( - bx.cx, - b, - b_scalar, - layout.scalar_pair_element_llvm_type(bx.cx, 1, true), - ); + let b_layout = layout.scalar_pair_element_llvm_type(bx.cx, 1, true); + let b_llval = match b { + ScalarMaybeUndef::Scalar(b) => scalar_to_llvm( + bx.cx, + b, + b_scalar, + b_layout, + ), + ScalarMaybeUndef::Undef => C_undef(b_layout), + }; OperandValue::Pair(a_llval, b_llval) }, ConstValue::ByRef(alloc, offset) => { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index a60513116b2..d614131c526 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -1102,6 +1102,13 @@ pub fn compare_const_vals<'a, 'tcx>( len_b, ), ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => { + let len_a = len_a.unwrap_or_err().ok(); + let len_b = len_b.unwrap_or_err().ok(); + if len_a.is_none() || len_b.is_none() { + tcx.sess.struct_err("str slice len is undef").delay_as_bug(); + } + let len_a = len_a?; + let len_b = len_b?; if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) { if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) { if len_a == len_b { diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 121812e8713..9d66a0b396b 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -87,7 +87,7 @@ pub fn value_to_const_value<'tcx>( } let val = match val { Value::Scalar(val) => ConstValue::Scalar(val.unwrap_or_err()?), - Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b.unwrap_or_err()?), + Value::ScalarPair(a, b) => ConstValue::ScalarPair(a.unwrap_or_err()?, b), Value::ByRef(ptr, align) => { let ptr = ptr.to_ptr().unwrap(); let alloc = ecx.memory.get(ptr.alloc_id)?; diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 5f05783b15c..bd90b308fab 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -193,7 +193,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; -use rustc::mir::interpret::{AllocId, ConstValue}; +use rustc::mir::interpret::{AllocId, ConstValue, ScalarMaybeUndef}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; use rustc::ty::subst::Substs; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind}; @@ -1264,11 +1264,11 @@ fn collect_const<'a, 'tcx>( }; match val { ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"), - ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => { + ConstValue::ScalarPair(Scalar::Ptr(a), ScalarMaybeUndef::Scalar(Scalar::Ptr(b))) => { collect_miri(tcx, a.alloc_id, output); collect_miri(tcx, b.alloc_id, output); } - ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) | + ConstValue::ScalarPair(_, ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr))) | ConstValue::ScalarPair(Scalar::Ptr(ptr), _) | ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), diff --git a/src/test/compile-fail/const-err4.rs b/src/test/compile-fail/const-err4.rs index 09ebf1681c5..10376d57809 100644 --- a/src/test/compile-fail/const-err4.rs +++ b/src/test/compile-fail/const-err4.rs @@ -16,7 +16,7 @@ union Foo { enum Bar { Boo = [unsafe { Foo { b: () }.a }; 4][3], - //~^ ERROR constant evaluation of enum discriminant resulted in non-integer + //~^ ERROR could not evaluate enum discriminant } fn main() {