Skip to content

Commit 6077b7c

Browse files
committed
Auto merge of rust-lang#99013 - RalfJung:dont-poison-my-places, r=oli-obk
interpret: get rid of MemPlaceMeta::Poison This is achieved by refactoring the projection code (`{mplace,place,operand}_{downcast,field,index,...}`) so that we no longer need to call `assert_mem_place` in the operand handling.
2 parents 522abf6 + e3ef4fd commit 6077b7c

File tree

6 files changed

+15
-22
lines changed

6 files changed

+15
-22
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ pub(super) fn op_to_const<'tcx>(
165165
Ok(ref mplace) => to_const_value(mplace),
166166
// see comment on `let try_as_immediate` above
167167
Err(imm) => match *imm {
168+
_ if imm.layout.is_zst() => ConstValue::ZeroSized,
168169
Immediate::Scalar(x) => match x {
169170
ScalarMaybeUninit::Scalar(s) => ConstValue::Scalar(s),
170171
ScalarMaybeUninit::Uninit => to_const_value(&op.assert_mem_place()),

compiler/rustc_const_eval/src/const_eval/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ pub(crate) fn deref_mir_constant<'tcx>(
147147

148148
let ty = match mplace.meta {
149149
MemPlaceMeta::None => mplace.layout.ty,
150-
MemPlaceMeta::Poison => bug!("poison metadata in `deref_mir_constant`: {:#?}", mplace),
151150
// In case of unsized types, figure out the real type behind.
152151
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
153152
ty::Str => bug!("there's no sized equivalent of a `str`"),

compiler/rustc_const_eval/src/interpret/eval_context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
987987
" by {} ref {:?}:",
988988
match mplace.meta {
989989
MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
990-
MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
990+
MemPlaceMeta::None => String::new(),
991991
},
992992
mplace.ptr,
993993
)?;

compiler/rustc_const_eval/src/interpret/place.rs

+9-16
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@ pub enum MemPlaceMeta<Tag: Provenance = AllocId> {
2424
Meta(Scalar<Tag>),
2525
/// `Sized` types or unsized `extern type`
2626
None,
27-
/// The address of this place may not be taken. This protects the `MemPlace` from coming from
28-
/// a ZST Operand without a backing allocation and being converted to an integer address. This
29-
/// should be impossible, because you can't take the address of an operand, but this is a second
30-
/// protection layer ensuring that we don't mess up.
31-
Poison,
3227
}
3328

3429
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@@ -38,15 +33,16 @@ impl<Tag: Provenance> MemPlaceMeta<Tag> {
3833
pub fn unwrap_meta(self) -> Scalar<Tag> {
3934
match self {
4035
Self::Meta(s) => s,
41-
Self::None | Self::Poison => {
36+
Self::None => {
4237
bug!("expected wide pointer extra data (e.g. slice length or trait object vtable)")
4338
}
4439
}
4540
}
41+
4642
pub fn has_meta(self) -> bool {
4743
match self {
4844
Self::Meta(_) => true,
49-
Self::None | Self::Poison => false,
45+
Self::None => false,
5046
}
5147
}
5248
}
@@ -163,10 +159,6 @@ impl<Tag: Provenance> MemPlace<Tag> {
163159
MemPlaceMeta::Meta(meta) => {
164160
Immediate::ScalarPair(Scalar::from_maybe_pointer(self.ptr, cx).into(), meta.into())
165161
}
166-
MemPlaceMeta::Poison => bug!(
167-
"MPlaceTy::dangling may never be used to produce a \
168-
place that will have the address of its pointee taken"
169-
),
170162
}
171163
}
172164

@@ -195,13 +187,15 @@ impl<Tag: Provenance> Place<Tag> {
195187
}
196188

197189
impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> {
198-
/// Produces a MemPlace that works for ZST but nothing else
190+
/// Produces a MemPlace that works for ZST but nothing else.
191+
/// Conceptually this is a new allocation, but it doesn't actually create an allocation so you
192+
/// don't need to worry about memory leaks.
199193
#[inline]
200-
pub fn dangling(layout: TyAndLayout<'tcx>) -> Self {
194+
pub fn fake_alloc_zst(layout: TyAndLayout<'tcx>) -> Self {
195+
assert!(layout.is_zst());
201196
let align = layout.align.abi;
202197
let ptr = Pointer::from_addr(align.bytes()); // no provenance, absolute address
203-
// `Poison` this to make sure that the pointer value `ptr` is never observable by the program.
204-
MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::Poison }, layout, align }
198+
MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::None }, layout, align }
205199
}
206200

207201
#[inline]
@@ -273,7 +267,6 @@ impl<'tcx, Tag: Provenance> OpTy<'tcx, Tag> {
273267
Operand::Indirect(mplace) => {
274268
Ok(MPlaceTy { mplace, layout: self.layout, align: self.align.unwrap() })
275269
}
276-
Operand::Immediate(_) if self.layout.is_zst() => Ok(MPlaceTy::dangling(self.layout)),
277270
Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)),
278271
}
279272
}

compiler/rustc_const_eval/src/interpret/terminator.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -617,16 +617,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
617617
place.to_ref(self),
618618
self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
619619
);
620-
621-
let ty = self.tcx.mk_unit(); // return type is ()
622-
let dest = MPlaceTy::dangling(self.layout_of(ty)?);
620+
let ret = MPlaceTy::fake_alloc_zst(self.layout_of(self.tcx.types.unit)?);
623621

624622
self.eval_fn_call(
625623
FnVal::Instance(instance),
626624
(Abi::Rust, fn_abi),
627625
&[arg.into()],
628626
false,
629-
&dest.into(),
627+
&ret.into(),
630628
Some(target),
631629
match unwind {
632630
Some(cleanup) => StackPopUnwind::Cleanup(cleanup),

compiler/rustc_middle/src/mir/interpret/allocation.rs

+2
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ impl<Tag> Allocation<Tag> {
225225

226226
/// Try to create an Allocation of `size` bytes, failing if there is not enough memory
227227
/// available to the compiler to do so.
228+
///
229+
/// If `panic_on_fail` is true, this will never return `Err`.
228230
pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> {
229231
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
230232
// This results in an error that can happen non-deterministically, since the memory

0 commit comments

Comments
 (0)