Auto merge of #98846 - RalfJung:alignment-is-a-type-thing, r=oli-obk

interpret: track place alignment together with the type, not the value

This matches how I handle alignment in [MiniRust](https://github.com/RalfJung/minirust). I think it makes conceptually a lot more sense.
Fixes https://github.com/rust-lang/rust/issues/63085

r? `@oli-obk`
This commit is contained in:
bors 2022-07-05 01:23:09 +00:00
commit 4008dd8c6d
3 changed files with 118 additions and 95 deletions

View File

@ -808,7 +808,7 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
if !unwinding {
let op = self.access_local(&frame, mir::RETURN_PLACE, None)?;
let op = self.local_to_op(&frame, mir::RETURN_PLACE, None)?;
self.copy_op_transmute(&op, &frame.return_place)?;
trace!("{:?}", self.dump_place(*frame.return_place));
}
@ -981,8 +981,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
LocalValue::Live(Operand::Indirect(mplace)) => {
write!(
fmt,
" by align({}){} ref {:?}:",
mplace.align.bytes(),
" by {} ref {:?}:",
match mplace.meta {
MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
@ -1011,13 +1010,9 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(fmt, ": {:?}", self.ecx.dump_allocs(allocs.into_iter().flatten().collect()))
}
Place::Ptr(mplace) => match mplace.ptr.provenance.and_then(Provenance::get_alloc_id) {
Some(alloc_id) => write!(
fmt,
"by align({}) ref {:?}: {:?}",
mplace.align.bytes(),
mplace.ptr,
self.ecx.dump_alloc(alloc_id)
),
Some(alloc_id) => {
write!(fmt, "by ref {:?}: {:?}", mplace.ptr, self.ecx.dump_alloc(alloc_id))
}
ptr => write!(fmt, " integral by ref: {:?}", ptr),
},
}

View File

@ -10,7 +10,7 @@
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
use rustc_middle::ty::{ConstInt, DelaySpanBugEmitted, Ty};
use rustc_middle::{mir, ty};
use rustc_target::abi::{self, Abi, HasDataLayout, Size, TagEncoding};
use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding};
use rustc_target::abi::{VariantIdx, Variants};
use super::{
@ -177,10 +177,18 @@ pub enum Operand<Tag: Provenance = AllocId> {
pub struct OpTy<'tcx, Tag: Provenance = AllocId> {
op: Operand<Tag>, // Keep this private; it helps enforce invariants.
pub layout: TyAndLayout<'tcx>,
/// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct:
/// it needs to have a different alignment than the field type would usually have.
/// So we represent this here with a separate field that "overwrites" `layout.align`.
/// This means `layout.align` should never be used for an `OpTy`!
/// `None` means "alignment does not matter since this is a by-value operand"
/// (`Operand::Immediate`); this field is only relevant for `Operand::Indirect`.
/// Also CTFE ignores alignment anyway, so this is for Miri only.
pub align: Option<Align>,
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(OpTy<'_>, 80);
rustc_data_structures::static_assert_size!(OpTy<'_>, 88);
impl<'tcx, Tag: Provenance> std::ops::Deref for OpTy<'tcx, Tag> {
type Target = Operand<Tag>;
@ -193,28 +201,28 @@ fn deref(&self) -> &Operand<Tag> {
impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
OpTy { op: Operand::Indirect(*mplace), layout: mplace.layout }
OpTy { op: Operand::Indirect(*mplace), layout: mplace.layout, align: Some(mplace.align) }
}
}
impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self {
OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout }
OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout, align: Some(mplace.align) }
}
}
impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self {
OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout }
OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout, align: Some(mplace.align) }
}
}
impl<'tcx, Tag: Provenance> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
#[inline(always)]
fn from(val: ImmTy<'tcx, Tag>) -> Self {
OpTy { op: Operand::Immediate(val.imm), layout: val.layout }
OpTy { op: Operand::Immediate(val.imm), layout: val.layout, align: None }
}
}
@ -450,7 +458,7 @@ pub fn operand_field(
),
};
Ok(OpTy { op: Operand::Immediate(field_val), layout: field_layout })
Ok(OpTy { op: Operand::Immediate(field_val), layout: field_layout, align: None })
}
pub fn operand_index(
@ -522,7 +530,7 @@ pub fn operand_to_simd(
///
/// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an
/// OpTy from a local
pub fn access_local(
pub fn local_to_op(
&self,
frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
local: mir::Local,
@ -535,7 +543,7 @@ pub fn access_local(
} else {
M::access_local(&self, frame, local)?
};
Ok(OpTy { op, layout })
Ok(OpTy { op, layout, align: Some(layout.align.abi) })
}
/// Every place can be read from, so we can turn them into an operand.
@ -549,10 +557,10 @@ pub fn place_to_op(
let op = match **place {
Place::Ptr(mplace) => Operand::Indirect(mplace),
Place::Local { frame, local } => {
*self.access_local(&self.stack()[frame], local, None)?
*self.local_to_op(&self.stack()[frame], local, None)?
}
};
Ok(OpTy { op, layout: place.layout })
Ok(OpTy { op, layout: place.layout, align: Some(place.align) })
}
/// Evaluate a place with the goal of reading from it. This lets us sometimes
@ -566,7 +574,7 @@ pub fn eval_place_to_op(
// here is not the entire place.
let layout = if place.projection.is_empty() { layout } else { None };
let base_op = self.access_local(self.frame(), place.local, layout)?;
let base_op = self.local_to_op(self.frame(), place.local, layout)?;
let op = place
.projection
@ -603,11 +611,11 @@ pub fn eval_operand(
Constant(ref constant) => {
let val =
self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?;
// This can still fail:
// * During ConstProp, with `TooGeneric` or since the `required_consts` were not all
// checked yet.
// * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
self.mir_const_to_op(&val, layout)?
}
};
@ -683,7 +691,7 @@ pub(crate) fn const_val_to_op(
// We rely on mutability being set correctly in that allocation to prevent writes
// where none should happen.
let ptr = self.global_base_pointer(Pointer::new(id, offset))?;
Operand::Indirect(MemPlace::from_ptr(ptr.into(), layout.align.abi))
Operand::Indirect(MemPlace::from_ptr(ptr.into()))
}
ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x)?.into()),
ConstValue::Slice { data, start, end } => {
@ -700,7 +708,7 @@ pub(crate) fn const_val_to_op(
))
}
};
Ok(OpTy { op, layout })
Ok(OpTy { op, layout, align: Some(layout.align.abi) })
}
/// Read discriminant, return the runtime value as well as the variant index.

View File

@ -57,7 +57,6 @@ fn has_meta(self) -> bool {
pub struct MemPlace<Tag: Provenance = AllocId> {
/// The pointer can be a pure integer, with the `None` tag.
pub ptr: Pointer<Option<Tag>>,
pub align: Align,
/// Metadata for unsized places. Interpretation is up to the type.
/// Must not be present for sized types, but can be missing for unsized types
/// (e.g., `extern type`).
@ -65,7 +64,7 @@ pub struct MemPlace<Tag: Provenance = AllocId> {
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(MemPlace, 48);
rustc_data_structures::static_assert_size!(MemPlace, 40);
#[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable, Debug)]
pub enum Place<Tag: Provenance = AllocId> {
@ -78,12 +77,17 @@ pub enum Place<Tag: Provenance = AllocId> {
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Place, 56);
rustc_data_structures::static_assert_size!(Place, 48);
#[derive(Copy, Clone, Debug)]
pub struct PlaceTy<'tcx, Tag: Provenance = AllocId> {
place: Place<Tag>, // Keep this private; it helps enforce invariants.
pub layout: TyAndLayout<'tcx>,
/// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct:
/// it needs to have a different alignment than the field type would usually have.
/// So we represent this here with a separate field that "overwrites" `layout.align`.
/// This means `layout.align` should never be used for a `PlaceTy`!
pub align: Align,
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@ -102,6 +106,11 @@ fn deref(&self) -> &Place<Tag> {
pub struct MPlaceTy<'tcx, Tag: Provenance = AllocId> {
mplace: MemPlace<Tag>,
pub layout: TyAndLayout<'tcx>,
/// rustc does not have a proper way to represent the type of a field of a `repr(packed)` struct:
/// it needs to have a different alignment than the field type would usually have.
/// So we represent this here with a separate field that "overwrites" `layout.align`.
/// This means `layout.align` should never be used for a `MPlaceTy`!
pub align: Align,
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@ -118,28 +127,28 @@ fn deref(&self) -> &MemPlace<Tag> {
impl<'tcx, Tag: Provenance> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
PlaceTy { place: Place::Ptr(*mplace), layout: mplace.layout }
PlaceTy { place: Place::Ptr(*mplace), layout: mplace.layout, align: mplace.align }
}
}
impl<'tcx, Tag: Provenance> From<&'_ MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: &MPlaceTy<'tcx, Tag>) -> Self {
PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout }
PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout, align: mplace.align }
}
}
impl<'tcx, Tag: Provenance> From<&'_ mut MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> {
#[inline(always)]
fn from(mplace: &mut MPlaceTy<'tcx, Tag>) -> Self {
PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout }
PlaceTy { place: Place::Ptr(**mplace), layout: mplace.layout, align: mplace.align }
}
}
impl<Tag: Provenance> MemPlace<Tag> {
#[inline(always)]
pub fn from_ptr(ptr: Pointer<Option<Tag>>, align: Align) -> Self {
MemPlace { ptr, align, meta: MemPlaceMeta::None }
pub fn from_ptr(ptr: Pointer<Option<Tag>>) -> Self {
MemPlace { ptr, meta: MemPlaceMeta::None }
}
/// Adjust the provenance of the main pointer (metadata is unaffected).
@ -170,11 +179,7 @@ pub fn offset<'tcx>(
meta: MemPlaceMeta<Tag>,
cx: &impl HasDataLayout,
) -> InterpResult<'tcx, Self> {
Ok(MemPlace {
ptr: self.ptr.offset(offset, cx)?,
align: self.align.restrict_for_offset(offset),
meta,
})
Ok(MemPlace { ptr: self.ptr.offset(offset, cx)?, meta })
}
}
@ -185,7 +190,7 @@ pub fn dangling(layout: TyAndLayout<'tcx>) -> Self {
let align = layout.align.abi;
let ptr = Pointer::new(None, Size::from_bytes(align.bytes())); // no provenance, absolute address
// `Poison` this to make sure that the pointer value `ptr` is never observable by the program.
MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout }
MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::Poison }, layout, align }
}
#[inline]
@ -196,12 +201,16 @@ pub fn offset(
layout: TyAndLayout<'tcx>,
cx: &impl HasDataLayout,
) -> InterpResult<'tcx, Self> {
Ok(MPlaceTy { mplace: self.mplace.offset(offset, meta, cx)?, layout })
Ok(MPlaceTy {
mplace: self.mplace.offset(offset, meta, cx)?,
align: self.align.restrict_for_offset(offset),
layout,
})
}
#[inline]
pub fn from_aligned_ptr(ptr: Pointer<Option<Tag>>, layout: TyAndLayout<'tcx>) -> Self {
MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align.abi), layout }
MPlaceTy { mplace: MemPlace::from_ptr(ptr), layout, align: layout.align.abi }
}
#[inline]
@ -210,10 +219,10 @@ pub fn from_aligned_ptr_with_meta(
layout: TyAndLayout<'tcx>,
meta: MemPlaceMeta<Tag>,
) -> Self {
let mut mplace = MemPlace::from_ptr(ptr, layout.align.abi);
let mut mplace = MemPlace::from_ptr(ptr);
mplace.meta = meta;
MPlaceTy { mplace, layout }
MPlaceTy { mplace, layout, align: layout.align.abi }
}
#[inline]
@ -250,7 +259,9 @@ impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> {
/// read from the resulting mplace, not to get its address back.
pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Tag>, ImmTy<'tcx, Tag>> {
match **self {
Operand::Indirect(mplace) => Ok(MPlaceTy { mplace, layout: self.layout }),
Operand::Indirect(mplace) => {
Ok(MPlaceTy { mplace, layout: self.layout, align: self.align.unwrap() })
}
Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout)),
Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)),
}
@ -264,20 +275,19 @@ pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Tag> {
}
}
impl<Tag: Provenance> Place<Tag> {
impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> {
/// A place is either an mplace or some local.
#[inline]
pub fn assert_mem_place(self) -> MemPlace<Tag> {
match self {
Place::Ptr(mplace) => mplace,
_ => bug!("assert_mem_place: expected Place::Ptr, got {:?}", self),
pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Tag>, (usize, mir::Local)> {
match **self {
Place::Ptr(mplace) => Ok(MPlaceTy { mplace, layout: self.layout, align: self.align }),
Place::Local { frame, local } => Err((frame, local)),
}
}
}
impl<'tcx, Tag: Provenance> PlaceTy<'tcx, Tag> {
#[inline]
pub fn assert_mem_place(self) -> MPlaceTy<'tcx, Tag> {
MPlaceTy { mplace: self.place.assert_mem_place(), layout: self.layout }
self.try_as_mplace().unwrap()
}
}
@ -306,16 +316,10 @@ pub fn ref_to_mplace(
Immediate::ScalarPair(ptr, meta) => (ptr, MemPlaceMeta::Meta(meta.check_init()?)),
};
let mplace = MemPlace {
ptr: self.scalar_to_ptr(ptr.check_init()?)?,
// We could use the run-time alignment here. For now, we do not, because
// the point of tracking the alignment here is to make sure that the *static*
// alignment information emitted with the loads is correct. The run-time
// alignment can only be more restrictive.
align: layout.align.abi,
meta,
};
Ok(MPlaceTy { mplace, layout })
let mplace = MemPlace { ptr: self.scalar_to_ptr(ptr.check_init()?)?, meta };
// When deref'ing a pointer, the *static* alignment given by the type is what matters.
let align = layout.align.abi;
Ok(MPlaceTy { mplace, layout, align })
}
/// Take an operand, representing a pointer, and dereference it to a place -- that
@ -368,7 +372,7 @@ fn check_mplace_access(
let (size, align) = self
.size_and_align_of_mplace(&mplace)?
.unwrap_or((mplace.layout.size, mplace.layout.align.abi));
assert!(mplace.mplace.align <= align, "dynamic alignment less strict than static one?");
assert!(mplace.align <= align, "dynamic alignment less strict than static one?");
let align = M::enforce_alignment(self).then_some(align);
self.check_ptr_access_align(mplace.ptr, size, align.unwrap_or(Align::ONE), msg)?;
Ok(())
@ -533,7 +537,7 @@ pub(super) fn mplace_projection(
Index(local) => {
let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.access_local(self.frame(), local, Some(layout))?;
let n = self.local_to_op(self.frame(), local, Some(layout))?;
let n = self.read_scalar(&n)?;
let n = n.to_machine_usize(self)?;
self.mplace_index(base, n)?
@ -608,11 +612,9 @@ pub fn place_downcast(
variant: VariantIdx,
) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
// Downcast just changes the layout
Ok(match base.place {
Place::Ptr(mplace) => {
self.mplace_downcast(&MPlaceTy { mplace, layout: base.layout }, variant)?.into()
}
Place::Local { .. } => {
Ok(match base.try_as_mplace() {
Ok(mplace) => self.mplace_downcast(&mplace, variant)?.into(),
Err(..) => {
let layout = base.layout.for_variant(self, variant);
PlaceTy { layout, ..*base }
}
@ -649,6 +651,16 @@ pub fn place_to_simd(
self.mplace_to_simd(&mplace)
}
pub fn local_to_place(
&self,
frame: usize,
local: mir::Local,
) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
let layout = self.layout_of_local(&self.stack()[frame], local, None)?;
let place = Place::Local { frame, local };
Ok(PlaceTy { place, layout, align: layout.align.abi })
}
/// Computes a place. You should only use this if you intend to write into this
/// place; for reading, a more efficient alternative is `eval_place_to_op`.
#[instrument(skip(self), level = "debug")]
@ -656,11 +668,7 @@ pub fn eval_place(
&mut self,
place: mir::Place<'tcx>,
) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
let mut place_ty = PlaceTy {
// This works even for dead/uninitialized locals; we check further when writing
place: Place::Local { frame: self.frame_idx(), local: place.local },
layout: self.layout_of_local(self.frame(), place.local, None)?,
};
let mut place_ty = self.local_to_place(self.frame_idx(), place.local)?;
for elem in place.projection.iter() {
place_ty = self.place_projection(&place_ty, &elem)?
@ -668,14 +676,19 @@ pub fn eval_place(
trace!("{:?}", self.dump_place(place_ty.place));
// Sanity-check the type we ended up with.
debug_assert!(mir_assign_valid_types(
*self.tcx,
self.param_env,
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
place.ty(&self.frame().body.local_decls, *self.tcx).ty
)?)?,
place_ty.layout,
));
debug_assert!(
mir_assign_valid_types(
*self.tcx,
self.param_env,
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
place.ty(&self.frame().body.local_decls, *self.tcx).ty
)?)?,
place_ty.layout,
),
"eval_place of a MIR place with type {:?} produced an interpret place with type {:?}",
place.ty(&self.frame().body.local_decls, *self.tcx).ty,
place_ty.layout.ty,
);
Ok(place_ty)
}
@ -746,7 +759,7 @@ fn write_immediate_no_validate(
}
Place::Ptr(mplace) => mplace, // already referring to memory
};
let dest = MPlaceTy { mplace, layout: dest.layout };
let dest = MPlaceTy { mplace, layout: dest.layout, align: dest.align };
// This is already in memory, write there.
self.write_immediate_to_mplace_no_validate(src, &dest)
@ -808,9 +821,9 @@ fn write_immediate_to_mplace_no_validate(
}
pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
let mplace = match dest.place {
Place::Ptr(mplace) => MPlaceTy { mplace, layout: dest.layout },
Place::Local { frame, local } => {
let mplace = match dest.try_as_mplace() {
Ok(mplace) => mplace,
Err((frame, local)) => {
match M::access_local_mut(self, frame, local)? {
Ok(local) => match dest.layout.abi {
Abi::Scalar(_) => {
@ -830,7 +843,7 @@ pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::PointerTag>) -> InterpRes
},
Err(mplace) => {
// The local is in memory, go on below.
MPlaceTy { mplace, layout: dest.layout }
MPlaceTy { mplace, layout: dest.layout, align: dest.align }
}
}
}
@ -948,7 +961,7 @@ pub fn copy_op_transmute(
let dest = self.force_allocation(dest)?;
self.copy_op_no_validate(
src,
&PlaceTy::from(MPlaceTy { mplace: *dest, layout: src.layout }),
&PlaceTy::from(MPlaceTy { mplace: *dest, layout: src.layout, align: dest.align }),
)?;
if M::enforce_validity(self) {
@ -989,12 +1002,16 @@ pub fn force_allocation_maybe_sized(
.size_and_align_of(&meta, &local_layout)?
.expect("Cannot allocate for non-dyn-sized type");
let ptr = self.allocate_ptr(size, align, MemoryKind::Stack)?;
let mplace = MemPlace { ptr: ptr.into(), align, meta };
let mplace = MemPlace { ptr: ptr.into(), meta };
if let LocalValue::Live(Operand::Immediate(value)) = local_val {
// Preserve old value.
// We don't have to validate as we can assume the local
// was already valid for its type.
let mplace = MPlaceTy { mplace, layout: local_layout };
let mplace = MPlaceTy {
mplace,
layout: local_layout,
align: local_layout.align.abi,
};
self.write_immediate_to_mplace_no_validate(value, &mplace)?;
}
// Now we can call `access_mut` again, asserting it goes well,
@ -1009,7 +1026,7 @@ pub fn force_allocation_maybe_sized(
Place::Ptr(mplace) => (mplace, None),
};
// Return with the original layout, so that the caller can go on
Ok((MPlaceTy { mplace, layout: place.layout }, size))
Ok((MPlaceTy { mplace, layout: place.layout, align: place.align }, size))
}
#[inline(always)]
@ -1038,15 +1055,14 @@ pub fn allocate_str(
) -> MPlaceTy<'tcx, M::PointerTag> {
let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl);
let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self);
let mplace =
MemPlace { ptr: ptr.into(), align: Align::ONE, meta: MemPlaceMeta::Meta(meta) };
let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) };
let ty = self.tcx.mk_ref(
self.tcx.lifetimes.re_static,
ty::TypeAndMut { ty: self.tcx.types.str_, mutbl },
);
let layout = self.layout_of(ty).unwrap();
MPlaceTy { mplace, layout }
MPlaceTy { mplace, layout, align: layout.align.abi }
}
/// Writes the discriminant of the given variant.
@ -1166,7 +1182,11 @@ pub(super) fn unpack_dyn_trait(
assert_eq!(align, layout.align.abi);
}
let mplace = MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..**mplace }, layout };
let mplace = MPlaceTy {
mplace: MemPlace { meta: MemPlaceMeta::None, ..**mplace },
layout,
align: layout.align.abi,
};
Ok((instance, mplace))
}
}