diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 461285ff9bc1..8bb93d09a2aa 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -340,7 +340,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { let field = field.try_into().unwrap(); let field_layout = op.layout.field(self, field)?; - if field_layout.size.bytes() == 0 { + if field_layout.is_zst() { let val = Value::Scalar(Scalar::zst().into()); return Ok(OpTy { op: Operand::Immediate(val), layout: field_layout }); } @@ -397,9 +397,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Field(field, _) => self.operand_field(base, field.index() as u64)?, Downcast(_, variant) => self.operand_downcast(base, variant)?, Deref => self.deref_operand(base)?.into(), - // The rest should only occur as mplace, we do not use Immediates for types - // allowing such operations. This matches place_projection forcing an allocation. - Subslice { .. } | ConstantIndex { .. } | Index(_) => { + Subslice { .. } | ConstantIndex { .. } | Index(_) => if base.layout.is_zst() { + OpTy { + op: Operand::Immediate(Value::Scalar(Scalar::zst().into())), + // the actual index doesn't matter, so we just pick a convenient one like 0 + layout: base.layout.field(self, 0)?, + } + } else { + // The rest should only occur as mplace, we do not use Immediates for types + // allowing such operations. This matches place_projection forcing an allocation. let mplace = base.to_mem_place(); self.mplace_projection(mplace, proj_elem)?.into() } diff --git a/src/test/ui/consts/const-eval/zst_operand_eval.rs b/src/test/ui/consts/const-eval/zst_operand_eval.rs new file mode 100644 index 000000000000..c6deb88d4f1a --- /dev/null +++ b/src/test/ui/consts/const-eval/zst_operand_eval.rs @@ -0,0 +1,5 @@ +// compile-pass + +static ASSERT: () = [()][(std::mem::size_of::() != 4) as usize]; + +fn main() {}