about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2017-08-04 16:01:46 -0700
committerRalf Jung <post@ralfj.de>2017-08-04 16:02:16 -0700
commitfb2ed457c6bdbe587e2ac21c2f671d3e30bab353 (patch)
tree530e47f37d49ed7791926f80cb6ede5b7227f876 /src
parent4957031e3cf2333ae5c5519ffd03237eb4ca426c (diff)
downloadrust-fb2ed457c6bdbe587e2ac21c2f671d3e30bab353.tar.gz
rust-fb2ed457c6bdbe587e2ac21c2f671d3e30bab353.zip
consolidate making Undef release a NOP in one place
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/interpret/validation.rs17
-rw-r--r--src/librustc_mir/interpret/value.rs2
2 files changed, 10 insertions, 9 deletions
diff --git a/src/librustc_mir/interpret/validation.rs b/src/librustc_mir/interpret/validation.rs
index 5b7c932efc2..f77c7d65ff7 100644
--- a/src/librustc_mir/interpret/validation.rs
+++ b/src/librustc_mir/interpret/validation.rs
@@ -11,7 +11,7 @@ use super::{
     EvalError, EvalResult, EvalErrorKind,
     EvalContext, DynamicLifetime,
     AccessKind, LockInfo,
-    PrimVal, Value,
+    Value,
     Lvalue, LvalueExtra,
     Machine,
 };
@@ -156,10 +156,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
     fn validate(&mut self, query: ValidationQuery<'tcx>, mode: ValidationMode) -> EvalResult<'tcx>
     {
         match self.try_validate(query, mode) {
-            // HACK: If, during releasing, we hit memory we cannot use, we just ignore that.
-            // This can happen because releases are added before drop elaboration.
-            // TODO: Fix the MIR so that these releases do not happen.
-            res @ Err(EvalError{ kind: EvalErrorKind::DanglingPointerDeref, ..}) |
+            // Releasing an uninitalized variable is a NOP.  This is needed because
+            // we have to release the return value of a function; due to destination-passing-style
+            // the callee may directly write there.
+            // TODO: Ideally we would know whether the destination is already initialized, and only
+            // release if it is.
             res @ Err(EvalError{ kind: EvalErrorKind::ReadUndefBytes, ..}) => {
                 if let ValidationMode::Release = mode {
                     return Ok(());
@@ -187,16 +188,14 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             }
         }
 
-        // Release of an Undef local is fine, and a NOP.
         // HACK: For now, bail out if we hit a dead local during recovery (can happen because sometimes we have
-        // StorageDead before EndRegion).
+        // StorageDead before EndRegion due to https://github.com/rust-lang/rust/issues/43481).
         // TODO: We should rather fix the MIR.
         match query.lval {
             Lvalue::Local { frame, local } => {
                 let res = self.stack[frame].get_local(local);
                 match (res, mode) {
-                    (Err(EvalError{ kind: EvalErrorKind::DeadLocal, ..}), ValidationMode::Recover(_)) |
-                    (Ok(Value::ByVal(PrimVal::Undef)), ValidationMode::Release) => {
+                    (Err(EvalError{ kind: EvalErrorKind::DeadLocal, ..}), ValidationMode::Recover(_)) => {
                         return Ok(());
                     }
                     _ => {},
diff --git a/src/librustc_mir/interpret/value.rs b/src/librustc_mir/interpret/value.rs
index 163643be01c..88ffc57a8f0 100644
--- a/src/librustc_mir/interpret/value.rs
+++ b/src/librustc_mir/interpret/value.rs
@@ -197,6 +197,7 @@ impl<'a, 'tcx: 'a> Value {
 
             ByValPair(ptr, vtable) => Ok((ptr.into(), vtable.to_ptr()?)),
 
+            ByVal(PrimVal::Undef) => err!(ReadUndefBytes),
             _ => bug!("expected ptr and vtable, got {:?}", self),
         }
     }
@@ -216,6 +217,7 @@ impl<'a, 'tcx: 'a> Value {
                 assert_eq!(len as u64 as u128, len);
                 Ok((ptr.into(), len as u64))
             },
+            ByVal(PrimVal::Undef) => err!(ReadUndefBytes),
             ByVal(_) => bug!("expected ptr and length, got {:?}", self),
         }
     }