Skip to content

Commit 7cbcdae

Browse files
committed
Auto merge of #54693 - RalfJung:ctfe-scalar-pair-undef, r=oli-obk
do not normalize all non-scalar constants to a ConstValue::ScalarPair We still need `ConstValue::ScalarPair` for match handling (matching slices and strings), but that will never see anything `Undef`. For non-fat-ptr `ScalarPair`, just point to the allocation like larger data structures do. Fixes #54387 r? @eddyb
2 parents de3d640 + d62aa3e commit 7cbcdae

File tree

19 files changed

+166
-150
lines changed

19 files changed

+166
-150
lines changed

src/librustc/ich/impls_ty.rs

-5
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,6 @@ for ::mir::interpret::ConstValue<'gcx> {
391391
}
392392
}
393393

394-
impl_stable_hash_for!(enum mir::interpret::ScalarMaybeUndef {
395-
Scalar(v),
396-
Undef
397-
});
398-
399394
impl_stable_hash_for!(struct mir::interpret::Pointer {
400395
alloc_id,
401396
offset

src/librustc/mir/interpret/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub use self::error::{
2323
FrameInfo, ConstEvalResult,
2424
};
2525

26-
pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef};
26+
pub use self::value::{Scalar, ConstValue};
2727

2828
use std::fmt;
2929
use mir;

src/librustc/mir/interpret/value.rs

+9-99
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

@@ -340,96 +343,3 @@ pub enum Scalar<Id=AllocId> {
340343
/// relocation and its associated offset together as a `Pointer` here.
341344
Ptr(Pointer<Id>),
342345
}
343-
344-
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
345-
pub enum ScalarMaybeUndef<Id=AllocId> {
346-
Scalar(Scalar<Id>),
347-
Undef,
348-
}
349-
350-
impl From<Scalar> for ScalarMaybeUndef {
351-
#[inline(always)]
352-
fn from(s: Scalar) -> Self {
353-
ScalarMaybeUndef::Scalar(s)
354-
}
355-
}
356-
357-
impl<'tcx> ScalarMaybeUndef {
358-
#[inline]
359-
pub fn not_undef(self) -> EvalResult<'static, Scalar> {
360-
match self {
361-
ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
362-
ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))),
363-
}
364-
}
365-
366-
#[inline(always)]
367-
pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
368-
self.not_undef()?.to_ptr()
369-
}
370-
371-
#[inline(always)]
372-
pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
373-
self.not_undef()?.to_bits(target_size)
374-
}
375-
376-
#[inline(always)]
377-
pub fn to_bool(self) -> EvalResult<'tcx, bool> {
378-
self.not_undef()?.to_bool()
379-
}
380-
381-
#[inline(always)]
382-
pub fn to_char(self) -> EvalResult<'tcx, char> {
383-
self.not_undef()?.to_char()
384-
}
385-
386-
#[inline(always)]
387-
pub fn to_f32(self) -> EvalResult<'tcx, f32> {
388-
self.not_undef()?.to_f32()
389-
}
390-
391-
#[inline(always)]
392-
pub fn to_f64(self) -> EvalResult<'tcx, f64> {
393-
self.not_undef()?.to_f64()
394-
}
395-
396-
#[inline(always)]
397-
pub fn to_u8(self) -> EvalResult<'tcx, u8> {
398-
self.not_undef()?.to_u8()
399-
}
400-
401-
#[inline(always)]
402-
pub fn to_u32(self) -> EvalResult<'tcx, u32> {
403-
self.not_undef()?.to_u32()
404-
}
405-
406-
#[inline(always)]
407-
pub fn to_u64(self) -> EvalResult<'tcx, u64> {
408-
self.not_undef()?.to_u64()
409-
}
410-
411-
#[inline(always)]
412-
pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
413-
self.not_undef()?.to_usize(cx)
414-
}
415-
416-
#[inline(always)]
417-
pub fn to_i8(self) -> EvalResult<'tcx, i8> {
418-
self.not_undef()?.to_i8()
419-
}
420-
421-
#[inline(always)]
422-
pub fn to_i32(self) -> EvalResult<'tcx, i32> {
423-
self.not_undef()?.to_i32()
424-
}
425-
426-
#[inline(always)]
427-
pub fn to_i64(self) -> EvalResult<'tcx, i64> {
428-
self.not_undef()?.to_i64()
429-
}
430-
431-
#[inline(always)]
432-
pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> {
433-
self.not_undef()?.to_isize(cx)
434-
}
435-
}

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::Resu
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/eval_context.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,13 @@ use rustc_data_structures::indexed_vec::IndexVec;
2525
use rustc::mir::interpret::{
2626
GlobalId, Scalar, FrameInfo, AllocId,
2727
EvalResult, EvalErrorKind,
28-
ScalarMaybeUndef,
2928
truncate, sign_extend,
3029
};
3130

3231
use syntax::source_map::{self, Span};
3332

3433
use super::{
35-
Value, Operand, MemPlace, MPlaceTy, Place,
34+
Value, Operand, MemPlace, MPlaceTy, Place, ScalarMaybeUndef,
3635
Memory, Machine
3736
};
3837

src/librustc_mir/interpret/memory.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ use std::ptr;
2121

2222
use rustc::ty::{self, Instance, query::TyCtxtAt};
2323
use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout};
24-
use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, ScalarMaybeUndef, GlobalId,
24+
use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, GlobalId,
2525
EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
2626
truncate};
2727
pub use rustc::mir::interpret::{write_target_uint, read_target_uint};
2828
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
2929

3030
use syntax::ast::Mutability;
3131

32-
use super::Machine;
32+
use super::{Machine, ScalarMaybeUndef};
3333

3434
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
3535
pub enum MemoryKind<T> {

src/librustc_mir/interpret/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ pub use self::memory::{Memory, MemoryKind};
3434

3535
pub use self::machine::Machine;
3636

37-
pub use self::operand::{Value, ValTy, Operand, OpTy};
37+
pub use self::operand::{ScalarMaybeUndef, Value, ValTy, Operand, OpTy};

0 commit comments

Comments
 (0)