Skip to content

Commit 432e5e9

Browse files
committed
Allow dereferencing of single-variant, single-argument tag values
(Using the * operator.) This makes tags more useful as nominal 'newtype' types, since you no longer have to copy out their contents (or construct a cumbersome boilerplate alt) to access them. I could have gone with a scheme where you could dereference individual arguments of an n-ary variant with ._0, ._1, etc, but opted not to, since we plan to move to a system where all variants are unary (or, I guess, nullary).
1 parent 57e6340 commit 432e5e9

File tree

4 files changed

+141
-81
lines changed

4 files changed

+141
-81
lines changed

src/comp/middle/alias.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -549,18 +549,13 @@ fn expr_root(&ctx cx, @ast::expr ex, bool autoderef) ->
549549
case (ast::expr_unary(?op, ?base)) {
550550
if (op == ast::deref) {
551551
auto base_t = ty::expr_ty(*cx.tcx, base);
552+
auto mut = false;
552553
alt (ty::struct(*cx.tcx, base_t)) {
553-
case (ty::ty_box(?mt)) {
554-
vec::push(ds, rec(mut=mt.mut != ast::imm,
555-
kind=unbox,
556-
outer_t=base_t));
557-
}
558-
case (ty::ty_res(_, ?inner, _)) {
559-
vec::push(ds, rec(mut=false,
560-
kind=unbox,
561-
outer_t=base_t));
562-
}
554+
case (ty::ty_box(?mt)) { mut = mt.mut != ast::imm; }
555+
case (ty::ty_res(_, _, _)) {}
556+
case (ty::ty_tag(_, _)) {}
563557
}
558+
vec::push(ds, rec(mut=mut, kind=unbox, outer_t=base_t));
564559
ex = base;
565560
} else { break; }
566561
}

src/comp/middle/trans.rs

Lines changed: 85 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ type block_ctxt =
329329
tag block_parent { parent_none; parent_some(@block_ctxt); }
330330

331331
type result = rec(@block_ctxt bcx, ValueRef val);
332+
type result_t = rec(@block_ctxt bcx, ValueRef val, ty::t ty);
332333

333334
fn extend_path(@local_ctxt cx, &str name) -> @local_ctxt {
334335
ret @rec(path=cx.path + [name] with *cx);
@@ -3320,18 +3321,16 @@ fn trans_unary(&@block_ctxt cx, ast::unop op, &@ast::expr e,
33203321
auto e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, e);
33213322
alt (op) {
33223323
case (ast::not) {
3323-
sub =
3324-
autoderef(sub.bcx, sub.val,
3325-
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
3326-
ret rslt(sub.bcx, sub.bcx.build.Not(sub.val));
3324+
auto dr = autoderef(sub.bcx, sub.val,
3325+
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
3326+
ret rslt(dr.bcx, dr.bcx.build.Not(dr.val));
33273327
}
33283328
case (ast::neg) {
3329-
sub =
3330-
autoderef(sub.bcx, sub.val,
3331-
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
3329+
auto dr = autoderef(sub.bcx, sub.val,
3330+
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
33323331
if (ty::struct(cx.fcx.lcx.ccx.tcx, e_ty) == ty::ty_float) {
3333-
ret rslt(sub.bcx, sub.bcx.build.FNeg(sub.val));
3334-
} else { ret rslt(sub.bcx, sub.bcx.build.Neg(sub.val)); }
3332+
ret rslt(dr.bcx, dr.bcx.build.FNeg(dr.val));
3333+
} else { ret rslt(dr.bcx, sub.bcx.build.Neg(dr.val)); }
33353334
}
33363335
case (ast::box(_)) {
33373336
auto e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, e);
@@ -3380,7 +3379,6 @@ fn trans_compare(&@block_ctxt cx0, ast::binop op, &ty::t t0, ValueRef lhs0,
33803379
auto rhs_r = autoderef(cx, rhs0, t0);
33813380
auto rhs = rhs_r.val;
33823381
cx = rhs_r.bcx;
3383-
auto t = ty::type_autoderef(cx.fcx.lcx.ccx.tcx, t0);
33843382
// Determine the operation we need.
33853383
// FIXME: Use or-patterns when we have them.
33863384

@@ -3393,7 +3391,7 @@ fn trans_compare(&@block_ctxt cx0, ast::binop op, &ty::t t0, ValueRef lhs0,
33933391
case (ast::ge) { llop = C_u8(abi::cmp_glue_op_lt); }
33943392
case (ast::gt) { llop = C_u8(abi::cmp_glue_op_le); }
33953393
}
3396-
auto rs = compare(cx, lhs, rhs, t, llop);
3394+
auto rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
33973395

33983396
// Invert the result if necessary.
33993397
// FIXME: Use or-patterns when we have them.
@@ -4113,11 +4111,12 @@ fn trans_eager_binop(&@block_ctxt cx, ast::binop op, &ty::t intype,
41134111
}
41144112

41154113
fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
4116-
-> result {
4114+
-> result_t {
41174115
let ValueRef v1 = v;
41184116
let ty::t t1 = t;
4117+
auto ccx = cx.fcx.lcx.ccx;
41194118
while (true) {
4120-
alt (ty::struct(cx.fcx.lcx.ccx.tcx, t1)) {
4119+
alt (ty::struct(ccx.tcx, t1)) {
41214120
case (ty::ty_box(?mt)) {
41224121
// If we are working with an lval, we want to
41234122
// unconditionally load at the top of the loop
@@ -4132,24 +4131,41 @@ fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
41324131
// to cast this pointer, since statically-sized tag types have
41334132
// different types depending on whether they're behind a box
41344133
// or not.
4135-
4136-
if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, mt.ty)) {
4137-
auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, mt.ty);
4134+
if (!ty::type_has_dynamic_size(ccx.tcx, mt.ty)) {
4135+
auto llty = type_of(ccx, cx.sp, mt.ty);
41384136
v1 = cx.build.PointerCast(body, T_ptr(llty));
41394137
} else { v1 = body; }
4140-
4141-
// But if we aren't working with an lval, we get rid of
4142-
// a layer of indirection at the bottom of the loop so
4143-
// that it is gone when we return...
4144-
if (!is_lval) { v1 = load_if_immediate(cx, v1, t1); }
4138+
}
4139+
case (ty::ty_res(?did, ?inner, ?tps)) {
4140+
if (is_lval) { v1 = cx.build.Load(v1); }
4141+
t1 = ty::substitute_type_params(ccx.tcx, tps, inner);
4142+
v1 = cx.build.GEP(v1, [C_int(0), C_int(1)]);
4143+
}
4144+
case (ty::ty_tag(?did, ?tps)) {
4145+
auto variants = ty::tag_variants(ccx.tcx, did);
4146+
if (vec::len(variants) != 1u ||
4147+
vec::len(variants.(0).args) != 1u) {
4148+
break;
4149+
}
4150+
if (is_lval) { v1 = cx.build.Load(v1); }
4151+
t1 = ty::substitute_type_params
4152+
(ccx.tcx, tps, variants.(0).args.(0));
4153+
if (!ty::type_has_dynamic_size(ccx.tcx, t1)) {
4154+
v1 = cx.build.PointerCast
4155+
(v1, T_ptr(type_of(ccx, cx.sp, t1)));
4156+
}
41454157
}
41464158
case (_) { break; }
41474159
}
4160+
// But if we aren't working with an lval, we get rid of
4161+
// a layer of indirection at the bottom of the loop so
4162+
// that it is gone when we return...
4163+
if (!is_lval) { v1 = load_if_immediate(cx, v1, t1); }
41484164
}
4149-
ret rslt(cx, v1);
4165+
ret rec(bcx=cx, val=v1, ty=t1);
41504166
}
41514167

4152-
fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
4168+
fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result_t {
41534169
ret autoderef_lval(cx, v, t, false);
41544170
}
41554171

@@ -4160,15 +4176,14 @@ fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
41604176
alt (op) {
41614177
case (ast::and) {
41624178
// Lazy-eval and
4163-
4164-
auto lhs_res = trans_expr(cx, a);
4165-
lhs_res =
4166-
autoderef(lhs_res.bcx, lhs_res.val,
4179+
auto lhs_expr = trans_expr(cx, a);
4180+
auto lhs_res =
4181+
autoderef(lhs_expr.bcx, lhs_expr.val,
41674182
ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
41684183
auto rhs_cx = new_scope_block_ctxt(cx, "rhs");
4169-
auto rhs_res = trans_expr(rhs_cx, b);
4170-
rhs_res =
4171-
autoderef(rhs_res.bcx, rhs_res.val,
4184+
auto rhs_expr = trans_expr(rhs_cx, b);
4185+
auto rhs_res =
4186+
autoderef(rhs_expr.bcx, rhs_expr.val,
41724187
ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
41734188
auto lhs_false_cx = new_scope_block_ctxt(cx, "lhs false");
41744189
auto lhs_false_res = rslt(lhs_false_cx, C_bool(false));
@@ -4181,20 +4196,18 @@ fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
41814196
lhs_res.bcx.build.CondBr(lhs_res.val, rhs_cx.llbb,
41824197
lhs_false_cx.llbb);
41834198
ret join_results(cx, T_bool(),
4184-
[lhs_false_res, rec(bcx=rhs_bcx with rhs_res)]);
4199+
[lhs_false_res, rec(bcx=rhs_bcx,
4200+
val=rhs_res.val)]);
41854201
}
41864202
case (ast::or) {
41874203
// Lazy-eval or
4188-
4189-
auto lhs_res = trans_expr(cx, a);
4190-
lhs_res =
4191-
autoderef(lhs_res.bcx, lhs_res.val,
4192-
ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
4204+
auto lhs_expr = trans_expr(cx, a);
4205+
auto lhs_res = autoderef(lhs_expr.bcx, lhs_expr.val,
4206+
ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
41934207
auto rhs_cx = new_scope_block_ctxt(cx, "rhs");
4194-
auto rhs_res = trans_expr(rhs_cx, b);
4195-
rhs_res =
4196-
autoderef(rhs_res.bcx, rhs_res.val,
4197-
ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
4208+
auto rhs_expr = trans_expr(rhs_cx, b);
4209+
auto rhs_res = autoderef(rhs_expr.bcx, rhs_expr.val,
4210+
ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
41984211
auto lhs_true_cx = new_scope_block_ctxt(cx, "lhs true");
41994212
auto lhs_true_res = rslt(lhs_true_cx, C_bool(true));
42004213
// see the and case for an explanation
@@ -4203,19 +4216,19 @@ fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
42034216
lhs_res.bcx.build.CondBr(lhs_res.val, lhs_true_cx.llbb,
42044217
rhs_cx.llbb);
42054218
ret join_results(cx, T_bool(),
4206-
[lhs_true_res, rec(bcx=rhs_bcx with rhs_res)]);
4219+
[lhs_true_res, rec(bcx=rhs_bcx,
4220+
val=rhs_res.val)]);
42074221
}
42084222
case (_) {
42094223
// Remaining cases are eager:
42104224

4211-
auto lhs = trans_expr(cx, a);
4225+
auto lhs_expr = trans_expr(cx, a);
42124226
auto lhty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, a);
4213-
lhs = autoderef(lhs.bcx, lhs.val, lhty);
4214-
auto rhs = trans_expr(lhs.bcx, b);
4227+
auto lhs = autoderef(lhs_expr.bcx, lhs_expr.val, lhty);
4228+
auto rhs_expr = trans_expr(lhs.bcx, b);
42154229
auto rhty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, b);
4216-
rhs = autoderef(rhs.bcx, rhs.val, rhty);
4217-
ret trans_eager_binop(rhs.bcx, op,
4218-
ty::type_autoderef(cx.fcx.lcx.ccx.tcx,lhty),
4230+
auto rhs = autoderef(rhs_expr.bcx, rhs_expr.val, rhty);
4231+
ret trans_eager_binop(rhs.bcx, op, lhs.ty,
42194232
lhs.val, rhs.val);
42204233
}
42214234
}
@@ -4931,7 +4944,7 @@ fn trans_path(&@block_ctxt cx, &ast::path p, ast::node_id id) -> lval_result {
49314944
fn trans_field(&@block_ctxt cx, &span sp, ValueRef v, &ty::t t0,
49324945
&ast::ident field, ast::node_id id) -> lval_result {
49334946
auto r = autoderef(cx, v, t0);
4934-
auto t = ty::type_autoderef(cx.fcx.lcx.ccx.tcx, t0);
4947+
auto t = r.ty;
49354948
alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
49364949
case (ty::ty_tup(_)) {
49374950
let uint ix = ty::field_num(cx.fcx.lcx.ccx.sess, sp, field);
@@ -4971,11 +4984,11 @@ fn trans_index(&@block_ctxt cx, &span sp, &@ast::expr base, &@ast::expr idx,
49714984
// Is this an interior vector?
49724985

49734986
auto base_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, base);
4974-
auto base_ty_no_boxes = ty::strip_boxes(cx.fcx.lcx.ccx.tcx, base_ty);
4987+
auto exp = trans_expr(cx, base);
4988+
auto lv = autoderef(exp.bcx, exp.val, base_ty);
4989+
auto base_ty_no_boxes = lv.ty;
49754990
auto is_interior =
49764991
ty::sequence_is_interior(cx.fcx.lcx.ccx.tcx, base_ty_no_boxes);
4977-
auto lv = trans_expr(cx, base);
4978-
lv = autoderef(lv.bcx, lv.val, base_ty);
49794992
auto ix = trans_expr(lv.bcx, idx);
49804993
auto v = lv.val;
49814994
auto bcx = ix.bcx;
@@ -5056,14 +5069,29 @@ fn trans_lval(&@block_ctxt cx, &@ast::expr e) -> lval_result {
50565069
ret trans_index(cx, e.span, base, idx, e.id);
50575070
}
50585071
case (ast::expr_unary(?unop, ?base)) {
5072+
auto ccx = cx.fcx.lcx.ccx;
50595073
assert (unop == ast::deref);
50605074
auto sub = trans_expr(cx, base);
5061-
auto t = ty::expr_ty(cx.fcx.lcx.ccx.tcx, base);
5062-
auto offset = alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
5063-
case (ty::ty_box(_)) { abi::box_rc_field_body }
5064-
case (ty::ty_res(_, _, _)) { 1 }
5075+
auto t = ty::expr_ty(ccx.tcx, base);
5076+
auto val = alt (ty::struct(ccx.tcx, t)) {
5077+
case (ty::ty_box(_)) {
5078+
sub.bcx.build.GEP
5079+
(sub.val, [C_int(0), C_int(abi::box_rc_field_body)])
5080+
}
5081+
case (ty::ty_res(_, _, _)) {
5082+
sub.bcx.build.GEP(sub.val, [C_int(0), C_int(1)])
5083+
}
5084+
case (ty::ty_tag(_, _)) {
5085+
auto ety = ty::expr_ty(ccx.tcx, e);
5086+
auto ellty;
5087+
if (ty::type_has_dynamic_size(ccx.tcx, ety)) {
5088+
ellty = T_typaram_ptr(ccx.tn);
5089+
} else {
5090+
ellty = T_ptr(type_of(ccx, e.span, ety));
5091+
};
5092+
sub.bcx.build.PointerCast(sub.val, ellty)
5093+
}
50655094
};
5066-
auto val = sub.bcx.build.GEP(sub.val, [C_int(0), C_int(offset)]);
50675095
ret lval_mem(sub.bcx, val);
50685096
}
50695097
case (ast::expr_self_method(?ident)) {
@@ -5692,7 +5720,7 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody,
56925720
// It's a closure. We have to autoderef.
56935721
auto res = autoderef_lval(bcx, f_res.res.val, fn_ty, true);
56945722
bcx = res.bcx;
5695-
fn_ty = ty::type_autoderef(bcx.fcx.lcx.ccx.tcx, fn_ty);
5723+
fn_ty = res.ty;
56965724

56975725
auto pair = res.val;
56985726
faddr =

src/comp/middle/ty.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ export sequence_is_interior;
111111
export struct;
112112
export sort_methods;
113113
export stmt_node_id;
114-
export strip_boxes;
115114
export sty;
116115
export substitute_type_params;
117116
export t;
@@ -1287,6 +1286,17 @@ fn type_autoderef(&ctxt cx, &ty::t t) -> ty::t {
12871286
while (true) {
12881287
alt (struct(cx, t1)) {
12891288
case (ty::ty_box(?mt)) { t1 = mt.ty; }
1289+
case (ty::ty_res(_, ?inner, ?tps)) {
1290+
t1 = substitute_type_params(cx, tps, inner);
1291+
}
1292+
case (ty::ty_tag(?did, ?tps)) {
1293+
auto variants = tag_variants(cx, did);
1294+
if (vec::len(variants) != 1u ||
1295+
vec::len(variants.(0).args) != 1u) {
1296+
break;
1297+
}
1298+
t1 = substitute_type_params(cx, tps, variants.(0).args.(0));
1299+
}
12901300
case (_) { break; }
12911301
}
12921302
}
@@ -2891,7 +2901,7 @@ fn ret_ty_of_fn(ctxt cx, ast::node_id id) -> t {
28912901

28922902

28932903
// NB: This function requires that the given type has no variables. So, inside
2894-
// typeck, you should use typeck::strip_boxes() instead.
2904+
// typeck, you should use typeck::do_autoderef() instead.
28952905
fn strip_boxes(&ctxt cx, &ty::t t) -> ty::t {
28962906
auto t1 = t;
28972907
while (true) {

0 commit comments

Comments
 (0)