Skip to content

Commit 392ea7a

Browse files
committed
do not normalize non-scalar constants to a ConstValue::ScalarPair
1 parent eb50e75 commit 392ea7a

File tree

10 files changed

+53
-37
lines changed

10 files changed

+53
-37
lines changed

src/librustc/mir/interpret/value.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,18 @@ pub enum ConstValue<'tcx> {
2424
/// to allow HIR creation to happen for everything before needing to be able to run constant
2525
/// evaluation
2626
Unevaluated(DefId, &'tcx Substs<'tcx>),
27+
2728
/// Used only for types with layout::abi::Scalar ABI and ZSTs
2829
///
2930
/// Not using the enum `Value` to encode that this must not be `Undef`
3031
Scalar(Scalar),
31-
/// Used only for types with layout::abi::ScalarPair
32+
33+
/// Used only for *fat pointers* with layout::abi::ScalarPair
3234
///
33-
/// The second field may be undef in case of `Option<usize>::None`
34-
ScalarPair(Scalar, ScalarMaybeUndef),
35-
/// Used only for the remaining cases. An allocation + offset into the allocation.
35+
/// Needed for pattern matching code related to slices and strings.
36+
ScalarPair(Scalar, Scalar),
37+
38+
/// An allocation + offset into the allocation.
3639
/// Invariant: The AllocId matches the allocation.
3740
ByRef(AllocId, &'tcx Allocation, Size),
3841
}
@@ -67,12 +70,12 @@ impl<'tcx> ConstValue<'tcx> {
6770
ConstValue::ScalarPair(val, Scalar::Bits {
6871
bits: len as u128,
6972
size: cx.data_layout().pointer_size.bytes() as u8,
70-
}.into())
73+
})
7174
}
7275

7376
#[inline]
7477
pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
75-
ConstValue::ScalarPair(val, Scalar::Ptr(vtable).into())
78+
ConstValue::ScalarPair(val, Scalar::Ptr(vtable))
7679
}
7780
}
7881

src/librustc/mir/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use hir::def::CtorKind;
1717
use hir::def_id::DefId;
1818
use hir::{self, HirId, InlineAsm};
1919
use middle::region;
20-
use mir::interpret::{ConstValue, EvalErrorKind, Scalar, ScalarMaybeUndef};
20+
use mir::interpret::{ConstValue, EvalErrorKind, Scalar};
2121
use mir::visit::MirVisitable;
2222
use rustc_apfloat::ieee::{Double, Single};
2323
use rustc_apfloat::Float;
@@ -2397,7 +2397,7 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const) -> fmt::Result {
23972397
// print string literals
23982398
if let ConstValue::ScalarPair(ptr, len) = value {
23992399
if let Scalar::Ptr(ptr) = ptr {
2400-
if let ScalarMaybeUndef::Scalar(Scalar::Bits { bits: len, .. }) = len {
2400+
if let Scalar::Bits { bits: len, .. } = len {
24012401
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
24022402
return ty::tls::with(|tcx| {
24032403
let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);

src/librustc_codegen_llvm/mir/operand.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use rustc::mir::interpret::ConstEvalErr;
11+
use rustc::mir::interpret::{ConstValue, ConstEvalErr};
1212
use rustc::mir;
13-
use rustc::mir::interpret::{ConstValue, ScalarMaybeUndef};
1413
use rustc::ty;
1514
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
1615
use rustc_data_structures::sync::Lrc;
@@ -114,15 +113,12 @@ impl OperandRef<'ll, 'tcx> {
114113
layout.scalar_pair_element_llvm_type(bx.cx, 0, true),
115114
);
116115
let b_layout = layout.scalar_pair_element_llvm_type(bx.cx, 1, true);
117-
let b_llval = match b {
118-
ScalarMaybeUndef::Scalar(b) => scalar_to_llvm(
119-
bx.cx,
120-
b,
121-
b_scalar,
122-
b_layout,
123-
),
124-
ScalarMaybeUndef::Undef => C_undef(b_layout),
125-
};
116+
let b_llval = scalar_to_llvm(
117+
bx.cx,
118+
b,
119+
b_scalar,
120+
b_layout,
121+
);
126122
OperandValue::Pair(a_llval, b_llval)
127123
},
128124
ConstValue::ByRef(_, alloc, offset) => {

src/librustc_mir/const_eval.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc::hir::{self, def_id::DefId};
1717
use rustc::mir::interpret::ConstEvalErr;
1818
use rustc::mir;
1919
use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
20-
use rustc::ty::layout::{LayoutOf, TyLayout};
20+
use rustc::ty::layout::{self, LayoutOf, TyLayout};
2121
use rustc::ty::subst::Subst;
2222
use rustc_data_structures::indexed_vec::IndexVec;
2323

@@ -97,8 +97,18 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
9797
pub fn op_to_const<'tcx>(
9898
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
9999
op: OpTy<'tcx>,
100-
normalize: bool,
100+
may_normalize: bool,
101101
) -> EvalResult<'tcx, &'tcx ty::Const<'tcx>> {
102+
// We do not normalize just any data. Only scalar layout and fat pointers.
103+
let normalize = may_normalize
104+
&& match op.layout.abi {
105+
layout::Abi::Scalar(..) => true,
106+
layout::Abi::ScalarPair(..) => {
107+
// Must be a fat pointer
108+
op.layout.ty.builtin_deref(true).is_some()
109+
},
110+
_ => false,
111+
};
102112
let normalized_op = if normalize {
103113
ecx.try_read_value(op)?
104114
} else {
@@ -125,7 +135,7 @@ pub fn op_to_const<'tcx>(
125135
Ok(Value::Scalar(x)) =>
126136
ConstValue::Scalar(x.not_undef()?),
127137
Ok(Value::ScalarPair(a, b)) =>
128-
ConstValue::ScalarPair(a.not_undef()?, b),
138+
ConstValue::ScalarPair(a.not_undef()?, b.not_undef()?),
129139
};
130140
Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, op.layout.ty))
131141
}

src/librustc_mir/hair/pattern/mod.rs

-7
Original file line numberDiff line numberDiff line change
@@ -1124,13 +1124,6 @@ pub fn compare_const_vals<'a, 'tcx>(
11241124
len_b,
11251125
),
11261126
) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
1127-
let len_a = len_a.not_undef().ok();
1128-
let len_b = len_b.not_undef().ok();
1129-
if len_a.is_none() || len_b.is_none() {
1130-
tcx.sess.struct_err("str slice len is undef").delay_as_bug();
1131-
}
1132-
let len_a = len_a?;
1133-
let len_b = len_b?;
11341127
if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
11351128
if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
11361129
if len_a == len_b {

src/librustc_mir/interpret/operand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
490490
Ok(Operand::Indirect(MemPlace::from_ptr(Pointer::new(id, offset), alloc.align)))
491491
},
492492
ConstValue::ScalarPair(a, b) =>
493-
Ok(Operand::Immediate(Value::ScalarPair(a.into(), b))),
493+
Ok(Operand::Immediate(Value::ScalarPair(a.into(), b.into()))),
494494
ConstValue::Scalar(x) =>
495495
Ok(Operand::Immediate(Value::Scalar(x.into()))),
496496
}

src/librustc_mir/monomorphize/collector.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
193193

194194
use rustc::hir::Node;
195195
use rustc::hir::def_id::DefId;
196-
use rustc::mir::interpret::{AllocId, ConstValue, ScalarMaybeUndef};
196+
use rustc::mir::interpret::{AllocId, ConstValue};
197197
use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
198198
use rustc::ty::subst::Substs;
199199
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
@@ -1263,11 +1263,11 @@ fn collect_const<'a, 'tcx>(
12631263
};
12641264
match val {
12651265
ConstValue::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
1266-
ConstValue::ScalarPair(Scalar::Ptr(a), ScalarMaybeUndef::Scalar(Scalar::Ptr(b))) => {
1266+
ConstValue::ScalarPair(Scalar::Ptr(a), Scalar::Ptr(b)) => {
12671267
collect_miri(tcx, a.alloc_id, output);
12681268
collect_miri(tcx, b.alloc_id, output);
12691269
}
1270-
ConstValue::ScalarPair(_, ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr))) |
1270+
ConstValue::ScalarPair(_, Scalar::Ptr(ptr)) |
12711271
ConstValue::ScalarPair(Scalar::Ptr(ptr), _) |
12721272
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
12731273
collect_miri(tcx, ptr.alloc_id, output),

src/test/ui/consts/const-eval/union-ice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const UNION: DummyUnion = DummyUnion { field1: 1065353216 };
2222

2323
const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR this constant cannot be used
2424

25-
const FIELD_PATH: Struct = Struct { //~ ERROR this constant cannot be used
25+
const FIELD_PATH: Struct = Struct { //~ ERROR this constant likely exhibits undefined behavior
2626
a: 42,
2727
b: unsafe { UNION.field3 },
2828
};

src/test/ui/consts/const-eval/union-ice.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ LL | const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR this constant can
66
|
77
= note: #[deny(const_err)] on by default
88

9-
error: this constant cannot be used
9+
error[E0080]: this constant likely exhibits undefined behavior
1010
--> $DIR/union-ice.rs:25:1
1111
|
12-
LL | / const FIELD_PATH: Struct = Struct { //~ ERROR this constant cannot be used
12+
LL | / const FIELD_PATH: Struct = Struct { //~ ERROR this constant likely exhibits undefined behavior
1313
LL | | a: 42,
1414
LL | | b: unsafe { UNION.field3 },
1515
LL | | };
16-
| |__^ attempted to read undefined bytes
16+
| |__^ type validation failed: encountered undefined bytes at .b
17+
|
18+
= 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
1719

1820
error[E0080]: this constant likely exhibits undefined behavior
1921
--> $DIR/union-ice.rs:35:1

src/test/ui/issues/issue-54387.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// compile-pass
2+
3+
pub struct GstRc {
4+
_obj: *const (),
5+
_borrowed: bool,
6+
}
7+
8+
const FOO: Option<GstRc> = None;
9+
10+
fn main() {
11+
let _meh = FOO;
12+
}

0 commit comments

Comments
 (0)