From bc647e9d33009bcf3327d298a8251630d8504e52 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 17 Oct 2018 14:50:36 +0200 Subject: [PATCH] add 'raw reference' to the machine hook, and use that in ptr-to-raw casts --- src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/interpret/cast.rs | 23 ++++++++++++++++++----- src/librustc_mir/interpret/machine.rs | 3 ++- src/librustc_mir/interpret/place.rs | 2 +- src/librustc_mir/interpret/step.rs | 2 +- src/librustc_mir/interpret/terminator.rs | 2 +- 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 66fd5edcc90b..ebe877484c62 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -468,7 +468,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> _ptr: Pointer, _pointee_ty: Ty<'tcx>, _pointee_size: Size, - _borrow_kind: mir::BorrowKind, + _borrow_kind: Option, ) -> EvalResult<'tcx, Self::PointerTag> { Ok(()) } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index f5e824b76288..9b11a1637c63 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -38,7 +38,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> dest: PlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx> { let src_layout = src.layout; - let dst_layout = dest.layout; use rustc::mir::CastKind::*; match kind { Unsize => { @@ -47,7 +46,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> Misc => { let src = self.read_value(src)?; - if self.type_is_fat_ptr(src_layout.ty) { + + if src.layout.ty.is_region_ptr() && dest.layout.ty.is_unsafe_ptr() { + // For the purpose of the "ptr tag hooks", treat this as creating + // a new, raw reference. + let place = self.ref_to_mplace(src)?; + let _val = self.create_ref(place, None)?; + // FIXME: The blog post said we should now also erase the tag. + // That would amount to using `_val` instead of `src` from here on. + // However, do we really want to do that? `transmute` doesn't + // do it either and we have to support that, somehow. + } + + if self.type_is_fat_ptr(src.layout.ty) { match (*src, self.type_is_fat_ptr(dest.layout.ty)) { // pointers to extern types (Value::Scalar(_),_) | @@ -65,11 +76,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> match src_layout.variants { layout::Variants::Single { index } => { if let Some(def) = src_layout.ty.ty_adt_def() { + // Cast from a univariant enum + assert!(src.layout.is_zst()); let discr_val = def .discriminant_for_variant(*self.tcx, index) .val; return self.write_scalar( - Scalar::from_uint(discr_val, dst_layout.size), + Scalar::from_uint(discr_val, dest.layout.size), dest); } } @@ -85,7 +98,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ReifyFnPointer => { // The src operand does not matter, just its type - match src_layout.ty.sty { + match src.layout.ty.sty { ty::FnDef(def_id, substs) => { if self.tcx.has_attr(def_id, "rustc_args_required_const") { bug!("reifying a fn ptr that requires \ @@ -117,7 +130,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ClosureFnPointer => { // The src operand does not matter, just its type - match src_layout.ty.sty { + match src.layout.ty.sty { ty::Closure(def_id, substs) => { let substs = self.tcx.subst_and_normalize_erasing_regions( self.substs(), diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index a3e52919f02c..8f7abea47d87 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -201,12 +201,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { /// Executed when evaluating the `&` operator: Creating a new reference. /// This has the chance to adjust the tag. + /// `borrow_kind` can be `None` in case a raw ptr is being created. fn tag_reference( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer, pointee_ty: Ty<'tcx>, pointee_size: Size, - borrow_kind: mir::BorrowKind, + borrow_kind: Option, ) -> EvalResult<'tcx, Self::PointerTag>; /// Executed when evaluating the `*` operator: Following a reference. diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 1b319b012978..6ee70bac583d 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -291,7 +291,7 @@ where pub fn create_ref( &mut self, place: MPlaceTy<'tcx, M::PointerTag>, - borrow_kind: mir::BorrowKind, + borrow_kind: Option, ) -> EvalResult<'tcx, Value> { let ptr = match place.ptr { Scalar::Ptr(ptr) => { diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index cb629e8313cd..1bab536e3e0f 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -251,7 +251,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> Ref(_, borrow_kind, ref place) => { let src = self.eval_place(place)?; let val = self.force_allocation(src)?; - let val = self.create_ref(val, borrow_kind)?; + let val = self.create_ref(val, Some(borrow_kind))?; self.write_value(val, dest)?; } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index bb2dc7322004..c759727f546c 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -448,7 +448,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let arg = OpTy { op: Operand::Immediate(self.create_ref( place, - mir::BorrowKind::Mut { allow_two_phase_borrow: false } + None // this is a "raw reference" )?), layout: self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?, };