Skip to content

Commit e7c23ab

Browse files
committed
Auto merge of #82124 - tmiasko:op-ty-ref, r=oli-obk
Pass large interpreter types by reference, not value r? `@ghost`
2 parents da5f7f1 + f2da425 commit e7c23ab

17 files changed

+401
-358
lines changed

compiler/rustc_mir/src/const_eval/eval_queries.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
5656
ecx.push_stack_frame(
5757
cid.instance,
5858
body,
59-
Some(ret.into()),
59+
Some(&ret.into()),
6060
StackPopCleanup::None { cleanup: false },
6161
)?;
6262

@@ -72,7 +72,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
7272
None => InternKind::Constant,
7373
}
7474
};
75-
intern_const_alloc_recursive(ecx, intern_kind, ret)?;
75+
intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
7676

7777
debug!("eval_body_using_ecx done: {:?}", *ret);
7878
Ok(ret)
@@ -105,7 +105,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
105105
/// type system.
106106
pub(super) fn op_to_const<'tcx>(
107107
ecx: &CompileTimeEvalContext<'_, 'tcx>,
108-
op: OpTy<'tcx>,
108+
op: &OpTy<'tcx>,
109109
) -> ConstValue<'tcx> {
110110
// We do not have value optimizations for everything.
111111
// Only scalars and slices, since they are very common.
@@ -137,7 +137,7 @@ pub(super) fn op_to_const<'tcx>(
137137
op.try_as_mplace(ecx)
138138
};
139139

140-
let to_const_value = |mplace: MPlaceTy<'_>| match mplace.ptr {
140+
let to_const_value = |mplace: &MPlaceTy<'_>| match mplace.ptr {
141141
Scalar::Ptr(ptr) => {
142142
let alloc = ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory();
143143
ConstValue::ByRef { alloc, offset: ptr.offset }
@@ -155,12 +155,12 @@ pub(super) fn op_to_const<'tcx>(
155155
}
156156
};
157157
match immediate {
158-
Ok(mplace) => to_const_value(mplace),
158+
Ok(ref mplace) => to_const_value(mplace),
159159
// see comment on `let try_as_immediate` above
160160
Err(imm) => match *imm {
161161
Immediate::Scalar(x) => match x {
162162
ScalarMaybeUninit::Scalar(s) => ConstValue::Scalar(s),
163-
ScalarMaybeUninit::Uninit => to_const_value(op.assert_mem_place(ecx)),
163+
ScalarMaybeUninit::Uninit => to_const_value(&op.assert_mem_place(ecx)),
164164
},
165165
Immediate::ScalarPair(a, b) => {
166166
let (data, start) = match a.check_init().unwrap() {
@@ -201,7 +201,7 @@ fn turn_into_const_value<'tcx>(
201201
"the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
202202
);
203203
// Turn this into a proper constant.
204-
op_to_const(&ecx, mplace.into())
204+
op_to_const(&ecx, &mplace.into())
205205
}
206206

207207
pub fn eval_to_const_value_raw_provider<'tcx>(
@@ -348,7 +348,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
348348
Some(_) => CtfeValidationMode::Regular, // a `static`
349349
None => CtfeValidationMode::Const { inner, allow_static_ptrs: false },
350350
};
351-
ecx.const_validate_operand(mplace.into(), path, &mut ref_tracking, mode)?;
351+
ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)?;
352352
inner = true;
353353
}
354354
};

compiler/rustc_mir/src/const_eval/machine.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
3939
// &str
4040
assert!(args.len() == 1);
4141

42-
let msg_place = self.deref_operand(args[0])?;
43-
let msg = Symbol::intern(self.read_str(msg_place)?);
42+
let msg_place = self.deref_operand(&args[0])?;
43+
let msg = Symbol::intern(self.read_str(&msg_place)?);
4444
let span = self.find_closest_untracked_caller_location();
4545
let (file, line, col) = self.location_triple_for_span(span);
4646
Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
@@ -222,7 +222,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
222222
instance: ty::Instance<'tcx>,
223223
_abi: Abi,
224224
args: &[OpTy<'tcx>],
225-
_ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
225+
_ret: Option<(&PlaceTy<'tcx>, mir::BasicBlock)>,
226226
_unwind: Option<mir::BasicBlock>, // unwinding is not supported in consts
227227
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
228228
debug!("find_mir_or_eval_fn: {:?}", instance);
@@ -262,7 +262,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
262262
ecx: &mut InterpCx<'mir, 'tcx, Self>,
263263
instance: ty::Instance<'tcx>,
264264
args: &[OpTy<'tcx>],
265-
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
265+
ret: Option<(&PlaceTy<'tcx>, mir::BasicBlock)>,
266266
_unwind: Option<mir::BasicBlock>,
267267
) -> InterpResult<'tcx> {
268268
// Shared intrinsics.
@@ -284,8 +284,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
284284
};
285285
match intrinsic_name {
286286
sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
287-
let a = ecx.read_immediate(args[0])?.to_scalar()?;
288-
let b = ecx.read_immediate(args[1])?.to_scalar()?;
287+
let a = ecx.read_immediate(&args[0])?.to_scalar()?;
288+
let b = ecx.read_immediate(&args[1])?.to_scalar()?;
289289
let cmp = if intrinsic_name == sym::ptr_guaranteed_eq {
290290
ecx.guaranteed_eq(a, b)
291291
} else {
@@ -294,8 +294,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
294294
ecx.write_scalar(Scalar::from_bool(cmp), dest)?;
295295
}
296296
sym::const_allocate => {
297-
let size = ecx.read_scalar(args[0])?.to_machine_usize(ecx)?;
298-
let align = ecx.read_scalar(args[1])?.to_machine_usize(ecx)?;
297+
let size = ecx.read_scalar(&args[0])?.to_machine_usize(ecx)?;
298+
let align = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?;
299299

300300
let align = match Align::from_bytes(align) {
301301
Ok(a) => a,
@@ -330,7 +330,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
330330
use rustc_middle::mir::AssertKind::*;
331331
// Convert `AssertKind<Operand>` to `AssertKind<Scalar>`.
332332
let eval_to_int =
333-
|op| ecx.read_immediate(ecx.eval_operand(op, None)?).map(|x| x.to_const_int());
333+
|op| ecx.read_immediate(&ecx.eval_operand(op, None)?).map(|x| x.to_const_int());
334334
let err = match msg {
335335
BoundsCheck { ref len, ref index } => {
336336
let len = eval_to_int(len)?;
@@ -358,15 +358,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
358358
fn binary_ptr_op(
359359
_ecx: &InterpCx<'mir, 'tcx, Self>,
360360
_bin_op: mir::BinOp,
361-
_left: ImmTy<'tcx>,
362-
_right: ImmTy<'tcx>,
361+
_left: &ImmTy<'tcx>,
362+
_right: &ImmTy<'tcx>,
363363
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
364364
Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into())
365365
}
366366

367367
fn box_alloc(
368368
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
369-
_dest: PlaceTy<'tcx>,
369+
_dest: &PlaceTy<'tcx>,
370370
) -> InterpResult<'tcx> {
371371
Err(ConstEvalErrKind::NeedsRfc("heap allocations via `box` keyword".to_string()).into())
372372
}

compiler/rustc_mir/src/const_eval/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub(crate) fn const_caller_location(
2929
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
3030

3131
let loc_place = ecx.alloc_caller_location(file, line, col);
32-
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place).is_err() {
32+
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
3333
bug!("intern_const_alloc_recursive should not error in this case")
3434
}
3535
ConstValue::Scalar(loc_place.ptr)
@@ -55,17 +55,17 @@ pub(crate) fn destructure_const<'tcx>(
5555
return mir::DestructuredConst { variant: None, fields: &[] };
5656
}
5757
ty::Adt(def, _) => {
58-
let variant = ecx.read_discriminant(op).unwrap().1;
59-
let down = ecx.operand_downcast(op, variant).unwrap();
58+
let variant = ecx.read_discriminant(&op).unwrap().1;
59+
let down = ecx.operand_downcast(&op, variant).unwrap();
6060
(def.variants[variant].fields.len(), Some(variant), down)
6161
}
6262
ty::Tuple(substs) => (substs.len(), None, op),
6363
_ => bug!("cannot destructure constant {:?}", val),
6464
};
6565

6666
let fields_iter = (0..field_count).map(|i| {
67-
let field_op = ecx.operand_field(down, i).unwrap();
68-
let val = op_to_const(&ecx, field_op);
67+
let field_op = ecx.operand_field(&down, i).unwrap();
68+
let val = op_to_const(&ecx, &field_op);
6969
ty::Const::from_value(tcx, val, field_op.layout.ty)
7070
});
7171
let fields = tcx.arena.alloc_from_iter(fields_iter);
@@ -81,7 +81,7 @@ pub(crate) fn deref_const<'tcx>(
8181
trace!("deref_const: {:?}", val);
8282
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
8383
let op = ecx.const_to_op(val, None).unwrap();
84-
let mplace = ecx.deref_operand(op).unwrap();
84+
let mplace = ecx.deref_operand(&op).unwrap();
8585
if let Scalar::Ptr(ptr) = mplace.ptr {
8686
assert_eq!(
8787
ecx.memory.get_raw(ptr.alloc_id).unwrap().mutability,
@@ -106,5 +106,5 @@ pub(crate) fn deref_const<'tcx>(
106106
},
107107
};
108108

109-
tcx.mk_const(ty::Const { val: ty::ConstKind::Value(op_to_const(&ecx, mplace.into())), ty })
109+
tcx.mk_const(ty::Const { val: ty::ConstKind::Value(op_to_const(&ecx, &mplace.into())), ty })
110110
}

compiler/rustc_mir/src/interpret/cast.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ use super::{
1717
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1818
pub fn cast(
1919
&mut self,
20-
src: OpTy<'tcx, M::PointerTag>,
20+
src: &OpTy<'tcx, M::PointerTag>,
2121
cast_kind: CastKind,
2222
cast_ty: Ty<'tcx>,
23-
dest: PlaceTy<'tcx, M::PointerTag>,
23+
dest: &PlaceTy<'tcx, M::PointerTag>,
2424
) -> InterpResult<'tcx> {
2525
use rustc_middle::mir::CastKind::*;
2626
// FIXME: In which cases should we trigger UB when the source is uninit?
@@ -32,7 +32,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
3232

3333
Misc => {
3434
let src = self.read_immediate(src)?;
35-
let res = self.misc_cast(src, cast_ty)?;
35+
let res = self.misc_cast(&src, cast_ty)?;
3636
self.write_immediate(res, dest)?;
3737
}
3838

@@ -107,7 +107,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
107107

108108
fn misc_cast(
109109
&self,
110-
src: ImmTy<'tcx, M::PointerTag>,
110+
src: &ImmTy<'tcx, M::PointerTag>,
111111
cast_ty: Ty<'tcx>,
112112
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
113113
use rustc_middle::ty::TyKind::*;
@@ -158,13 +158,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
158158
let dest_layout = self.layout_of(cast_ty)?;
159159
if dest_layout.size == src.layout.size {
160160
// Thin or fat pointer that just hast the ptr kind of target type changed.
161-
return Ok(*src);
161+
return Ok(**src);
162162
} else {
163163
// Casting the metadata away from a fat ptr.
164164
assert_eq!(src.layout.size, 2 * self.memory.pointer_size());
165165
assert_eq!(dest_layout.size, self.memory.pointer_size());
166166
assert!(src.layout.ty.is_unsafe_ptr());
167-
return match *src {
167+
return match **src {
168168
Immediate::ScalarPair(data, _) => Ok(data.into()),
169169
Immediate::Scalar(..) => span_bug!(
170170
self.cur_span(),
@@ -259,8 +259,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
259259

260260
fn unsize_into_ptr(
261261
&mut self,
262-
src: OpTy<'tcx, M::PointerTag>,
263-
dest: PlaceTy<'tcx, M::PointerTag>,
262+
src: &OpTy<'tcx, M::PointerTag>,
263+
dest: &PlaceTy<'tcx, M::PointerTag>,
264264
// The pointee types
265265
source_ty: Ty<'tcx>,
266266
cast_ty: Ty<'tcx>,
@@ -300,9 +300,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
300300

301301
fn unsize_into(
302302
&mut self,
303-
src: OpTy<'tcx, M::PointerTag>,
303+
src: &OpTy<'tcx, M::PointerTag>,
304304
cast_ty: TyAndLayout<'tcx>,
305-
dest: PlaceTy<'tcx, M::PointerTag>,
305+
dest: &PlaceTy<'tcx, M::PointerTag>,
306306
) -> InterpResult<'tcx> {
307307
trace!("Unsizing {:?} of type {} into {:?}", *src, src.layout.ty, cast_ty.ty);
308308
match (&src.layout.ty.kind(), &cast_ty.ty.kind()) {
@@ -340,9 +340,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
340340
let src_field = self.operand_field(src, i)?;
341341
let dst_field = self.place_field(dest, i)?;
342342
if src_field.layout.ty == cast_ty_field.ty {
343-
self.copy_op(src_field, dst_field)?;
343+
self.copy_op(&src_field, &dst_field)?;
344344
} else {
345-
self.unsize_into(src_field, cast_ty_field, dst_field)?;
345+
self.unsize_into(&src_field, cast_ty_field, &dst_field)?;
346346
}
347347
}
348348
Ok(())

compiler/rustc_mir/src/interpret/eval_context.rs

+27-26
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
548548
/// This can fail to provide an answer for extern types.
549549
pub(super) fn size_and_align_of(
550550
&self,
551-
metadata: MemPlaceMeta<M::PointerTag>,
552-
layout: TyAndLayout<'tcx>,
551+
metadata: &MemPlaceMeta<M::PointerTag>,
552+
layout: &TyAndLayout<'tcx>,
553553
) -> InterpResult<'tcx, Option<(Size, Align)>> {
554554
if !layout.is_unsized() {
555555
return Ok(Some((layout.size, layout.align.abi)));
@@ -577,24 +577,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
577577
// the last field). Can't have foreign types here, how would we
578578
// adjust alignment and size for them?
579579
let field = layout.field(self, layout.fields.count() - 1)?;
580-
let (unsized_size, unsized_align) = match self.size_and_align_of(metadata, field)? {
581-
Some(size_and_align) => size_and_align,
582-
None => {
583-
// A field with extern type. If this field is at offset 0, we behave
584-
// like the underlying extern type.
585-
// FIXME: Once we have made decisions for how to handle size and alignment
586-
// of `extern type`, this should be adapted. It is just a temporary hack
587-
// to get some code to work that probably ought to work.
588-
if sized_size == Size::ZERO {
589-
return Ok(None);
590-
} else {
591-
span_bug!(
592-
self.cur_span(),
593-
"Fields cannot be extern types, unless they are at offset 0"
594-
)
580+
let (unsized_size, unsized_align) =
581+
match self.size_and_align_of(metadata, &field)? {
582+
Some(size_and_align) => size_and_align,
583+
None => {
584+
// A field with extern type. If this field is at offset 0, we behave
585+
// like the underlying extern type.
586+
// FIXME: Once we have made decisions for how to handle size and alignment
587+
// of `extern type`, this should be adapted. It is just a temporary hack
588+
// to get some code to work that probably ought to work.
589+
if sized_size == Size::ZERO {
590+
return Ok(None);
591+
} else {
592+
span_bug!(
593+
self.cur_span(),
594+
"Fields cannot be extern types, unless they are at offset 0"
595+
)
596+
}
595597
}
596-
}
597-
};
598+
};
598599

599600
// FIXME (#26403, #27023): We should be adding padding
600601
// to `sized_size` (to accommodate the `unsized_align`
@@ -645,24 +646,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
645646
#[inline]
646647
pub fn size_and_align_of_mplace(
647648
&self,
648-
mplace: MPlaceTy<'tcx, M::PointerTag>,
649+
mplace: &MPlaceTy<'tcx, M::PointerTag>,
649650
) -> InterpResult<'tcx, Option<(Size, Align)>> {
650-
self.size_and_align_of(mplace.meta, mplace.layout)
651+
self.size_and_align_of(&mplace.meta, &mplace.layout)
651652
}
652653

653654
pub fn push_stack_frame(
654655
&mut self,
655656
instance: ty::Instance<'tcx>,
656657
body: &'mir mir::Body<'tcx>,
657-
return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
658+
return_place: Option<&PlaceTy<'tcx, M::PointerTag>>,
658659
return_to_block: StackPopCleanup,
659660
) -> InterpResult<'tcx> {
660661
// first push a stack frame so we have access to the local substs
661662
let pre_frame = Frame {
662663
body,
663664
loc: Err(body.span), // Span used for errors caused during preamble.
664665
return_to_block,
665-
return_place,
666+
return_place: return_place.copied(),
666667
// empty local array, we fill it in below, after we are inside the stack frame and
667668
// all methods actually know about the frame
668669
locals: IndexVec::new(),
@@ -777,10 +778,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
777778

778779
if !unwinding {
779780
// Copy the return value to the caller's stack frame.
780-
if let Some(return_place) = frame.return_place {
781+
if let Some(ref return_place) = frame.return_place {
781782
let op = self.access_local(&frame, mir::RETURN_PLACE, None)?;
782-
self.copy_op_transmute(op, return_place)?;
783-
trace!("{:?}", self.dump_place(*return_place));
783+
self.copy_op_transmute(&op, return_place)?;
784+
trace!("{:?}", self.dump_place(**return_place));
784785
} else {
785786
throw_ub!(Unreachable);
786787
}

0 commit comments

Comments
 (0)