diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index b43c810b8e626..3d97132e53969 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -217,13 +217,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Normalice `place.ptr` to a `Pointer` if this is a place and not a ZST. /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. #[inline] - pub fn normalize_op_ptr( + pub fn force_op_ptr( &self, op: OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { match op.try_as_mplace() { - Ok(mplace) => Ok(self.normalize_mplace_ptr(mplace)?.into()), - Err(imm) => Ok(imm.into()), // Nothing to normalize + Ok(mplace) => Ok(self.force_mplace_ptr(mplace)?.into()), + Err(imm) => Ok(imm.into()), // Nothing to cast/force } } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 6b8eb3fa77353..50e3789ed8070 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -327,15 +327,13 @@ where self.memory.check_ptr_access(place.ptr, size, place.align) } - /// Normalice `place.ptr` to a `Pointer` if this is not a ZST. + /// Force `place.ptr` to a `Pointer`. /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. - pub fn normalize_mplace_ptr( + pub fn force_mplace_ptr( &self, mut place: MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { - if !place.layout.is_zst() { - place.mplace.ptr = self.force_ptr(place.mplace.ptr)?.into(); - } + place.mplace.ptr = self.force_ptr(place.mplace.ptr)?.into(); Ok(place) } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index bf062ac68a5c1..00107a536ba26 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -444,7 +444,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // `!` is a ZST and we want to validate it. // Normalize before handing `place` to tracking because that will // check for duplicates. - let place = self.ecx.normalize_mplace_ptr(place)?; + let place = if size.bytes() > 0 { + self.ecx.force_mplace_ptr(place) + .expect("we already bounds-checked") + } else { + place + }; let path = &self.path; ref_tracking.track(place, || { // We need to clone the path anyway, make sure it gets created @@ -578,8 +583,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> let ty_size = self.ecx.layout_of(tys)?.size; // This is the size in bytes of the whole array. let size = ty_size * len; - // Size is not 0, get a pointer (no cast because we normalized in validate_operand). - let ptr = mplace.ptr.assert_ptr(); + // Size is not 0, get a pointer. + let ptr = self.ecx.force_ptr(mplace.ptr)?; // NOTE: Keep this in sync with the handling of integer and float // types above, in `visit_primitive`. @@ -654,8 +659,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ecx: self, }; + // Try to cast to ptr *once* instead of all the time. + let op = self.force_op_ptr(op).unwrap_or(op); + // Run it - let op = self.normalize_op_ptr(op)?; // avoid doing ptr-to-int all the time visitor.visit_value(op) } }