diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 31541842e21..ef8d0bb1e27 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -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, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index ad841a57e78..8e026098850 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -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> 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]