Skip to content

Commit b00fd57

Browse files
committed
implement by-value object safety
1 parent 944ffbf commit b00fd57

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

src/librustc_mir/interpret/terminator.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -407,25 +407,41 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
407407
}
408408
// cannot use the shim here, because that will only result in infinite recursion
409409
ty::InstanceDef::Virtual(_, idx) => {
410+
let mut args = args.to_vec();
410411
let ptr_size = self.pointer_size();
411-
let ptr = self.deref_operand(args[0])?;
412-
let vtable = ptr.vtable()?;
412+
// We have to implement all "object safe receivers". Currently we
413+
// support built-in pointers (&, &mut, Box) as well as unsized-self. We do
414+
// not yet support custom self types.
415+
// Also see librustc_codegen_llvm/abi.rs and librustc_codegen_llvm/mir/block.rs.
416+
let receiver_place = match args[0].layout.ty.builtin_deref(true) {
417+
Some(_) => {
418+
// Built-in pointer.
419+
self.deref_operand(args[0])?
420+
}
421+
None => {
422+
// Unsized self.
423+
args[0].to_mem_place()
424+
}
425+
};
426+
// Find and consult vtable
427+
let vtable = receiver_place.vtable()?;
413428
self.memory.check_align(vtable.into(), self.tcx.data_layout.pointer_align.abi)?;
414429
let fn_ptr = self.memory.get(vtable.alloc_id)?.read_ptr_sized(
415430
self,
416431
vtable.offset(ptr_size * (idx as u64 + 3), self)?,
417432
)?.to_ptr()?;
418433
let instance = self.memory.get_fn(fn_ptr)?;
419434

420-
// We have to patch the self argument, in particular get the layout
421-
// expected by the actual function. Cannot just use "field 0" due to
422-
// Box<self>.
423-
let mut args = args.to_vec();
424-
let pointee = args[0].layout.ty.builtin_deref(true).unwrap().ty;
425-
let fake_fat_ptr_ty = self.tcx.mk_mut_ptr(pointee);
426-
args[0] = OpTy::from(ImmTy { // strip vtable
427-
layout: self.layout_of(fake_fat_ptr_ty)?.field(self, 0)?,
428-
imm: Immediate::Scalar(ptr.ptr.into())
435+
// `*mut receiver_place.layout.ty` is almost the layout that we
436+
// want for args[0]: We have to project to field 0 because we want
437+
// a thin pointer.
438+
assert!(receiver_place.layout.is_unsized());
439+
let receiver_ptr_ty = self.tcx.mk_mut_ptr(receiver_place.layout.ty);
440+
let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0)?;
441+
// Adjust receiver argument.
442+
args[0] = OpTy::from(ImmTy {
443+
layout: this_receiver_ptr,
444+
imm: Immediate::Scalar(receiver_place.ptr.into())
429445
});
430446
trace!("Patched self operand to {:#?}", args[0]);
431447
// recurse with concrete function

src/librustc_mir/interpret/traits.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc::ty::{self, Ty};
33
use rustc::ty::layout::{Size, Align, LayoutOf};
44
use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
55

6-
use super::{InterpretCx, Machine, MemoryKind};
6+
use super::{InterpretCx, InterpError, Machine, MemoryKind};
77

88
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
99
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
@@ -76,7 +76,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
7676

7777
for (i, method) in methods.iter().enumerate() {
7878
if let Some((def_id, substs)) = *method {
79-
let instance = self.resolve(def_id, substs)?;
79+
// resolve for vtable: insert thims where needed
80+
let substs = self.subst_and_normalize_erasing_regions(substs)?;
81+
let instance = ty::Instance::resolve_for_vtable(
82+
*self.tcx,
83+
self.param_env,
84+
def_id,
85+
substs,
86+
).ok_or_else(|| InterpError::TooGeneric)?;
8087
let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag();
8188
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?;
8289
self.memory

0 commit comments

Comments
 (0)