提交 32644310 编写于 作者: F Felix S. Klock II

trans: When coercing to `Box<Trait>` or `Box<[T]>`, leave datum in its original L-/R-value state.

This fixes a subtle issue where temporaries were being allocated (but
not necessarily initialized) to the (parent) terminating scope of a
match expression; in particular, the code to zero out the temporary
emitted by `datum.store_to` is only attached to the particular
match-arm for that temporary, but when going down other arms of the
match expression, the temporary may falsely appear to have been
initialized, depending on what the stack held at that location, and
thus may have its destructor erroneously run at the end of the
terminating scope.

Test cases to appear in a follow-up commit.

Fix #20055
上级 e365e4c0
......@@ -420,9 +420,15 @@ fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let tcx = bcx.tcx();
let datum_ty = datum.ty;
// Arrange cleanup
let lval = unpack_datum!(bcx,
datum.to_lvalue_datum(bcx, "unsize_unique_vec", expr.id));
debug!("unsize_unique_vec expr.id={} datum_ty={} len={}",
expr.id, datum_ty.repr(tcx), len);
// We do not arrange cleanup ourselves; if we already are an
// L-value, then cleanup will have already been scheduled (and
// the `datum.store_to` call below will emit code to zero the
// drop flag when moving out of the L-value). If we are an R-value,
// then we do not need to schedule cleanup.
let ll_len = C_uint(bcx.ccx(), len);
let unit_ty = ty::sequence_element_type(tcx, ty::type_content(datum_ty));
......@@ -433,7 +439,7 @@ fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let base = PointerCast(bcx,
base,
type_of::type_of(bcx.ccx(), datum_ty).ptr_to());
bcx = lval.store_to(bcx, base);
bcx = datum.store_to(bcx, base);
Store(bcx, ll_len, get_len(bcx, scratch.val));
DatumBlock::new(bcx, scratch.to_expr_datum())
......@@ -455,13 +461,16 @@ fn unsize_unique_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
};
let result_ty = ty::mk_uniq(tcx, ty::unsize_ty(tcx, unboxed_ty, k, expr.span));
let lval = unpack_datum!(bcx,
datum.to_lvalue_datum(bcx, "unsize_unique_expr", expr.id));
// We do not arrange cleanup ourselves; if we already are an
// L-value, then cleanup will have already been scheduled (and
// the `datum.store_to` call below will emit code to zero the
// drop flag when moving out of the L-value). If we are an R-value,
// then we do not need to schedule cleanup.
let scratch = rvalue_scratch_datum(bcx, result_ty, "__uniq_fat_ptr");
let llbox_ty = type_of::type_of(bcx.ccx(), datum_ty);
let base = PointerCast(bcx, get_dataptr(bcx, scratch.val), llbox_ty.ptr_to());
bcx = lval.store_to(bcx, base);
bcx = datum.store_to(bcx, base);
let info = unsized_info(bcx, k, expr.id, unboxed_ty, |t| ty::mk_uniq(tcx, t));
Store(bcx, info, get_len(bcx, scratch.val));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册