Don't ICE when pattern matching packed structs

This commit is contained in:
Oliver Scherer 2019-06-03 18:35:50 +02:00
parent 21b1bd69b0
commit 870a6dc230
2 changed files with 24 additions and 2 deletions

View file

@ -482,7 +482,12 @@ pub fn const_field<'tcx>(
trace!("const_field: {:?}, {:?}", field, value);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
// get the operand again
let op = ecx.eval_const_to_op(value, None).unwrap();
let mut op = ecx.eval_const_to_op(value, None).unwrap();
// adjust the alignment of `op` to the one of the allocation, since it may be a field of a
// packed struct and thus end up causing an alignment error if we read from it.
if let ConstValue::ByRef(_, alloc) = value.val {
op.force_alignment(alloc.align);
}
// downcast
let down = match variant {
None => op,

View file

@ -4,7 +4,9 @@
use std::convert::TryInto;
use rustc::{mir, ty};
use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx};
use rustc::ty::layout::{
self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx, Align,
};
use rustc::mir::interpret::{
GlobalId, AllocId, CheckInAllocMsg,
@ -177,6 +179,21 @@ impl<'tcx, Tag> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
}
}
impl<'tcx, Tag> OpTy<'tcx, Tag> {
/// This function exists solely for pattern matching. If we pattern match a packed struct with
/// an ADT field, the constant representing that field will have lost the information about the
/// packedness. We could clone the allocation and adjust the alignment, but that seems wasteful,
/// since the alignment is already encoded in the allocation. We know it is alright, because
/// validation checked everything before the initial constant entered match checking.
pub(crate) fn force_alignment(&mut self, align: Align) {
if let Operand::Indirect(mplace) = &mut self.op {
if align < mplace.align {
mplace.align = align;
}
}
}
}
impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag>
{
#[inline]