From 575f690b39559160e31930726b5629dfbd3526fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sun, 27 Dec 2015 17:56:15 +0100 Subject: [PATCH] Fix `auto_ref()` for fat pointers `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 --- src/librustc_trans/trans/expr.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index ecf54cde9f63a..85d4876d160be 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>,