Skip to content

Commit e180d36

Browse files
authored
Rollup merge of rust-lang#67501 - oli-obk:test-slice-patterns, r=RalfJung
Reduce special treatment for zsts addresses rust-lang#67467 (comment) cc @RalfJung
2 parents aabb037 + c5c4fa8 commit e180d36

File tree

11 files changed

+157
-152
lines changed

11 files changed

+157
-152
lines changed

Diff for: src/librustc_mir/const_eval/eval_queries.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -115,28 +115,31 @@ pub(super) fn op_to_const<'tcx>(
115115
// by-val is if we are in const_field, i.e., if this is (a field of) something that we
116116
// "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
117117
// structs containing such.
118-
op.try_as_mplace()
118+
op.try_as_mplace(ecx)
119119
};
120-
let val = match immediate {
121-
Ok(mplace) => {
122-
let ptr = mplace.ptr.assert_ptr();
120+
121+
let to_const_value = |mplace: MPlaceTy<'_>| match mplace.ptr {
122+
Scalar::Ptr(ptr) => {
123123
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
124124
ConstValue::ByRef { alloc, offset: ptr.offset }
125125
}
126+
Scalar::Raw { data, .. } => {
127+
assert!(mplace.layout.is_zst());
128+
assert_eq!(
129+
data,
130+
mplace.layout.align.abi.bytes().into(),
131+
"this MPlaceTy must come from `try_as_mplace` being used on a zst, so we know what
132+
value this integer address must have",
133+
);
134+
ConstValue::Scalar(Scalar::zst())
135+
}
136+
};
137+
let val = match immediate {
138+
Ok(mplace) => to_const_value(mplace),
126139
// see comment on `let try_as_immediate` above
127140
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
128141
ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
129-
ScalarMaybeUndef::Undef => {
130-
// When coming out of "normal CTFE", we'll always have an `Indirect` operand as
131-
// argument and we will not need this. The only way we can already have an
132-
// `Immediate` is when we are called from `const_field`, and that `Immediate`
133-
// comes from a constant so it can happen have `Undef`, because the indirect
134-
// memory that was read had undefined bytes.
135-
let mplace = op.assert_mem_place();
136-
let ptr = mplace.ptr.assert_ptr();
137-
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
138-
ConstValue::ByRef { alloc, offset: ptr.offset }
139-
}
142+
ScalarMaybeUndef::Undef => to_const_value(op.assert_mem_place(ecx)),
140143
},
141144
Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
142145
let (data, start) = match a.not_undef().unwrap() {

Diff for: src/librustc_mir/interpret/eval_context.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_macros::HashStable;
2020
use rustc_span::source_map::{self, Span, DUMMY_SP};
2121

2222
use super::{
23-
Immediate, MPlaceTy, Machine, MemPlace, Memory, OpTy, Operand, Place, PlaceTy,
23+
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
2424
ScalarMaybeUndef, StackPopInfo,
2525
};
2626

@@ -393,7 +393,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
393393
/// This can fail to provide an answer for extern types.
394394
pub(super) fn size_and_align_of(
395395
&self,
396-
metadata: Option<Scalar<M::PointerTag>>,
396+
metadata: MemPlaceMeta<M::PointerTag>,
397397
layout: TyLayout<'tcx>,
398398
) -> InterpResult<'tcx, Option<(Size, Align)>> {
399399
if !layout.is_unsized() {
@@ -465,14 +465,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
465465
Ok(Some((size, align)))
466466
}
467467
ty::Dynamic(..) => {
468-
let vtable = metadata.expect("dyn trait fat ptr must have vtable");
468+
let vtable = metadata.unwrap_meta();
469469
// Read size and align from vtable (already checks size).
470470
Ok(Some(self.read_size_and_align_from_vtable(vtable)?))
471471
}
472472

473473
ty::Slice(_) | ty::Str => {
474-
let len =
475-
metadata.expect("slice fat ptr must have length").to_machine_usize(self)?;
474+
let len = metadata.unwrap_meta().to_machine_usize(self)?;
476475
let elem = layout.field(self, 0)?;
477476

478477
// Make sure the slice is not too big.
@@ -818,8 +817,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
818817
" by align({}){} ref:",
819818
mplace.align.bytes(),
820819
match mplace.meta {
821-
Some(meta) => format!(" meta({:?})", meta),
822-
None => String::new(),
820+
MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
821+
MemPlaceMeta::Poison | MemPlaceMeta::None => String::new(),
823822
}
824823
)
825824
.unwrap();

Diff for: src/librustc_mir/interpret/intern.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx
193193
{
194194
// Validation has already errored on an invalid vtable pointer so we can safely not
195195
// do anything if this is not a real pointer.
196-
if let Scalar::Ptr(vtable) = mplace.meta.unwrap() {
196+
if let Scalar::Ptr(vtable) = mplace.meta.unwrap_meta() {
197197
// Explicitly choose `Immutable` here, since vtables are immutable, even
198198
// if the reference of the fat pointer is mutable.
199199
self.intern_shallow(vtable.alloc_id, Mutability::Not, None)?;
@@ -226,7 +226,8 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx
226226
| (InternMode::Const, hir::Mutability::Mut) => match referenced_ty.kind {
227227
ty::Array(_, n)
228228
if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {}
229-
ty::Slice(_) if mplace.meta.unwrap().to_machine_usize(self.ecx)? == 0 => {}
229+
ty::Slice(_)
230+
if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)? == 0 => {}
230231
_ => bug!("const qualif failed to prevent mutable references"),
231232
},
232233
}

Diff for: src/librustc_mir/interpret/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one pla
2020

2121
pub use self::eval_context::{Frame, InterpCx, LocalState, LocalValue, StackPopCleanup};
2222

23-
pub use self::place::{MPlaceTy, MemPlace, Place, PlaceTy};
23+
pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};
2424

2525
pub use self::memory::{AllocCheck, FnVal, Memory, MemoryKind};
2626

Diff for: src/librustc_mir/interpret/operand.rs

+5-49
Original file line numberDiff line numberDiff line change
@@ -153,30 +153,6 @@ pub enum Operand<Tag = (), Id = AllocId> {
153153
Indirect(MemPlace<Tag, Id>),
154154
}
155155

156-
impl<Tag> Operand<Tag> {
157-
#[inline]
158-
pub fn assert_mem_place(self) -> MemPlace<Tag>
159-
where
160-
Tag: ::std::fmt::Debug,
161-
{
162-
match self {
163-
Operand::Indirect(mplace) => mplace,
164-
_ => bug!("assert_mem_place: expected Operand::Indirect, got {:?}", self),
165-
}
166-
}
167-
168-
#[inline]
169-
pub fn assert_immediate(self) -> Immediate<Tag>
170-
where
171-
Tag: ::std::fmt::Debug,
172-
{
173-
match self {
174-
Operand::Immediate(imm) => imm,
175-
_ => bug!("assert_immediate: expected Operand::Immediate, got {:?}", self),
176-
}
177-
}
178-
}
179-
180156
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
181157
pub struct OpTy<'tcx, Tag = ()> {
182158
op: Operand<Tag>, // Keep this private; it helps enforce invariants.
@@ -267,7 +243,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
267243
&self,
268244
op: OpTy<'tcx, M::PointerTag>,
269245
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
270-
match op.try_as_mplace() {
246+
match op.try_as_mplace(self) {
271247
Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()),
272248
Err(imm) => Ok(imm.into()), // Nothing to cast/force
273249
}
@@ -335,7 +311,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
335311
&self,
336312
src: OpTy<'tcx, M::PointerTag>,
337313
) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::PointerTag>, MPlaceTy<'tcx, M::PointerTag>>> {
338-
Ok(match src.try_as_mplace() {
314+
Ok(match src.try_as_mplace(self) {
339315
Ok(mplace) => {
340316
if let Some(val) = self.try_read_immediate_from_mplace(mplace)? {
341317
Ok(val)
@@ -383,7 +359,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
383359
op: OpTy<'tcx, M::PointerTag>,
384360
field: u64,
385361
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
386-
let base = match op.try_as_mplace() {
362+
let base = match op.try_as_mplace(self) {
387363
Ok(mplace) => {
388364
// The easy case
389365
let field = self.mplace_field(mplace, field)?;
@@ -420,7 +396,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
420396
variant: VariantIdx,
421397
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
422398
// Downcasts only change the layout
423-
Ok(match op.try_as_mplace() {
399+
Ok(match op.try_as_mplace(self) {
424400
Ok(mplace) => self.mplace_downcast(mplace, variant)?.into(),
425401
Err(..) => {
426402
let layout = op.layout.for_variant(self, variant);
@@ -439,30 +415,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
439415
Field(field, _) => self.operand_field(base, field.index() as u64)?,
440416
Downcast(_, variant) => self.operand_downcast(base, variant)?,
441417
Deref => self.deref_operand(base)?.into(),
442-
ConstantIndex { .. } | Index(_) if base.layout.is_zst() => {
443-
OpTy {
444-
op: Operand::Immediate(Scalar::zst().into()),
445-
// the actual index doesn't matter, so we just pick a convenient one like 0
446-
layout: base.layout.field(self, 0)?,
447-
}
448-
}
449-
Subslice { from, to, from_end } if base.layout.is_zst() => {
450-
let elem_ty = if let ty::Array(elem_ty, _) = base.layout.ty.kind {
451-
elem_ty
452-
} else {
453-
bug!("slices shouldn't be zero-sized");
454-
};
455-
assert!(!from_end, "arrays shouldn't be subsliced from the end");
456-
457-
OpTy {
458-
op: Operand::Immediate(Scalar::zst().into()),
459-
layout: self.layout_of(self.tcx.mk_array(elem_ty, (to - from) as u64))?,
460-
}
461-
}
462418
Subslice { .. } | ConstantIndex { .. } | Index(_) => {
463419
// The rest should only occur as mplace, we do not use Immediates for types
464420
// allowing such operations. This matches place_projection forcing an allocation.
465-
let mplace = base.assert_mem_place();
421+
let mplace = base.assert_mem_place(self);
466422
self.mplace_projection(mplace, proj_elem)?.into()
467423
}
468424
})

0 commit comments

Comments
 (0)