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)] #[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 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>>( fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
@ -326,14 +326,14 @@ fn layout(&self) -> TyAndLayout<'tcx> {
} }
#[inline] #[inline]
fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta<Prov>> { fn meta(&self) -> MemPlaceMeta<Prov> {
Ok(match self.as_mplace_or_imm() { match self.as_mplace_or_imm() {
Left(mplace) => mplace.meta, Left(mplace) => mplace.meta,
Right(_) => { Right(_) => {
debug_assert!(self.layout.is_sized(), "unsized immediates are not a thing"); debug_assert!(self.layout.is_sized(), "unsized immediates are not a thing");
MemPlaceMeta::None MemPlaceMeta::None
} }
}) }
} }
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>( 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;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Ty; 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::{ use super::{
alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg, alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
@ -48,27 +48,6 @@ pub fn has_meta(self) -> bool {
Self::None => false, 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)] #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
@ -224,8 +203,8 @@ fn layout(&self) -> TyAndLayout<'tcx> {
} }
#[inline(always)] #[inline(always)]
fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta<Prov>> { fn meta(&self) -> MemPlaceMeta<Prov> {
Ok(self.meta) self.meta
} }
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>( fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
@ -257,14 +236,14 @@ fn layout(&self) -> TyAndLayout<'tcx> {
} }
#[inline] #[inline]
fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta<Prov>> { fn meta(&self) -> MemPlaceMeta<Prov> {
Ok(match self.as_mplace_or_local() { match self.as_mplace_or_local() {
Left(mplace) => mplace.meta, Left(mplace) => mplace.meta,
Right(_) => { Right(_) => {
debug_assert!(self.layout.is_sized(), "unsized locals should live in memory"); debug_assert!(self.layout.is_sized(), "unsized locals should live in memory");
MemPlaceMeta::None MemPlaceMeta::None
} }
}) }
} }
fn offset_with_meta<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>( 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>; fn layout(&self) -> TyAndLayout<'tcx>;
/// Get the metadata of a wide value. /// 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>>( fn len<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
&self, &self,
ecx: &InterpCx<'mir, 'tcx, M>, ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, u64> { ) -> 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. /// 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>, ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, Self>; ) -> InterpResult<'tcx, Self>;
#[inline]
fn offset<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>( fn offset<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
&self, &self,
offset: Size, offset: Size,
@ -53,6 +69,7 @@ fn offset<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
self.offset_with_meta(offset, MemPlaceMeta::None, layout, ecx) self.offset_with_meta(offset, MemPlaceMeta::None, layout, ecx)
} }
#[inline]
fn transmute<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>( fn transmute<'mir, M: Machine<'mir, 'tcx, Provenance = Prov>>(
&self, &self,
layout: TyAndLayout<'tcx>, 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`) // But const-prop actually feeds us such nonsense MIR! (see test `const_prop/issue-86351.rs`)
throw_inval!(ConstPropNonsense); throw_inval!(ConstPropNonsense);
} }
let base_meta = base.meta()?; let base_meta = base.meta();
// Re-use parent metadata to determine dynamic field layout. // Re-use parent metadata to determine dynamic field layout.
// With custom DSTS, this *will* execute user-defined code, but the same // With custom DSTS, this *will* execute user-defined code, but the same
// happens at run-time so that's okay. // happens at run-time so that's okay.
@ -153,7 +170,7 @@ pub fn project_downcast<P: Projectable<'tcx, M::Provenance>>(
base: &P, base: &P,
variant: VariantIdx, variant: VariantIdx,
) -> InterpResult<'tcx, P> { ) -> InterpResult<'tcx, P> {
assert!(!base.meta()?.has_meta()); assert!(!base.meta().has_meta());
// Downcasts only change the layout. // Downcasts only change the layout.
// (In particular, no check about whether this is even the active variant -- that's by design, // (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.) // see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.)