diff options
| author | bors <bors@rust-lang.org> | 2022-04-05 16:46:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-04-05 16:46:13 +0000 |
| commit | f262ca12aac76152c4b46cefcf8300f0249a5eb2 (patch) | |
| tree | 50b8a31fd3869a4c0805e26f6a6f2127c9a82988 /compiler/rustc_const_eval/src | |
| parent | d4c7839f73e4a84c75e8708adaafb9fafcb668f0 (diff) | |
| parent | d57b7559090266fc0db2616bcfe8286739ee131d (diff) | |
| download | rust-f262ca12aac76152c4b46cefcf8300f0249a5eb2.tar.gz rust-f262ca12aac76152c4b46cefcf8300f0249a5eb2.zip | |
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`
Diffstat (limited to 'compiler/rustc_const_eval/src')
6 files changed, 27 insertions, 18 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index b81a4bfe149..b856d1708ab 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, subst::Subst, TyCtxt}; use rustc_span::source_map::Span; -use rustc_target::abi::Abi; +use rustc_target::abi::{self, Abi}; use std::borrow::Cow; use std::convert::TryInto; @@ -118,7 +118,7 @@ pub(super) fn op_to_const<'tcx>( // the usual cases of extracting e.g. a `usize`, without there being a real use case for the // `Undef` situation. let try_as_immediate = match op.layout.abi { - Abi::Scalar(..) => true, + Abi::Scalar(abi::Scalar::Initialized { .. }) => true, Abi::ScalarPair(..) => match op.layout.ty.kind() { ty::Ref(_, inner, _) => match *inner.kind() { ty::Slice(elem) => elem == ecx.tcx.types.u8, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index a956a478cef..3cc237faf69 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -188,7 +188,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = self.read_scalar(&args[0])?.check_init()?; let bits = val.to_bits(layout_of.size)?; let kind = match layout_of.abi { - Abi::Scalar(scalar) => scalar.value, + Abi::Scalar(scalar) => scalar.primitive(), _ => span_bug!( self.cur_span(), "{} called on invalid type {:?}", diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 3012f763b80..ee1ba608293 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -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)?)?; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index c37973bd166..5f7f52ef9e9 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -772,13 +772,11 @@ where // 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) = match dest.layout.abi { - Abi::ScalarPair(a, b) => (a.value, b.value), - _ => span_bug!( + let Abi::ScalarPair(a, b) = dest.layout.abi else { span_bug!( self.cur_span(), "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}", dest.layout - ), + ) }; let (a_size, b_size) = (a.size(&tcx), b.size(&tcx)); let b_offset = a_size.align_to(b.align(&tcx).abi); @@ -1046,7 +1044,7 @@ where // raw discriminants for enums are isize or bigger during // their computation, but the in-memory tag is the smallest possible // representation - let size = tag_layout.value.size(self); + let size = tag_layout.size(self); let tag_val = size.truncate(discr_val); let tag_dest = self.place_field(dest, tag_field)?; @@ -1070,7 +1068,7 @@ where .expect("overflow computing relative variant idx"); // We need to use machine arithmetic when taking into account `niche_start`: // tag_val = variant_index_relative + niche_start_val - let tag_layout = self.layout_of(tag_layout.value.to_int_ty(*self.tcx))?; + let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?; let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); let variant_index_relative_val = ImmTy::from_uint(variant_index_relative, tag_layout); diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index a7587652114..c2a38c6978b 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -189,12 +189,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // that will take care to make it UB to leave the range, just // like for transmute). (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => { - caller.value == callee.value + caller.primitive() == callee.primitive() } ( abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2), - ) => caller1.value == callee1.value && caller2.value == callee2.value, + ) => { + caller1.primitive() == callee1.primitive() + && caller2.primitive() == callee2.primitive() + } // Be conservative _ => false, } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 42ff7b19459..e5fd182f8b3 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -629,12 +629,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' op: &OpTy<'tcx, M::PointerTag>, scalar_layout: ScalarAbi, ) -> InterpResult<'tcx> { - if scalar_layout.valid_range.is_full_for(op.layout.size) { + if scalar_layout.valid_range(self.ecx).is_full_for(op.layout.size) { // Nothing to check return Ok(()); } // At least one value is excluded. - let valid_range = scalar_layout.valid_range; + let valid_range = scalar_layout.valid_range(self.ecx); let WrappingRange { start, end } = valid_range; let max_value = op.layout.size.unsigned_int_max(); assert!(end <= max_value); |
