Dereference classes with dtors only on a field access
A class with a dtor has a different representation (a pair of a bit field and a pointer to the class itself), and previously, the trans code was selecting out the second field on any reference to a variable whose type was a class with a dtor. This turned out to be wrong in the case where a closure captures a variable with such a type. Changed the code to only insert the field selection on a class field access.
This commit is contained in:
parent
7daf986aec
commit
8972588583
1 changed files with 14 additions and 14 deletions
|
@ -2448,19 +2448,7 @@ fn trans_local_var(cx: block, def: ast::def) -> local_var_result {
|
||||||
}
|
}
|
||||||
ast::def_self(sid) {
|
ast::def_self(sid) {
|
||||||
let slf = alt copy cx.fcx.llself {
|
let slf = alt copy cx.fcx.llself {
|
||||||
some(s) {
|
some(s) { cast_self(cx, s) }
|
||||||
alt option::map(ty::ty_to_def_id(s.t)) {|did|
|
|
||||||
ty::ty_dtor(cx.tcx(), did)} {
|
|
||||||
some(some(_)) {
|
|
||||||
/* self is a class with a dtor, which means we
|
|
||||||
have to select out the object itself
|
|
||||||
(If any other code does the same thing, that's
|
|
||||||
a bug */
|
|
||||||
GEPi(cx, cast_self(cx, s), [0u, 1u])
|
|
||||||
}
|
|
||||||
_ { cast_self(cx, s) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
none { cx.sess().bug("trans_local_var: reference to self \
|
none { cx.sess().bug("trans_local_var: reference to self \
|
||||||
out of context"); }
|
out of context"); }
|
||||||
};
|
};
|
||||||
|
@ -2535,9 +2523,13 @@ fn trans_rec_field(bcx: block, base: @ast::expr,
|
||||||
|
|
||||||
fn trans_rec_field_inner(bcx: block, val: ValueRef, ty: ty::t,
|
fn trans_rec_field_inner(bcx: block, val: ValueRef, ty: ty::t,
|
||||||
field: ast::ident, sp: span) -> lval_result {
|
field: ast::ident, sp: span) -> lval_result {
|
||||||
|
let mut deref = false;
|
||||||
let fields = alt ty::get(ty).struct {
|
let fields = alt ty::get(ty).struct {
|
||||||
ty::ty_rec(fs) { fs }
|
ty::ty_rec(fs) { fs }
|
||||||
ty::ty_class(did, substs) {
|
ty::ty_class(did, substs) {
|
||||||
|
if option::is_some(ty::ty_dtor(bcx.tcx(), did)) {
|
||||||
|
deref = true;
|
||||||
|
}
|
||||||
ty::class_items_as_fields(bcx.tcx(), did, substs)
|
ty::class_items_as_fields(bcx.tcx(), did, substs)
|
||||||
}
|
}
|
||||||
// Constraint?
|
// Constraint?
|
||||||
|
@ -2545,7 +2537,15 @@ fn trans_rec_field_inner(bcx: block, val: ValueRef, ty: ty::t,
|
||||||
base expr has non-record type"); }
|
base expr has non-record type"); }
|
||||||
};
|
};
|
||||||
let ix = field_idx_strict(bcx.tcx(), sp, field, fields);
|
let ix = field_idx_strict(bcx.tcx(), sp, field, fields);
|
||||||
let val = GEPi(bcx, val, [0u, ix]);
|
|
||||||
|
/* self is a class with a dtor, which means we
|
||||||
|
have to select out the object itself
|
||||||
|
(If any other code does the same thing, that's
|
||||||
|
a bug */
|
||||||
|
let val = if deref {
|
||||||
|
GEPi(bcx, GEPi(bcx, val, [0u, 1u]), [0u, ix])
|
||||||
|
}
|
||||||
|
else { GEPi(bcx, val, [0u, ix]) };
|
||||||
|
|
||||||
ret {bcx: bcx, val: val, kind: owned};
|
ret {bcx: bcx, val: val, kind: owned};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue