mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 04:08:40 +00:00
Build records in two phases to avoid cleanups on partial records
This commit is contained in:
parent
432e931a2a
commit
dd1cf63515
@ -3973,6 +3973,21 @@ fn trans_rec(cx: @block_ctxt, fields: [ast::field],
|
|||||||
}
|
}
|
||||||
let ty_fields: [ty::field] = [];
|
let ty_fields: [ty::field] = [];
|
||||||
alt ty::struct(bcx_tcx(cx), t) { ty::ty_rec(flds) { ty_fields = flds; } }
|
alt ty::struct(bcx_tcx(cx), t) { ty::ty_rec(flds) { ty_fields = flds; } }
|
||||||
|
|
||||||
|
tag fieldsrc {
|
||||||
|
provided(lval_result);
|
||||||
|
inherited(ValueRef);
|
||||||
|
}
|
||||||
|
type fieldval = {
|
||||||
|
dst: ValueRef,
|
||||||
|
src: fieldsrc,
|
||||||
|
ty: ty::t
|
||||||
|
};
|
||||||
|
let fieldvals: [fieldval] = [];
|
||||||
|
|
||||||
|
// We build the record in two stages so that we don't have to clean up a
|
||||||
|
// partial record if we fail: first collect all the values, then construct
|
||||||
|
// the record.
|
||||||
for tf: ty::field in ty_fields {
|
for tf: ty::field in ty_fields {
|
||||||
let e_ty = tf.mt.ty;
|
let e_ty = tf.mt.ty;
|
||||||
// FIXME: constraint on argument?
|
// FIXME: constraint on argument?
|
||||||
@ -3984,8 +3999,12 @@ fn trans_rec(cx: @block_ctxt, fields: [ast::field],
|
|||||||
if str::eq(f.node.ident, tf.ident) {
|
if str::eq(f.node.ident, tf.ident) {
|
||||||
expr_provided = true;
|
expr_provided = true;
|
||||||
let lv = trans_lval(bcx, f.node.expr);
|
let lv = trans_lval(bcx, f.node.expr);
|
||||||
bcx =
|
bcx = lv.bcx;
|
||||||
move_val_if_temp(lv.bcx, INIT, dst_res.val, lv, e_ty);
|
fieldvals += [{
|
||||||
|
dst: dst_res.val,
|
||||||
|
src: provided(lv),
|
||||||
|
ty: e_ty
|
||||||
|
}];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3993,12 +4012,30 @@ fn trans_rec(cx: @block_ctxt, fields: [ast::field],
|
|||||||
// FIXME: constraint on argument?
|
// FIXME: constraint on argument?
|
||||||
check type_is_tup_like(bcx, t);
|
check type_is_tup_like(bcx, t);
|
||||||
let src_res = GEP_tup_like(bcx, t, base_val, [0, i]);
|
let src_res = GEP_tup_like(bcx, t, base_val, [0, i]);
|
||||||
src_res =
|
bcx = src_res.bcx;
|
||||||
rslt(src_res.bcx, load_if_immediate(bcx, src_res.val, e_ty));
|
fieldvals += [{
|
||||||
bcx = copy_val(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty);
|
dst: dst_res.val,
|
||||||
|
src: inherited(src_res.val),
|
||||||
|
ty: e_ty
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now build the record
|
||||||
|
for fieldval in fieldvals {
|
||||||
|
alt fieldval.src {
|
||||||
|
provided(lv) {
|
||||||
|
bcx = move_val_if_temp(bcx, INIT, fieldval.dst,
|
||||||
|
lv, fieldval.ty);
|
||||||
|
}
|
||||||
|
inherited(val) {
|
||||||
|
let val = load_if_immediate(bcx, val, fieldval.ty);
|
||||||
|
bcx = copy_val(bcx, INIT, fieldval.dst, val, fieldval.ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
add_clean_temp(cx, rec_val, t);
|
add_clean_temp(cx, rec_val, t);
|
||||||
ret rslt(bcx, rec_val);
|
ret rslt(bcx, rec_val);
|
||||||
}
|
}
|
||||||
|
16
src/test/run-fail/unwind-rec2.rs
Normal file
16
src/test/run-fail/unwind-rec2.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// error-pattern:fail
|
||||||
|
|
||||||
|
fn build1() -> [int] {
|
||||||
|
[0,0,0,0,0,0,0]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build2() -> [int] {
|
||||||
|
fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let blk = {
|
||||||
|
node: build1(),
|
||||||
|
span: build2()
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user