]> git.lizzy.rs Git - rust.git/commitdiff
also allow visiting places and mplaces
authorRalf Jung <post@ralfj.de>
Wed, 31 Oct 2018 18:52:10 +0000 (19:52 +0100)
committerRalf Jung <post@ralfj.de>
Mon, 5 Nov 2018 08:17:48 +0000 (09:17 +0100)
src/librustc_mir/interpret/visitor.rs

index 7d6029d6424f718c68febbf520c72ec0e80c62aa..79b400a821ffa098f90709e6984c210531acf89e 100644 (file)
@@ -10,7 +10,7 @@
 };
 
 use super::{
-    Machine, EvalContext, MPlaceTy, OpTy,
+    Machine, EvalContext, MPlaceTy, PlaceTy, OpTy,
 };
 
 // A thing that we can project into, and that has a layout.
@@ -21,13 +21,16 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
     // Get this value's layout.
     fn layout(&self) -> TyLayout<'tcx>;
 
-    // Get the underlying `MPlaceTy`, or panic if there is no such thing.
-    fn to_mem_place(self) -> MPlaceTy<'tcx, M::PointerTag>;
+    // Make this a `MPlaceTy`, or panic if that's not possible.
+    fn force_allocation(
+        self,
+        ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>>;
 
-    // Create this from an `MPlaceTy`
+    // Create this from an `MPlaceTy`.
     fn from_mem_place(MPlaceTy<'tcx, M::PointerTag>) -> Self;
 
-    // Project to the n-th field
+    // Project to the n-th field.
     fn project_field(
         self,
         ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
@@ -45,8 +48,11 @@ fn layout(&self) -> TyLayout<'tcx> {
     }
 
     #[inline(always)]
-    fn to_mem_place(self) -> MPlaceTy<'tcx, M::PointerTag> {
-        self.to_mem_place()
+    fn force_allocation(
+        self,
+        _ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        Ok(self.to_mem_place())
     }
 
     #[inline(always)]
@@ -63,6 +69,66 @@ fn project_field(
         ectx.operand_field(self, field)
     }
 }
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
+    for MPlaceTy<'tcx, M::PointerTag>
+{
+    #[inline(always)]
+    fn layout(&self) -> TyLayout<'tcx> {
+        self.layout
+    }
+
+    #[inline(always)]
+    fn force_allocation(
+        self,
+        _ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        Ok(self)
+    }
+
+    #[inline(always)]
+    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
+        mplace
+    }
+
+    #[inline(always)]
+    fn project_field(
+        self,
+        ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
+        field: u64,
+    ) -> EvalResult<'tcx, Self> {
+        ectx.mplace_field(self, field)
+    }
+}
+impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
+    for PlaceTy<'tcx, M::PointerTag>
+{
+    #[inline(always)]
+    fn layout(&self) -> TyLayout<'tcx> {
+        self.layout
+    }
+
+    #[inline(always)]
+    fn force_allocation(
+        self,
+        ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        ectx.force_allocation(self)
+    }
+
+    #[inline(always)]
+    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
+        mplace.into()
+    }
+
+    #[inline(always)]
+    fn project_field(
+        self,
+        ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
+        field: u64,
+    ) -> EvalResult<'tcx, Self> {
+        ectx.place_field(self, field)
+    }
+}
 
 // How to traverse a value and what to do when we are at the leaves.
 pub trait ValueVisitor<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: fmt::Debug {
@@ -135,7 +201,8 @@ pub fn visit_value<V: ValueVisitor<'a, 'mir, 'tcx, M>>(
         // If it is a trait object, switch to the actual type that was used to create it.
         match v.layout().ty.sty {
             ty::Dynamic(..) => {
-                let dest = v.value().to_mem_place(); // immediate trait objects are not a thing
+                // immediate trait objects are not a thing
+                let dest = v.value().force_allocation(self)?;
                 let inner = self.unpack_dyn_trait(dest)?.1;
                 // recurse with the inner type
                 return v.with_field(Value::from_mem_place(inner), 0, |v| self.visit_value(v));
@@ -201,7 +268,7 @@ pub fn visit_value<V: ValueVisitor<'a, 'mir, 'tcx, M>>(
                         MPlaceTy::dangling(v.layout(), self)
                     } else {
                         // non-ZST array/slice/str cannot be immediate
-                        v.value().to_mem_place()
+                        v.value().force_allocation(self)?
                     };
                     // Now iterate over it.
                     for (i, field) in self.mplace_array_fields(mplace)?.enumerate() {