diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index baf6a4ecaa02..66fd5edcc90b 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -19,8 +19,8 @@ use std::collections::hash_map::Entry; use rustc::hir::{self, def_id::DefId}; use rustc::mir::interpret::ConstEvalErr; use rustc::mir; -use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt}; -use rustc::ty::layout::{self, LayoutOf, TyLayout}; +use rustc::ty::{self, Ty, TyCtxt, Instance, query::TyCtxtAt}; +use rustc::ty::layout::{self, Size, LayoutOf, TyLayout}; use rustc::ty::subst::Subst; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashMap; @@ -28,13 +28,10 @@ use rustc_data_structures::fx::FxHashMap; use syntax::ast::Mutability; use syntax::source_map::{Span, DUMMY_SP}; -use rustc::mir::interpret::{ - EvalResult, EvalError, EvalErrorKind, GlobalId, - Scalar, Allocation, AllocId, ConstValue, -}; use interpret::{self, - PlaceTy, MPlaceTy, MemPlace, OpTy, Operand, Value, - EvalContext, StackPopCleanup, MemoryKind, + PlaceTy, MemPlace, OpTy, Operand, Value, Pointer, Scalar, ConstValue, + EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup, + Allocation, AllocId, MemoryKind, snapshot, }; @@ -468,11 +465,22 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> #[inline(always)] fn tag_reference( _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - _place: MPlaceTy<'tcx, Self::PointerTag>, + _ptr: Pointer, + _pointee_ty: Ty<'tcx>, + _pointee_size: Size, _borrow_kind: mir::BorrowKind, ) -> EvalResult<'tcx, Self::PointerTag> { Ok(()) } + + #[inline(always)] + fn tag_dereference( + _ecx: &EvalContext<'a, 'mir, 'tcx, Self>, + _ptr: Pointer, + _ptr_ty: Ty<'tcx>, + ) -> EvalResult<'tcx, Self::PointerTag> { + Ok(()) + } } /// Project to a field of a (variant of a) const diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index e30874ce7b38..5dd33ec551d7 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -17,11 +17,11 @@ use std::hash::Hash; use rustc::hir::def_id::DefId; use rustc::mir; -use rustc::ty::{self, layout::{Size, TyLayout}, query::TyCtxtAt}; +use rustc::ty::{self, Ty, layout::{Size, TyLayout}, query::TyCtxtAt}; use super::{ Allocation, AllocId, EvalResult, Scalar, - EvalContext, PlaceTy, OpTy, MPlaceTy, Pointer, MemoryKind, + EvalContext, PlaceTy, OpTy, Pointer, MemoryKind, }; /// Classifying memory accesses @@ -199,14 +199,23 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { } /// Executed when evaluating the `&` operator: Creating a new reference. - /// This has the chance to adjust the tag. It is only ever called if the - /// pointer in `place` is really a pointer, not another scalar. + /// This has the chance to adjust the tag. fn tag_reference( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, - place: MPlaceTy<'tcx, Self::PointerTag>, + ptr: Pointer, + pointee_ty: Ty<'tcx>, + pointee_size: Size, borrow_kind: mir::BorrowKind, ) -> EvalResult<'tcx, Self::PointerTag>; + /// Executed when evaluating the `*` operator: Following a reference. + /// This has the change to adjust the tag. + fn tag_dereference( + ecx: &EvalContext<'a, 'mir, 'tcx, Self>, + ptr: Pointer, + ptr_ty: Ty<'tcx>, + ) -> EvalResult<'tcx, Self::PointerTag>; + /// Execute a validation operation #[inline] fn validation_op( diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 51406a686bcc..1b319b012978 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -264,14 +264,24 @@ where &self, val: ValTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + let ptr = match val.to_scalar_ptr()? { + Scalar::Ptr(ptr) => { + // Machine might want to track the `*` operator + let tag = M::tag_dereference(self, ptr, val.layout.ty)?; + Scalar::Ptr(Pointer::new_with_tag(ptr.alloc_id, ptr.offset, tag)) + } + scalar @ Scalar::Bits { .. } => scalar, + }; + let pointee_type = val.layout.ty.builtin_deref(true).unwrap().ty; let layout = self.layout_of(pointee_type)?; let align = layout.align; + let mplace = match *val { - Value::Scalar(ptr) => - MemPlace { ptr: ptr.not_undef()?, align, meta: None }, - Value::ScalarPair(ptr, meta) => - MemPlace { ptr: ptr.not_undef()?, align, meta: Some(meta.not_undef()?) }, + Value::Scalar(_) => + MemPlace { ptr, align, meta: None }, + Value::ScalarPair(_, meta) => + MemPlace { ptr, align, meta: Some(meta.not_undef()?) }, }; Ok(MPlaceTy { mplace, layout }) } @@ -285,7 +295,10 @@ where ) -> EvalResult<'tcx, Value> { let ptr = match place.ptr { Scalar::Ptr(ptr) => { - let tag = M::tag_reference(self, place, borrow_kind)?; + // Machine might want to track the `&` operator + let (size, _) = self.size_and_align_of_mplace(place)? + .expect("create_ref cannot determine size"); + let tag = M::tag_reference(self, ptr, place.layout.ty, size, borrow_kind)?; Scalar::Ptr(Pointer::new_with_tag(ptr.alloc_id, ptr.offset, tag)) }, scalar @ Scalar::Bits { .. } => scalar,