Skip to content

Commit 27e438a

Browse files
committed
Make may_normalize explicit in the type system
1 parent 525983a commit 27e438a

File tree

1 file changed

+38
-34
lines changed

1 file changed

+38
-34
lines changed

src/librustc_mir/const_eval.rs

+38-34
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use syntax::ast::Mutability;
2121
use syntax::source_map::{Span, DUMMY_SP};
2222

2323
use crate::interpret::{self,
24-
PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Operand, Immediate, Scalar, Pointer,
24+
PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar, Pointer,
2525
RawConst, ConstValue,
2626
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
2727
Allocation, AllocId, MemoryKind,
@@ -62,45 +62,46 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
6262
eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
6363
}
6464

65-
// FIXME: These two conversion functions are bad hacks. We should just always use allocations.
66-
pub fn op_to_const<'tcx>(
65+
fn mplace_to_const<'tcx>(
66+
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
67+
mplace: MPlaceTy<'tcx>,
68+
) -> EvalResult<'tcx, ty::Const<'tcx>> {
69+
let MemPlace { ptr, align, meta } = *mplace;
70+
// extract alloc-offset pair
71+
assert!(meta.is_none());
72+
let ptr = ptr.to_ptr()?;
73+
let alloc = ecx.memory.get(ptr.alloc_id)?;
74+
assert!(alloc.align >= align);
75+
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= mplace.layout.size.bytes());
76+
let mut alloc = alloc.clone();
77+
alloc.align = align;
78+
// FIXME shouldn't it be the case that `mark_static_initialized` has already
79+
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
80+
let alloc = ecx.tcx.intern_const_alloc(alloc);
81+
let val = ConstValue::ByRef(ptr, alloc);
82+
Ok(ty::Const { val, ty: mplace.layout.ty })
83+
}
84+
85+
fn op_to_const<'tcx>(
6786
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
6887
op: OpTy<'tcx>,
69-
may_normalize: bool,
7088
) -> EvalResult<'tcx, ty::Const<'tcx>> {
7189
// We do not normalize just any data. Only scalar layout and slices.
72-
let normalize = may_normalize
73-
&& match op.layout.abi {
74-
layout::Abi::Scalar(..) => true,
75-
layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
76-
_ => false,
77-
};
90+
let normalize = match op.layout.abi {
91+
layout::Abi::Scalar(..) => true,
92+
layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
93+
_ => false,
94+
};
7895
let normalized_op = if normalize {
79-
Ok(*ecx.read_immediate(op).expect("normalization works on validated constants"))
96+
Err(*ecx.read_immediate(op).expect("normalization works on validated constants"))
8097
} else {
81-
match *op {
82-
Operand::Indirect(mplace) => Err(mplace),
83-
Operand::Immediate(val) => Ok(val)
84-
}
98+
op.try_as_mplace()
8599
};
86100
let val = match normalized_op {
87-
Err(MemPlace { ptr, align, meta }) => {
88-
// extract alloc-offset pair
89-
assert!(meta.is_none());
90-
let ptr = ptr.to_ptr()?;
91-
let alloc = ecx.memory.get(ptr.alloc_id)?;
92-
assert!(alloc.align >= align);
93-
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes());
94-
let mut alloc = alloc.clone();
95-
alloc.align = align;
96-
// FIXME shouldn't it be the case that `mark_static_initialized` has already
97-
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
98-
let alloc = ecx.tcx.intern_const_alloc(alloc);
99-
ConstValue::ByRef(ptr, alloc)
100-
},
101-
Ok(Immediate::Scalar(x)) =>
101+
Ok(mplace) => return mplace_to_const(ecx, mplace),
102+
Err(Immediate::Scalar(x)) =>
102103
ConstValue::Scalar(x.not_undef()?),
103-
Ok(Immediate::ScalarPair(a, b)) =>
104+
Err(Immediate::ScalarPair(a, b)) =>
104105
ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?),
105106
};
106107
Ok(ty::Const { val, ty: op.layout.ty })
@@ -486,7 +487,7 @@ pub fn const_field<'a, 'tcx>(
486487
let field = ecx.operand_field(down, field.index() as u64)?;
487488
// and finally move back to the const world, always normalizing because
488489
// this is not called for statics.
489-
op_to_const(&ecx, field, true)
490+
op_to_const(&ecx, field)
490491
})();
491492
result.map_err(|error| {
492493
let err = error_to_const_error(&ecx, error);
@@ -535,8 +536,11 @@ fn validate_and_turn_into_const<'a, 'tcx>(
535536
}
536537
// Now that we validated, turn this into a proper constant.
537538
let def_id = cid.instance.def.def_id();
538-
let normalize = tcx.is_static(def_id).is_none() && cid.promoted.is_none();
539-
op_to_const(&ecx, mplace.into(), normalize)
539+
if tcx.is_static(def_id).is_some() || cid.promoted.is_some() {
540+
mplace_to_const(&ecx, mplace)
541+
} else {
542+
op_to_const(&ecx, mplace.into())
543+
}
540544
})();
541545

542546
val.map_err(|error| {

0 commit comments

Comments
 (0)