about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-11-02 10:01:22 +0100
committerRalf Jung <post@ralfj.de>2018-11-05 09:40:05 +0100
commit996a42557e2816cd577120f464c52b865ef8a924 (patch)
tree0851fc311c1b222b428be1d4192c60a4192bf920
parentc2677211f65758f19d7051d6f24a34ce0ec44119 (diff)
downloadrust-996a42557e2816cd577120f464c52b865ef8a924.tar.gz
rust-996a42557e2816cd577120f464c52b865ef8a924.zip
the visitor can already load the value for visit_primitive
-rw-r--r--src/librustc_mir/interpret/validity.rs19
-rw-r--r--src/librustc_mir/interpret/visitor.rs14
-rw-r--r--src/test/ui/consts/const-eval/ub-ref.stderr2
3 files changed, 19 insertions, 16 deletions
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index c303d2a1e67..5ba15f4bb99 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -20,7 +20,7 @@ use rustc::mir::interpret::{
 };
 
 use super::{
-    OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor
+    OpTy, MPlaceTy, ImmTy, Machine, EvalContext, ValueVisitor
 };
 
 macro_rules! validation_failure {
@@ -213,7 +213,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
     fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
     {
         trace!("visit_value: {:?}, {:?}", *op, op.layout);
-        // Translate enum discriminant errors to something nicer.
+        // Translate some possible errors to something nicer.
         match self.walk_value(op) {
             Ok(()) => Ok(()),
             Err(err) => match err.kind {
@@ -221,16 +221,17 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
                     validation_failure!(
                         val, self.path, "a valid enum discriminant"
                     ),
+                EvalErrorKind::ReadPointerAsBytes =>
+                    validation_failure!(
+                        "a pointer", self.path, "plain bytes"
+                    ),
                 _ => Err(err),
             }
         }
     }
 
-    fn visit_primitive(&mut self, op: OpTy<'tcx, M::PointerTag>)
-        -> EvalResult<'tcx>
+    fn visit_primitive(&mut self, value: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
     {
-        let value = try_validation!(self.ecx.read_immediate(op),
-            "uninitialized or unrepresentable data", self.path);
         // Go over all the primitive types
         let ty = value.layout.ty;
         match ty.sty {
@@ -379,8 +380,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
         Ok(())
     }
 
-    fn visit_uninhabited(&mut self, _op: OpTy<'tcx, M::PointerTag>)
-        -> EvalResult<'tcx>
+    fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
     {
         validation_failure!("a value of an uninhabited type", self.path)
     }
@@ -390,8 +390,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
         op: OpTy<'tcx, M::PointerTag>,
         layout: &layout::Scalar,
     ) -> EvalResult<'tcx> {
-        let value = try_validation!(self.ecx.read_scalar(op),
-            "uninitialized or unrepresentable data", self.path);
+        let value = self.ecx.read_scalar(op)?;
         // Determine the allowed range
         let (lo, hi) = layout.valid_range.clone().into_inner();
         // `max_hi` is as big as the size fits
diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs
index 7ae747a7357..3211601400a 100644
--- a/src/librustc_mir/interpret/visitor.rs
+++ b/src/librustc_mir/interpret/visitor.rs
@@ -8,7 +8,7 @@ use rustc::mir::interpret::{
 };
 
 use super::{
-    Machine, EvalContext, MPlaceTy, PlaceTy, OpTy,
+    Machine, EvalContext, MPlaceTy, PlaceTy, OpTy, ImmTy,
 };
 
 // A thing that we can project into, and that has a layout.
@@ -205,9 +205,11 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
     /// Called whenever we reach a value with uninhabited layout.
     /// Recursing to fields will continue after this!
     #[inline(always)]
-    fn visit_uninhabited(&mut self, _v: Self::V) -> EvalResult<'tcx>
+    fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
     { Ok(()) }
     /// Called whenever we reach a value with scalar layout.
+    /// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory
+    /// if the visitor is not even interested in scalars.
     /// Recursing to fields will continue after this!
     #[inline(always)]
     fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<'tcx>
@@ -215,7 +217,7 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
     /// Called whenever we reach a value of primitive type.  There can be no recursion
     /// below such a value.
     #[inline(always)]
-    fn visit_primitive(&mut self, _v: Self::V) -> EvalResult<'tcx>
+    fn visit_primitive(&mut self, _val: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
     { Ok(()) }
 
     // Default recursors. Not meant to be overloaded.
@@ -275,7 +277,7 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
         // MyNewtype and then the scalar in there).
         match v.layout().abi {
             layout::Abi::Uninhabited => {
-                self.visit_uninhabited(v)?;
+                self.visit_uninhabited()?;
             }
             layout::Abi::Scalar(ref layout) => {
                 self.visit_scalar(v, layout)?;
@@ -295,7 +297,9 @@ pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Siz
             _ => v.layout().ty.builtin_deref(true).is_some(),
         };
         if primitive {
-            return self.visit_primitive(v);
+            let op = v.to_op(self.ecx())?;
+            let val = self.ecx().read_immediate(op)?;
+            return self.visit_primitive(val);
         }
 
         // Proceed into the fields.
diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr
index 359d1abb500..c3f5f4a26f5 100644
--- a/src/test/ui/consts/const-eval/ub-ref.stderr
+++ b/src/test/ui/consts/const-eval/ub-ref.stderr
@@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref.rs:25:1
    |
 LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a raw memory access tried to access part of a pointer value as raw bytes
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain bytes
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior