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
This commit is contained in:
Björn Steinbrink 2015-12-27 17:56:15 +01:00
parent 38201501df
commit 575f690b39

View File

@ -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>,