Skip to content

Commit 77ff1b8

Browse files
committed
interpret: make read functions generic over operand type
1 parent 00fb45d commit 77ff1b8

File tree

19 files changed

+130
-128
lines changed

19 files changed

+130
-128
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
216216

217217
let mut msg_place = self.deref_operand(&args[0])?;
218218
while msg_place.layout.ty.is_ref() {
219-
msg_place = self.deref_operand(&msg_place.into())?;
219+
msg_place = self.deref_operand(&msg_place)?;
220220
}
221221

222222
let msg = Symbol::intern(self.read_str(&msg_place)?);

compiler/rustc_const_eval/src/const_eval/valtrees.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
8686
Ok(ty::ValTree::zst())
8787
}
8888
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
89-
let Ok(val) = ecx.read_immediate(&place.into()) else {
89+
let Ok(val) = ecx.read_immediate(place) else {
9090
return Err(ValTreeCreationError::Other);
9191
};
9292
let val = val.to_scalar();
@@ -102,7 +102,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
102102
ty::FnPtr(_) | ty::RawPtr(_) => Err(ValTreeCreationError::NonSupportedType),
103103

104104
ty::Ref(_, _, _) => {
105-
let Ok(derefd_place)= ecx.deref_operand(&place.into()) else {
105+
let Ok(derefd_place)= ecx.deref_operand(place) else {
106106
return Err(ValTreeCreationError::Other);
107107
};
108108
debug!(?derefd_place);
@@ -130,7 +130,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
130130
bug!("uninhabited types should have errored and never gotten converted to valtree")
131131
}
132132

133-
let Ok(variant) = ecx.read_discriminant(&place.into()) else {
133+
let Ok(variant) = ecx.read_discriminant(place) else {
134134
return Err(ValTreeCreationError::Other);
135135
};
136136
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes)

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
5656
}
5757

5858
CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
59-
let src = self.read_immediate(&src)?;
59+
let src = self.read_immediate(src)?;
6060
let res = self.ptr_to_ptr(&src, cast_ty)?;
6161
self.write_immediate(res, dest)?;
6262
}

compiler/rustc_const_eval/src/interpret/discriminant.rs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use rustc_middle::{mir, ty};
55
use rustc_target::abi::{self, TagEncoding};
66
use rustc_target::abi::{VariantIdx, Variants};
77

8-
use super::place::Writeable;
9-
use super::{ImmTy, InterpCx, InterpResult, Machine, OpTy, Scalar};
8+
use super::{ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable};
109

1110
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1211
/// Writes the discriminant of the given variant.
@@ -97,32 +96,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
9796
#[instrument(skip(self), level = "trace")]
9897
pub fn read_discriminant(
9998
&self,
100-
op: &OpTy<'tcx, M::Provenance>,
99+
op: &impl Readable<'tcx, M::Provenance>,
101100
) -> InterpResult<'tcx, VariantIdx> {
102-
trace!("read_discriminant_value {:#?}", op.layout);
101+
let ty = op.layout().ty;
102+
trace!("read_discriminant_value {:#?}", op.layout());
103103
// Get type and layout of the discriminant.
104-
let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
104+
let discr_layout = self.layout_of(ty.discriminant_ty(*self.tcx))?;
105105
trace!("discriminant type: {:?}", discr_layout.ty);
106106

107107
// We use "discriminant" to refer to the value associated with a particular enum variant.
108108
// This is not to be confused with its "variant index", which is just determining its position in the
109109
// declared list of variants -- they can differ with explicitly assigned discriminants.
110110
// We use "tag" to refer to how the discriminant is encoded in memory, which can be either
111111
// straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
112-
let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants {
112+
let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout().variants {
113113
Variants::Single { index } => {
114114
// Do some extra checks on enums.
115-
if op.layout.ty.is_enum() {
115+
if ty.is_enum() {
116116
// Hilariously, `Single` is used even for 0-variant enums.
117117
// (See https://github.com/rust-lang/rust/issues/89765).
118-
if matches!(op.layout.ty.kind(), ty::Adt(def, ..) if def.variants().is_empty())
119-
{
118+
if matches!(ty.kind(), ty::Adt(def, ..) if def.variants().is_empty()) {
120119
throw_ub!(UninhabitedEnumVariantRead(index))
121120
}
122121
// For consisteny with `write_discriminant`, and to make sure that
123122
// `project_downcast` cannot fail due to strange layouts, we declare immediate UB
124123
// for uninhabited variants.
125-
if op.layout.for_variant(self, index).abi.is_uninhabited() {
124+
if op.layout().for_variant(self, index).abi.is_uninhabited() {
126125
throw_ub!(UninhabitedEnumVariantRead(index))
127126
}
128127
}
@@ -168,7 +167,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
168167
self.cast_from_int_like(scalar, tag_val.layout, discr_layout.ty).unwrap();
169168
let discr_bits = discr_val.assert_bits(discr_layout.size);
170169
// Convert discriminant to variant index, and catch invalid discriminants.
171-
let index = match *op.layout.ty.kind() {
170+
let index = match *ty.kind() {
172171
ty::Adt(adt, _) => {
173172
adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
174173
}
@@ -222,12 +221,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
222221
.checked_add(variant_index_relative)
223222
.expect("overflow computing absolute variant idx"),
224223
);
225-
let variants = op
226-
.layout
227-
.ty
228-
.ty_adt_def()
229-
.expect("tagged layout for non adt")
230-
.variants();
224+
let variants =
225+
ty.ty_adt_def().expect("tagged layout for non adt").variants();
231226
assert!(variant_index < variants.next_index());
232227
variant_index
233228
} else {
@@ -242,7 +237,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
242237
}
243238
};
244239
// For consisteny with `write_discriminant`, and to make sure that `project_downcast` cannot fail due to strange layouts, we declare immediate UB for uninhabited variants.
245-
if op.layout.for_variant(self, index).abi.is_uninhabited() {
240+
if op.layout().for_variant(self, index).abi.is_uninhabited() {
246241
throw_ub!(UninhabitedEnumVariantRead(index))
247242
}
248243
Ok(index)

compiler/rustc_const_eval/src/interpret/intern.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
170170
let tcx = self.ecx.tcx;
171171
let ty = mplace.layout.ty;
172172
if let ty::Ref(_, referenced_ty, ref_mutability) = *ty.kind() {
173-
let value = self.ecx.read_immediate(&mplace.into())?;
173+
let value = self.ecx.read_immediate(mplace)?;
174174
let mplace = self.ecx.ref_to_mplace(&value)?;
175175
assert_eq!(mplace.layout.ty, referenced_ty);
176176
// Handle trait object vtables.

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
226226
}
227227
sym::discriminant_value => {
228228
let place = self.deref_operand(&args[0])?;
229-
let variant = self.read_discriminant(&place.into())?;
229+
let variant = self.read_discriminant(&place)?;
230230
let discr = self.discriminant_for_variant(place.layout, variant)?;
231231
self.write_scalar(discr, dest)?;
232232
}
@@ -445,7 +445,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
445445
input_len
446446
);
447447
self.copy_op(
448-
&self.project_index(&input, index)?.into(),
448+
&self.project_index(&input, index)?,
449449
dest,
450450
/*allow_transmute*/ false,
451451
)?;
@@ -610,7 +610,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
610610
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
611611
nonoverlapping: bool,
612612
) -> InterpResult<'tcx> {
613-
let count = self.read_target_usize(&count)?;
613+
let count = self.read_target_usize(count)?;
614614
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
615615
let (size, align) = (layout.size, layout.align.abi);
616616
// `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
@@ -622,8 +622,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
622622
)
623623
})?;
624624

625-
let src = self.read_pointer(&src)?;
626-
let dst = self.read_pointer(&dst)?;
625+
let src = self.read_pointer(src)?;
626+
let dst = self.read_pointer(dst)?;
627627

628628
self.mem_copy(src, align, dst, align, size, nonoverlapping)
629629
}
@@ -636,9 +636,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
636636
) -> InterpResult<'tcx> {
637637
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap().ty)?;
638638

639-
let dst = self.read_pointer(&dst)?;
640-
let byte = self.read_scalar(&byte)?.to_u8()?;
641-
let count = self.read_target_usize(&count)?;
639+
let dst = self.read_pointer(dst)?;
640+
let byte = self.read_scalar(byte)?.to_u8()?;
641+
let count = self.read_target_usize(count)?;
642642

643643
// `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
644644
// but no actual allocation can be big enough for the difference to be noticeable.

compiler/rustc_const_eval/src/interpret/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub use self::eval_context::{Frame, FrameInfo, InterpCx, LocalState, LocalValue,
2424
pub use self::intern::{intern_const_alloc_recursive, InternKind};
2525
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
2626
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
27-
pub use self::operand::{ImmTy, Immediate, OpTy, Operand};
27+
pub use self::operand::{ImmTy, Immediate, OpTy, Operand, Readable};
2828
pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy, Writeable};
2929
pub use self::projection::Projectable;
3030
pub use self::terminator::FnArg;

compiler/rustc_const_eval/src/interpret/operand.rs

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -180,41 +180,13 @@ impl<'tcx, Prov: Provenance> From<MPlaceTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
180180
}
181181
}
182182

183-
impl<'tcx, Prov: Provenance> From<&'_ MPlaceTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
184-
#[inline(always)]
185-
fn from(mplace: &MPlaceTy<'tcx, Prov>) -> Self {
186-
OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout, align: Some(mplace.align) }
187-
}
188-
}
189-
190-
impl<'tcx, Prov: Provenance> From<&'_ mut MPlaceTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
191-
#[inline(always)]
192-
fn from(mplace: &mut MPlaceTy<'tcx, Prov>) -> Self {
193-
OpTy { op: Operand::Indirect(**mplace), layout: mplace.layout, align: Some(mplace.align) }
194-
}
195-
}
196-
197183
impl<'tcx, Prov: Provenance> From<ImmTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
198184
#[inline(always)]
199185
fn from(val: ImmTy<'tcx, Prov>) -> Self {
200186
OpTy { op: Operand::Immediate(val.imm), layout: val.layout, align: None }
201187
}
202188
}
203189

204-
impl<'tcx, Prov: Provenance> From<&'_ ImmTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
205-
#[inline(always)]
206-
fn from(val: &ImmTy<'tcx, Prov>) -> Self {
207-
OpTy { op: Operand::Immediate(val.imm), layout: val.layout, align: None }
208-
}
209-
}
210-
211-
impl<'tcx, Prov: Provenance> From<&'_ mut ImmTy<'tcx, Prov>> for OpTy<'tcx, Prov> {
212-
#[inline(always)]
213-
fn from(val: &mut ImmTy<'tcx, Prov>) -> Self {
214-
OpTy { op: Operand::Immediate(val.imm), layout: val.layout, align: None }
215-
}
216-
}
217-
218190
impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
219191
#[inline]
220192
pub fn from_scalar(val: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self {
@@ -341,7 +313,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> {
341313
&self,
342314
_ecx: &InterpCx<'mir, 'tcx, M>,
343315
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
344-
Ok(self.into())
316+
Ok(self.clone().into())
345317
}
346318
}
347319

@@ -400,6 +372,31 @@ impl<'tcx, Prov: Provenance + 'static> Projectable<'tcx, Prov> for OpTy<'tcx, Pr
400372
}
401373
}
402374

375+
pub trait Readable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
376+
fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>>;
377+
}
378+
379+
impl<'tcx, Prov: Provenance + 'static> Readable<'tcx, Prov> for OpTy<'tcx, Prov> {
380+
#[inline(always)]
381+
fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
382+
self.as_mplace_or_imm()
383+
}
384+
}
385+
386+
impl<'tcx, Prov: Provenance + 'static> Readable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
387+
#[inline(always)]
388+
fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
389+
Left(self.clone())
390+
}
391+
}
392+
393+
impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for ImmTy<'tcx, Prov> {
394+
#[inline(always)]
395+
fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
396+
Right(self.clone())
397+
}
398+
}
399+
403400
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
404401
/// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
405402
/// Returns `None` if the layout does not permit loading this as a value.
@@ -472,7 +469,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
472469
/// ConstProp needs it, though.
473470
pub fn read_immediate_raw(
474471
&self,
475-
src: &OpTy<'tcx, M::Provenance>,
472+
src: &impl Readable<'tcx, M::Provenance>,
476473
) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
477474
Ok(match src.as_mplace_or_imm() {
478475
Left(ref mplace) => {
@@ -492,14 +489,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
492489
#[inline(always)]
493490
pub fn read_immediate(
494491
&self,
495-
op: &OpTy<'tcx, M::Provenance>,
492+
op: &impl Readable<'tcx, M::Provenance>,
496493
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
497494
if !matches!(
498-
op.layout.abi,
495+
op.layout().abi,
499496
Abi::Scalar(abi::Scalar::Initialized { .. })
500497
| Abi::ScalarPair(abi::Scalar::Initialized { .. }, abi::Scalar::Initialized { .. })
501498
) {
502-
span_bug!(self.cur_span(), "primitive read not possible for type: {:?}", op.layout.ty);
499+
span_bug!(
500+
self.cur_span(),
501+
"primitive read not possible for type: {:?}",
502+
op.layout().ty
503+
);
503504
}
504505
let imm = self.read_immediate_raw(op)?.right().unwrap();
505506
if matches!(*imm, Immediate::Uninit) {
@@ -511,7 +512,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
511512
/// Read a scalar from a place
512513
pub fn read_scalar(
513514
&self,
514-
op: &OpTy<'tcx, M::Provenance>,
515+
op: &impl Readable<'tcx, M::Provenance>,
515516
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
516517
Ok(self.read_immediate(op)?.to_scalar())
517518
}
@@ -522,16 +523,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
522523
/// Read a pointer from a place.
523524
pub fn read_pointer(
524525
&self,
525-
op: &OpTy<'tcx, M::Provenance>,
526+
op: &impl Readable<'tcx, M::Provenance>,
526527
) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
527528
self.read_scalar(op)?.to_pointer(self)
528529
}
529530
/// Read a pointer-sized unsigned integer from a place.
530-
pub fn read_target_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> {
531+
pub fn read_target_usize(
532+
&self,
533+
op: &impl Readable<'tcx, M::Provenance>,
534+
) -> InterpResult<'tcx, u64> {
531535
self.read_scalar(op)?.to_target_usize(self)
532536
}
533537
/// Read a pointer-sized signed integer from a place.
534-
pub fn read_target_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> {
538+
pub fn read_target_isize(
539+
&self,
540+
op: &impl Readable<'tcx, M::Provenance>,
541+
) -> InterpResult<'tcx, i64> {
535542
self.read_scalar(op)?.to_target_isize(self)
536543
}
537544

0 commit comments

Comments
 (0)