From e3f69317a0aab547ec98b5db93130cc69f52e20d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 2 Oct 2018 20:47:57 +0200 Subject: [PATCH] do not normalize non-scalar constants to a ConstValue::ScalarPair --- src/librustc_mir/const_eval.rs | 14 ++++++++++++-- src/test/ui/consts/const-eval/union-ice.rs | 2 +- src/test/ui/consts/const-eval/union-ice.stderr | 8 +++++--- src/test/ui/issues/issue-54387.rs | 12 ++++++++++++ 4 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/issues/issue-54387.rs diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 82cc1b7f66166..dd6f5fc044618 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -17,7 +17,7 @@ use rustc::hir::{self, def_id::DefId}; use rustc::mir::interpret::ConstEvalErr; use rustc::mir; use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt}; -use rustc::ty::layout::{LayoutOf, TyLayout}; +use rustc::ty::layout::{self, LayoutOf, TyLayout}; use rustc::ty::subst::Subst; use rustc_data_structures::indexed_vec::IndexVec; @@ -90,8 +90,18 @@ pub fn eval_promoted<'a, 'mir, 'tcx>( pub fn op_to_const<'tcx>( ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>, op: OpTy<'tcx>, - normalize: bool, + may_normalize: bool, ) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> { + // We do not normalize just any data. Only scalar layout and fat pointers. + let normalize = may_normalize + && match op.layout.abi { + layout::Abi::Scalar(..) => true, + layout::Abi::ScalarPair(..) => { + // Must be a fat pointer + op.layout.ty.builtin_deref(true).is_some() + }, + _ => false, + }; let normalized_op = if normalize { ecx.try_read_value(op)? } else { diff --git a/src/test/ui/consts/const-eval/union-ice.rs b/src/test/ui/consts/const-eval/union-ice.rs index 0cdb78c97803c..5d50004e5549d 100644 --- a/src/test/ui/consts/const-eval/union-ice.rs +++ b/src/test/ui/consts/const-eval/union-ice.rs @@ -22,7 +22,7 @@ const UNION: DummyUnion = DummyUnion { field1: 1065353216 }; const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR this constant cannot be used -const FIELD_PATH: Struct = Struct { //~ ERROR this constant cannot be used +const FIELD_PATH: Struct = Struct { //~ ERROR this constant likely exhibits undefined behavior a: 42, b: unsafe { UNION.field3 }, }; diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index e8a7b2f500561..ec51802681e0d 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -6,14 +6,16 @@ LL | const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR this constant can | = note: #[deny(const_err)] on by default -error: this constant cannot be used +error[E0080]: this constant likely exhibits undefined behavior --> $DIR/union-ice.rs:25:1 | -LL | / const FIELD_PATH: Struct = Struct { //~ ERROR this constant cannot be used +LL | / const FIELD_PATH: Struct = Struct { //~ ERROR this constant likely exhibits undefined behavior LL | | a: 42, LL | | b: unsafe { UNION.field3 }, LL | | }; - | |__^ attempted to read undefined bytes + | |__^ type validation failed: encountered undefined bytes at .b + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: this constant likely exhibits undefined behavior --> $DIR/union-ice.rs:35:1 diff --git a/src/test/ui/issues/issue-54387.rs b/src/test/ui/issues/issue-54387.rs new file mode 100644 index 0000000000000..ac1033add0ee4 --- /dev/null +++ b/src/test/ui/issues/issue-54387.rs @@ -0,0 +1,12 @@ +// compile-pass + +pub struct GstRc { + _obj: *const (), + _borrowed: bool, +} + +const FOO: Option = None; + +fn main() { + let _meh = FOO; +}