diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index cb2a750f4e3..7c704e97911 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -183,8 +183,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } else if Some(def_id) == self.tcx.lang_items().panic_fn() { assert!(args.len() == 1); // &(&'static str, &'static str, u32, u32) - let ptr = self.read_immediate(args[0])?; - let place = self.ref_to_mplace(ptr)?; + let place = self.deref_operand(args[0])?; let (msg, file, line, col) = ( self.mplace_field(place, 0)?, self.mplace_field(place, 1)?, @@ -192,9 +191,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> self.mplace_field(place, 3)?, ); - let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?; + let msg_place = self.deref_operand(msg.into())?; let msg = Symbol::intern(self.read_str(msg_place)?); - let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?; + let file_place = self.deref_operand(file.into())?; let file = Symbol::intern(self.read_str(file_place)?); let line = self.read_scalar(line.into())?.to_u32()?; let col = self.read_scalar(col.into())?.to_u32()?; @@ -203,17 +202,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> assert!(args.len() == 2); // &'static str, &(&'static str, u32, u32) let msg = args[0]; - let ptr = self.read_immediate(args[1])?; - let place = self.ref_to_mplace(ptr)?; + let place = self.deref_operand(args[1])?; let (file, line, col) = ( self.mplace_field(place, 0)?, self.mplace_field(place, 1)?, self.mplace_field(place, 2)?, ); - let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?; + let msg_place = self.deref_operand(msg.into())?; let msg = Symbol::intern(self.read_str(msg_place)?); - let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?; + let file_place = self.deref_operand(file.into())?; let file = Symbol::intern(self.read_str(file_place)?); let line = self.read_scalar(line.into())?.to_u32()?; let col = self.read_scalar(col.into())?.to_u32()?; diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 83a2d14b7ca..a97bf95e734 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -555,17 +555,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> }) } - // Take an operand, representing a pointer, and dereference it to a place -- that - // will always be a MemPlace. - pub(super) fn deref_operand( - &self, - src: OpTy<'tcx, M::PointerTag>, - ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { - let val = self.read_immediate(src)?; - trace!("deref to {} on {:?}", val.layout.ty, *val); - Ok(self.ref_to_mplace(val)?) - } - pub fn operand_projection( &self, base: OpTy<'tcx, M::PointerTag>, diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index d52250a43ac..510b5826e48 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -277,6 +277,8 @@ where { /// Take a value, which represents a (thin or fat) reference, and make it a place. /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. + /// This does NOT call the "deref" machine hook, so it does NOT count as a + /// deref as far as Stacked Borrows is concerned. Use `deref_operand` for that! pub fn ref_to_mplace( &self, val: ImmTy<'tcx, M::PointerTag>, @@ -284,11 +286,25 @@ where let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty; let layout = self.layout_of(pointee_type)?; - let align = layout.align; - let meta = val.to_meta()?; - let ptr = val.to_scalar_ptr()?; - let mplace = MemPlace { ptr, align, meta }; - let mut mplace = MPlaceTy { mplace, layout }; + let mplace = MemPlace { + ptr: val.to_scalar_ptr()?, + align: layout.align, + meta: val.to_meta()?, + }; + Ok(MPlaceTy { mplace, layout }) + } + + // Take an operand, representing a pointer, and dereference it to a place -- that + // will always be a MemPlace. Lives in `place.rs` because it creates a place. + // This calls the "deref" machine hook, and counts as a deref as far as + // Stacked Borrows is concerned. + pub fn deref_operand( + &self, + src: OpTy<'tcx, M::PointerTag>, + ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + let val = self.read_immediate(src)?; + trace!("deref to {} on {:?}", val.layout.ty, *val); + let mut place = self.ref_to_mplace(val)?; // Pointer tag tracking might want to adjust the tag. let mutbl = match val.layout.ty.sty { // `builtin_deref` considers boxes immutable, that's useless for our purposes @@ -297,9 +313,8 @@ where ty::RawPtr(_) => None, _ => bug!("Unexpected pointer type {}", val.layout.ty.sty), }; - mplace.mplace.ptr = M::tag_dereference(self, mplace, mutbl)?; - // Done - Ok(mplace) + place.mplace.ptr = M::tag_dereference(self, place, mutbl)?; + Ok(place) } /// Offset a pointer to project to a field. Unlike place_field, this is always diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 4cd7ca8182e..6070b31d3e7 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -402,7 +402,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ty::InstanceDef::Virtual(_, idx) => { let ptr_size = self.pointer_size(); let ptr_align = self.tcx.data_layout.pointer_align; - let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?; + let ptr = self.deref_operand(args[0])?; let vtable = ptr.vtable()?; let fn_ptr = self.memory.read_ptr_sized( vtable.offset(ptr_size * (idx as u64 + 3), self)?, diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 8c8b3e2ca77..97bce651c05 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -322,13 +322,10 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> } } } - // Turn ptr into place. - // `ref_to_mplace` also calls the machine hook for (re)activating the tag, - // which in turn will (in full miri) check if the pointer is dereferencable. - let place = self.ecx.ref_to_mplace(value)?; // Recursive checking if let Some(ref mut ref_tracking) = self.ref_tracking { assert!(self.const_mode, "We should only do recursie checking in const mode"); + let place = self.ecx.ref_to_mplace(value)?; if size != Size::ZERO { // Non-ZST also have to be dereferencable let ptr = try_validation!(place.ptr.to_ptr(),