]> git.lizzy.rs Git - rust.git/commitdiff
add visit() hook to the trait
authorRalf Jung <post@ralfj.de>
Thu, 1 Nov 2018 12:11:23 +0000 (13:11 +0100)
committerRalf Jung <post@ralfj.de>
Mon, 5 Nov 2018 08:17:48 +0000 (09:17 +0100)
src/librustc_mir/interpret/validity.rs
src/librustc_mir/interpret/visitor.rs

index 8919db5a6d353c68a31b7217698052238934f537..2d977d109440ef8acfe9b6679054212200fd79bd 100644 (file)
@@ -207,11 +207,11 @@ fn value(&self) -> &OpTy<'tcx, M::PointerTag> {
     }
 
     #[inline]
-    fn with_field(
+    fn visit_field(
         &mut self,
+        ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
         val: Self::V,
         field: usize,
-        f: impl FnOnce(&mut Self) -> EvalResult<'tcx>,
     ) -> EvalResult<'tcx> {
         // Remember the old state
         let path_len = self.path.len();
@@ -219,7 +219,7 @@ fn with_field(
         // Perform operation
         self.push_aggregate_field_path_elem(op.layout, field);
         self.op = val;
-        f(self)?;
+        self.visit(ectx)?;
         // Undo changes
         self.path.truncate(path_len);
         self.op = op;
@@ -596,6 +596,6 @@ pub fn validate_operand(
         };
 
         // Run it
-        self.visit_value(&mut visitor)
+        visitor.visit(self)
     }
 }
index 79b400a821ffa098f90709e6984c210531acf89e..5eb9ff7627d6c852a454f3650605be3a1c85c0fb 100644 (file)
@@ -131,7 +131,7 @@ fn project_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 {
+pub trait ValueVisitor<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: fmt::Debug + Sized {
     type V: Value<'a, 'mir, 'tcx, M>;
 
     // There's a value in here.
@@ -143,16 +143,16 @@ fn layout(&self) -> TyLayout<'tcx> {
         self.value().layout()
     }
 
-    // Replace the value by `val`, which must be the `field`th field of `self`,
-    // then call `f` and then un-do everything that might have happened to the visitor state.
+    // Replace the value by `val`, which must be the `field`th field of `self`, then call
+    // `visit_value` and then un-do everything that might have happened to the visitor state.
     // The point of this is that some visitors keep a stack of fields that we projected below,
     // and this lets us avoid copying that stack; instead they will pop the stack after
-    // executing `f`.
-    fn with_field(
+    // executing `visit_value`.
+    fn visit_field(
         &mut self,
+        ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
         val: Self::V,
         field: usize,
-        f: impl FnOnce(&mut Self) -> EvalResult<'tcx>,
     ) -> EvalResult<'tcx>;
 
     // This is an enum, downcast it to whatever the current variant is.
@@ -170,6 +170,14 @@ fn handle_array(&mut self, _ectx: &EvalContext<'a, 'mir, 'tcx, M>)
         Ok(false)
     }
 
+    // Execute visitor on the current value.  Used for recursing.
+    #[inline]
+    fn visit(&mut self, ectx: &mut EvalContext<'a, 'mir, 'tcx, M>)
+        -> EvalResult<'tcx>
+    {
+        ectx.walk_value(self)
+    }
+
     // Actions on the leaves.
     fn visit_uninhabited(&mut self, ectx: &mut EvalContext<'a, 'mir, 'tcx, M>)
         -> EvalResult<'tcx>;
@@ -180,11 +188,11 @@ fn visit_primitive(&mut self, ectx: &mut EvalContext<'a, 'mir, 'tcx, M>)
 }
 
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
-    pub fn visit_value<V: ValueVisitor<'a, 'mir, 'tcx, M>>(
+    pub fn walk_value<V: ValueVisitor<'a, 'mir, 'tcx, M>>(
         &mut self,
         v: &mut V,
     ) -> EvalResult<'tcx> {
-        trace!("visit_value: {:?}", v);
+        trace!("walk_value: {:?}", v);
 
         // If this is a multi-variant layout, we have find the right one and proceed with that.
         // (No benefit from making this recursion, but it is equivalent to that.)
@@ -205,7 +213,7 @@ pub fn visit_value<V: ValueVisitor<'a, 'mir, 'tcx, M>>(
                 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));
+                return v.visit_field(self, Value::from_mem_place(inner), 0);
             },
             _ => {},
         };
@@ -256,7 +264,7 @@ pub fn visit_value<V: ValueVisitor<'a, 'mir, 'tcx, M>>(
             layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                 for i in 0..offsets.len() {
                     let val = v.value().project_field(self, i as u64)?;
-                    v.with_field(val, i, |v| self.visit_value(v))?;
+                    v.visit_field(self, val, i)?;
                 }
             },
             layout::FieldPlacement::Array { .. } => {
@@ -272,7 +280,7 @@ pub fn visit_value<V: ValueVisitor<'a, 'mir, 'tcx, M>>(
                     };
                     // Now iterate over it.
                     for (i, field) in self.mplace_array_fields(mplace)?.enumerate() {
-                        v.with_field(Value::from_mem_place(field?), i, |v| self.visit_value(v))?;
+                        v.visit_field(self, Value::from_mem_place(field?), i)?;
                     }
                 }
             }