about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-12-28 02:29:14 +0000
committerbors <bors@rust-lang.org>2015-12-28 02:29:14 +0000
commit0e9f6ecd0e38b22373e4ba1095a571cd635822bc (patch)
tree2b0af6f8224bd18535e4937b8d35c1dbbcbc9cef
parentb4707ebca321e9ea9e73a3b061b2213c2a9bdf14 (diff)
parent575f690b39559160e31930726b5629dfbd3526fa (diff)
downloadrust-0e9f6ecd0e38b22373e4ba1095a571cd635822bc.tar.gz
rust-0e9f6ecd0e38b22373e4ba1095a571cd635822bc.zip
Auto merge of #30579 - dotdash:30478, r=arielb1
`auto_ref()` currently returns an Rvalue datum for the ref'd value,
which is fine for thin pointers, but for fat pointers this means that
once the pointer is moved out of that datum, its memory will be marked
as dead. And because there is not necessarily an intermediate temporary
involved we can end up marking memory as dead that is actually still
used.

As I don't want to break the micro-optimization for thin pointers by
always returning an Lvalue datum, I decided to only do so for fat
pointers.

Fix #30478
-rw-r--r--src/librustc_trans/trans/expr.rs18
1 files changed, 11 insertions, 7 deletions
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index ecf54cde9f6..85d4876d160 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -2187,15 +2187,19 @@ fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let referent_ty = lv_datum.ty;
     let ptr_ty = bcx.tcx().mk_imm_ref(bcx.tcx().mk_region(ty::ReStatic), referent_ty);
 
+    // Construct the resulting datum. The right datum to return here would be an Lvalue datum,
+    // because there is cleanup scheduled and the datum doesn't own the data, but for thin pointers
+    // we microoptimize it to be an Rvalue datum to avoid the extra alloca and level of
+    // indirection and for thin pointers, this has no ill effects.
+    let kind  = if type_is_sized(bcx.tcx(), referent_ty) {
+        RvalueExpr(Rvalue::new(ByValue))
+    } else {
+        LvalueExpr(lv_datum.kind)
+    };
+
     // Get the pointer.
     let llref = lv_datum.to_llref();
-
-    // Construct the resulting datum, using what was the "by ref"
-    // ValueRef of type `referent_ty` to be the "by value" ValueRef
-    // of type `&referent_ty`.
-    // Pointers to DST types are non-immediate, and therefore still use ByRef.
-    let kind  = if type_is_sized(bcx.tcx(), referent_ty) { ByValue } else { ByRef };
-    DatumBlock::new(bcx, Datum::new(llref, ptr_ty, RvalueExpr(Rvalue::new(kind))))
+    DatumBlock::new(bcx, Datum::new(llref, ptr_ty, kind))
 }
 
 fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,