a bit of meta-related cleanup on Projectable

This commit is contained in:
Ralf Jung 2023-08-17 18:58:56 +02:00
parent a09df43d9f
commit 7cdeff266c
3 changed files with 32 additions and 36 deletions

View File

@ -295,9 +295,9 @@ fn layout(&self) -> TyAndLayout<'tcx> {
}
#[inline(always)]
fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta<Prov>> {
fn meta(&self) -> MemPlaceMeta<Prov> {
debug_assert!(self.layout.is_sized()); // unsized ImmTy can only exist temporarily and should never reach this here
Ok(MemPlaceMeta::None)
MemPlaceMeta::None
}
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
@ -326,14 +326,14 @@ fn layout(&self) -> TyAndLayout<'tcx> {
}
#[inline]
fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta<Prov>> {
Ok(match self.as_mplace_or_imm() {
fn meta(&self) -> MemPlaceMeta<Prov> {
match self.as_mplace_or_imm() {
Left(mplace) => mplace.meta,
Right(_) => {
debug_assert!(self.layout.is_sized(), "unsized immediates are not a thing");
MemPlaceMeta::None
}
})
}
}
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(

View File

@ -13,7 +13,7 @@
use rustc_middle::ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Ty;
use rustc_target::abi::{self, Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_VARIANT};
use rustc_target::abi::{Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_VARIANT};
use super::{
alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
@ -48,27 +48,6 @@ pub fn has_meta(self) -> bool {
Self::None => false,
}
}
pub(crate) fn len<'tcx>(
&self,
layout: TyAndLayout<'tcx>,
cx: &impl HasDataLayout,
) -> InterpResult<'tcx, u64> {
if layout.is_unsized() {
// We need to consult `meta` metadata
match layout.ty.kind() {
ty::Slice(..) | ty::Str => self.unwrap_meta().to_target_usize(cx),
_ => bug!("len not supported on unsized type {:?}", layout.ty),
}
} else {
// Go through the layout. There are lots of types that support a length,
// e.g., SIMD types. (But not all repr(simd) types even have FieldsShape::Array!)
match layout.fields {
abi::FieldsShape::Array { count, .. } => Ok(count),
_ => bug!("len not supported on sized type {:?}", layout.ty),
}
}
}
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
@ -224,8 +203,8 @@ fn layout(&self) -> TyAndLayout<'tcx> {
}
#[inline(always)]
fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta<Prov>> {
Ok(self.meta)
fn meta(&self) -> MemPlaceMeta<Prov> {
self.meta
}
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
@ -257,14 +236,14 @@ fn layout(&self) -> TyAndLayout<'tcx> {
}
#[inline]
fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta<Prov>> {
Ok(match self.as_mplace_or_local() {
fn meta(&self) -> MemPlaceMeta<Prov> {
match self.as_mplace_or_local() {
Left(mplace) => mplace.meta,
Right(_) => {
debug_assert!(self.layout.is_sized(), "unsized locals should live in memory");
MemPlaceMeta::None
}
})
}
}
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(

View File

@ -25,13 +25,28 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
fn layout(&self) -> TyAndLayout<'tcx>;
/// Get the metadata of a wide value.
fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta<Prov>>;
fn meta(&self) -> MemPlaceMeta<Prov>;
/// Get the length of a slice/string/array stored here.
fn len<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
&self,
ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, u64> {
self.meta()?.len(self.layout(), ecx)
let layout = self.layout();
if layout.is_unsized() {
// We need to consult `meta` metadata
match layout.ty.kind() {
ty::Slice(..) | ty::Str => self.meta().unwrap_meta().to_target_usize(ecx),
_ => bug!("len not supported on unsized type {:?}", layout.ty),
}
} else {
// Go through the layout. There are lots of types that support a length,
// e.g., SIMD types. (But not all repr(simd) types even have FieldsShape::Array!)
match layout.fields {
abi::FieldsShape::Array { count, .. } => Ok(count),
_ => bug!("len not supported on sized type {:?}", layout.ty),
}
}
}
/// Offset the value by the given amount, replacing the layout and metadata.
@ -43,6 +58,7 @@ fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, Self>;
#[inline]
fn offset<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
&self,
offset: Size,
@ -53,6 +69,7 @@ fn offset<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
self.offset_with_meta(offset, MemPlaceMeta::None, layout, ecx)
}
#[inline]
fn transmute<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
&self,
layout: TyAndLayout<'tcx>,
@ -125,7 +142,7 @@ pub fn project_field<P: Projectable<'tcx, M::Provenance>>(
// But const-prop actually feeds us such nonsense MIR! (see test `const_prop/issue-86351.rs`)
throw_inval!(ConstPropNonsense);
}
let base_meta = base.meta()?;
let base_meta = base.meta();
// Re-use parent metadata to determine dynamic field layout.
// With custom DSTS, this *will* execute user-defined code, but the same
// happens at run-time so that's okay.
@ -153,7 +170,7 @@ pub fn project_downcast<P: Projectable<'tcx, M::Provenance>>(
base: &P,
variant: VariantIdx,
) -> InterpResult<'tcx, P> {
assert!(!base.meta()?.has_meta());
assert!(!base.meta().has_meta());
// Downcasts only change the layout.
// (In particular, no check about whether this is even the active variant -- that's by design,
// see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.)