Auto merge of #94527 - oli-obk:undef_scalars, r=nagisa,erikdesjardin
Let CTFE to handle partially uninitialized unions without marking the entire value as uninitialized. follow up to #94411 To fix https://github.com/rust-lang/rust/issues/69488 and by extension fix https://github.com/rust-lang/rust/issues/94371, we should stop treating types like `MaybeUninit<usize>` as something that the `Scalar` type in the interpreter engine can represent. So we add a new field to `abi::Primitive` that records whether the primitive is nested in a union cc `@RalfJung` r? `@ghost`
This commit is contained in:
commit
f262ca12aa
42 changed files with 466 additions and 333 deletions
|
@ -10,7 +10,7 @@ use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
|
|||
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
|
||||
use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty};
|
||||
use rustc_middle::{mir, ty};
|
||||
use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding};
|
||||
use rustc_target::abi::{self, Abi, HasDataLayout, Size, TagEncoding};
|
||||
use rustc_target::abi::{VariantIdx, Variants};
|
||||
|
||||
use super::{
|
||||
|
@ -265,16 +265,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}));
|
||||
};
|
||||
|
||||
// It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point.
|
||||
// However, `MaybeUninit<u64>` is considered a `Scalar` as far as its layout is concerned --
|
||||
// and yet cannot be represented by an interpreter `Scalar`, since we have to handle the
|
||||
// case where some of the bytes are initialized and others are not. So, we need an extra
|
||||
// check that walks over the type of `mplace` to make sure it is truly correct to treat this
|
||||
// like a `Scalar` (or `ScalarPair`).
|
||||
match mplace.layout.abi {
|
||||
Abi::Scalar(..) => {
|
||||
Abi::Scalar(abi::Scalar::Initialized { .. }) => {
|
||||
let scalar = alloc.read_scalar(alloc_range(Size::ZERO, mplace.layout.size))?;
|
||||
Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout }))
|
||||
}
|
||||
Abi::ScalarPair(a, b) => {
|
||||
Abi::ScalarPair(
|
||||
abi::Scalar::Initialized { value: a, .. },
|
||||
abi::Scalar::Initialized { value: b, .. },
|
||||
) => {
|
||||
// We checked `ptr_align` above, so all fields will have the alignment they need.
|
||||
// We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
|
||||
// which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
|
||||
let (a, b) = (a.value, b.value);
|
||||
let (a_size, b_size) = (a.size(self), b.size(self));
|
||||
let b_offset = a_size.align_to(b.align(self).abi);
|
||||
assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields
|
||||
|
@ -676,7 +684,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
// may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
|
||||
|
||||
// Get layout for tag.
|
||||
let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?;
|
||||
let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;
|
||||
|
||||
// Read tag and sanity-check `tag_layout`.
|
||||
let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue