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).
This commit is contained in:
parent
57e6340253
commit
432e5e9f7f
@ -549,18 +549,13 @@ fn expr_root(&ctx cx, @ast::expr ex, bool autoderef) ->
|
||||
case (ast::expr_unary(?op, ?base)) {
|
||||
if (op == ast::deref) {
|
||||
auto base_t = ty::expr_ty(*cx.tcx, base);
|
||||
auto mut = false;
|
||||
alt (ty::struct(*cx.tcx, base_t)) {
|
||||
case (ty::ty_box(?mt)) {
|
||||
vec::push(ds, rec(mut=mt.mut != ast::imm,
|
||||
kind=unbox,
|
||||
outer_t=base_t));
|
||||
}
|
||||
case (ty::ty_res(_, ?inner, _)) {
|
||||
vec::push(ds, rec(mut=false,
|
||||
kind=unbox,
|
||||
outer_t=base_t));
|
||||
}
|
||||
case (ty::ty_box(?mt)) { mut = mt.mut != ast::imm; }
|
||||
case (ty::ty_res(_, _, _)) {}
|
||||
case (ty::ty_tag(_, _)) {}
|
||||
}
|
||||
vec::push(ds, rec(mut=mut, kind=unbox, outer_t=base_t));
|
||||
ex = base;
|
||||
} else { break; }
|
||||
}
|
||||
|
@ -329,6 +329,7 @@ type block_ctxt =
|
||||
tag block_parent { parent_none; parent_some(@block_ctxt); }
|
||||
|
||||
type result = rec(@block_ctxt bcx, ValueRef val);
|
||||
type result_t = rec(@block_ctxt bcx, ValueRef val, ty::t ty);
|
||||
|
||||
fn extend_path(@local_ctxt cx, &str name) -> @local_ctxt {
|
||||
ret @rec(path=cx.path + [name] with *cx);
|
||||
@ -3320,18 +3321,16 @@ fn trans_unary(&@block_ctxt cx, ast::unop op, &@ast::expr e,
|
||||
auto e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, e);
|
||||
alt (op) {
|
||||
case (ast::not) {
|
||||
sub =
|
||||
autoderef(sub.bcx, sub.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
|
||||
ret rslt(sub.bcx, sub.bcx.build.Not(sub.val));
|
||||
auto dr = autoderef(sub.bcx, sub.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
|
||||
ret rslt(dr.bcx, dr.bcx.build.Not(dr.val));
|
||||
}
|
||||
case (ast::neg) {
|
||||
sub =
|
||||
autoderef(sub.bcx, sub.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
|
||||
auto dr = autoderef(sub.bcx, sub.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, e));
|
||||
if (ty::struct(cx.fcx.lcx.ccx.tcx, e_ty) == ty::ty_float) {
|
||||
ret rslt(sub.bcx, sub.bcx.build.FNeg(sub.val));
|
||||
} else { ret rslt(sub.bcx, sub.bcx.build.Neg(sub.val)); }
|
||||
ret rslt(dr.bcx, dr.bcx.build.FNeg(dr.val));
|
||||
} else { ret rslt(dr.bcx, sub.bcx.build.Neg(dr.val)); }
|
||||
}
|
||||
case (ast::box(_)) {
|
||||
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,
|
||||
auto rhs_r = autoderef(cx, rhs0, t0);
|
||||
auto rhs = rhs_r.val;
|
||||
cx = rhs_r.bcx;
|
||||
auto t = ty::type_autoderef(cx.fcx.lcx.ccx.tcx, t0);
|
||||
// Determine the operation we need.
|
||||
// FIXME: Use or-patterns when we have them.
|
||||
|
||||
@ -3393,7 +3391,7 @@ fn trans_compare(&@block_ctxt cx0, ast::binop op, &ty::t t0, ValueRef lhs0,
|
||||
case (ast::ge) { llop = C_u8(abi::cmp_glue_op_lt); }
|
||||
case (ast::gt) { llop = C_u8(abi::cmp_glue_op_le); }
|
||||
}
|
||||
auto rs = compare(cx, lhs, rhs, t, llop);
|
||||
auto rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
|
||||
|
||||
// Invert the result if necessary.
|
||||
// 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,
|
||||
}
|
||||
|
||||
fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
|
||||
-> result {
|
||||
-> result_t {
|
||||
let ValueRef v1 = v;
|
||||
let ty::t t1 = t;
|
||||
auto ccx = cx.fcx.lcx.ccx;
|
||||
while (true) {
|
||||
alt (ty::struct(cx.fcx.lcx.ccx.tcx, t1)) {
|
||||
alt (ty::struct(ccx.tcx, t1)) {
|
||||
case (ty::ty_box(?mt)) {
|
||||
// If we are working with an lval, we want to
|
||||
// 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)
|
||||
// to cast this pointer, since statically-sized tag types have
|
||||
// different types depending on whether they're behind a box
|
||||
// or not.
|
||||
|
||||
if (!ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, mt.ty)) {
|
||||
auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, mt.ty);
|
||||
if (!ty::type_has_dynamic_size(ccx.tcx, mt.ty)) {
|
||||
auto llty = type_of(ccx, cx.sp, mt.ty);
|
||||
v1 = cx.build.PointerCast(body, T_ptr(llty));
|
||||
} else { v1 = body; }
|
||||
|
||||
// But if we aren't working with an lval, we get rid of
|
||||
// a layer of indirection at the bottom of the loop so
|
||||
// that it is gone when we return...
|
||||
if (!is_lval) { v1 = load_if_immediate(cx, v1, t1); }
|
||||
}
|
||||
case (ty::ty_res(?did, ?inner, ?tps)) {
|
||||
if (is_lval) { v1 = cx.build.Load(v1); }
|
||||
t1 = ty::substitute_type_params(ccx.tcx, tps, inner);
|
||||
v1 = cx.build.GEP(v1, [C_int(0), C_int(1)]);
|
||||
}
|
||||
case (ty::ty_tag(?did, ?tps)) {
|
||||
auto variants = ty::tag_variants(ccx.tcx, did);
|
||||
if (vec::len(variants) != 1u ||
|
||||
vec::len(variants.(0).args) != 1u) {
|
||||
break;
|
||||
}
|
||||
if (is_lval) { v1 = cx.build.Load(v1); }
|
||||
t1 = ty::substitute_type_params
|
||||
(ccx.tcx, tps, variants.(0).args.(0));
|
||||
if (!ty::type_has_dynamic_size(ccx.tcx, t1)) {
|
||||
v1 = cx.build.PointerCast
|
||||
(v1, T_ptr(type_of(ccx, cx.sp, t1)));
|
||||
}
|
||||
}
|
||||
case (_) { break; }
|
||||
}
|
||||
// But if we aren't working with an lval, we get rid of
|
||||
// a layer of indirection at the bottom of the loop so
|
||||
// that it is gone when we return...
|
||||
if (!is_lval) { v1 = load_if_immediate(cx, v1, t1); }
|
||||
}
|
||||
ret rslt(cx, v1);
|
||||
ret rec(bcx=cx, val=v1, ty=t1);
|
||||
}
|
||||
|
||||
fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
|
||||
fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result_t {
|
||||
ret autoderef_lval(cx, v, t, false);
|
||||
}
|
||||
|
||||
@ -4160,15 +4176,14 @@ fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
|
||||
alt (op) {
|
||||
case (ast::and) {
|
||||
// Lazy-eval and
|
||||
|
||||
auto lhs_res = trans_expr(cx, a);
|
||||
lhs_res =
|
||||
autoderef(lhs_res.bcx, lhs_res.val,
|
||||
auto lhs_expr = trans_expr(cx, a);
|
||||
auto lhs_res =
|
||||
autoderef(lhs_expr.bcx, lhs_expr.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
|
||||
auto rhs_cx = new_scope_block_ctxt(cx, "rhs");
|
||||
auto rhs_res = trans_expr(rhs_cx, b);
|
||||
rhs_res =
|
||||
autoderef(rhs_res.bcx, rhs_res.val,
|
||||
auto rhs_expr = trans_expr(rhs_cx, b);
|
||||
auto rhs_res =
|
||||
autoderef(rhs_expr.bcx, rhs_expr.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
|
||||
auto lhs_false_cx = new_scope_block_ctxt(cx, "lhs false");
|
||||
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)
|
||||
lhs_res.bcx.build.CondBr(lhs_res.val, rhs_cx.llbb,
|
||||
lhs_false_cx.llbb);
|
||||
ret join_results(cx, T_bool(),
|
||||
[lhs_false_res, rec(bcx=rhs_bcx with rhs_res)]);
|
||||
[lhs_false_res, rec(bcx=rhs_bcx,
|
||||
val=rhs_res.val)]);
|
||||
}
|
||||
case (ast::or) {
|
||||
// Lazy-eval or
|
||||
|
||||
auto lhs_res = trans_expr(cx, a);
|
||||
lhs_res =
|
||||
autoderef(lhs_res.bcx, lhs_res.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
|
||||
auto lhs_expr = trans_expr(cx, a);
|
||||
auto lhs_res = autoderef(lhs_expr.bcx, lhs_expr.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, a));
|
||||
auto rhs_cx = new_scope_block_ctxt(cx, "rhs");
|
||||
auto rhs_res = trans_expr(rhs_cx, b);
|
||||
rhs_res =
|
||||
autoderef(rhs_res.bcx, rhs_res.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
|
||||
auto rhs_expr = trans_expr(rhs_cx, b);
|
||||
auto rhs_res = autoderef(rhs_expr.bcx, rhs_expr.val,
|
||||
ty::expr_ty(cx.fcx.lcx.ccx.tcx, b));
|
||||
auto lhs_true_cx = new_scope_block_ctxt(cx, "lhs true");
|
||||
auto lhs_true_res = rslt(lhs_true_cx, C_bool(true));
|
||||
// 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)
|
||||
lhs_res.bcx.build.CondBr(lhs_res.val, lhs_true_cx.llbb,
|
||||
rhs_cx.llbb);
|
||||
ret join_results(cx, T_bool(),
|
||||
[lhs_true_res, rec(bcx=rhs_bcx with rhs_res)]);
|
||||
[lhs_true_res, rec(bcx=rhs_bcx,
|
||||
val=rhs_res.val)]);
|
||||
}
|
||||
case (_) {
|
||||
// Remaining cases are eager:
|
||||
|
||||
auto lhs = trans_expr(cx, a);
|
||||
auto lhs_expr = trans_expr(cx, a);
|
||||
auto lhty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, a);
|
||||
lhs = autoderef(lhs.bcx, lhs.val, lhty);
|
||||
auto rhs = trans_expr(lhs.bcx, b);
|
||||
auto lhs = autoderef(lhs_expr.bcx, lhs_expr.val, lhty);
|
||||
auto rhs_expr = trans_expr(lhs.bcx, b);
|
||||
auto rhty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, b);
|
||||
rhs = autoderef(rhs.bcx, rhs.val, rhty);
|
||||
ret trans_eager_binop(rhs.bcx, op,
|
||||
ty::type_autoderef(cx.fcx.lcx.ccx.tcx,lhty),
|
||||
auto rhs = autoderef(rhs_expr.bcx, rhs_expr.val, rhty);
|
||||
ret trans_eager_binop(rhs.bcx, op, lhs.ty,
|
||||
lhs.val, rhs.val);
|
||||
}
|
||||
}
|
||||
@ -4931,7 +4944,7 @@ fn trans_path(&@block_ctxt cx, &ast::path p, ast::node_id id) -> lval_result {
|
||||
fn trans_field(&@block_ctxt cx, &span sp, ValueRef v, &ty::t t0,
|
||||
&ast::ident field, ast::node_id id) -> lval_result {
|
||||
auto r = autoderef(cx, v, t0);
|
||||
auto t = ty::type_autoderef(cx.fcx.lcx.ccx.tcx, t0);
|
||||
auto t = r.ty;
|
||||
alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
|
||||
case (ty::ty_tup(_)) {
|
||||
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,
|
||||
// Is this an interior vector?
|
||||
|
||||
auto base_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, base);
|
||||
auto base_ty_no_boxes = ty::strip_boxes(cx.fcx.lcx.ccx.tcx, base_ty);
|
||||
auto exp = trans_expr(cx, base);
|
||||
auto lv = autoderef(exp.bcx, exp.val, base_ty);
|
||||
auto base_ty_no_boxes = lv.ty;
|
||||
auto is_interior =
|
||||
ty::sequence_is_interior(cx.fcx.lcx.ccx.tcx, base_ty_no_boxes);
|
||||
auto lv = trans_expr(cx, base);
|
||||
lv = autoderef(lv.bcx, lv.val, base_ty);
|
||||
auto ix = trans_expr(lv.bcx, idx);
|
||||
auto v = lv.val;
|
||||
auto bcx = ix.bcx;
|
||||
@ -5056,14 +5069,29 @@ fn trans_lval(&@block_ctxt cx, &@ast::expr e) -> lval_result {
|
||||
ret trans_index(cx, e.span, base, idx, e.id);
|
||||
}
|
||||
case (ast::expr_unary(?unop, ?base)) {
|
||||
auto ccx = cx.fcx.lcx.ccx;
|
||||
assert (unop == ast::deref);
|
||||
auto sub = trans_expr(cx, base);
|
||||
auto t = ty::expr_ty(cx.fcx.lcx.ccx.tcx, base);
|
||||
auto offset = alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
|
||||
case (ty::ty_box(_)) { abi::box_rc_field_body }
|
||||
case (ty::ty_res(_, _, _)) { 1 }
|
||||
auto t = ty::expr_ty(ccx.tcx, base);
|
||||
auto val = alt (ty::struct(ccx.tcx, t)) {
|
||||
case (ty::ty_box(_)) {
|
||||
sub.bcx.build.GEP
|
||||
(sub.val, [C_int(0), C_int(abi::box_rc_field_body)])
|
||||
}
|
||||
case (ty::ty_res(_, _, _)) {
|
||||
sub.bcx.build.GEP(sub.val, [C_int(0), C_int(1)])
|
||||
}
|
||||
case (ty::ty_tag(_, _)) {
|
||||
auto ety = ty::expr_ty(ccx.tcx, e);
|
||||
auto ellty;
|
||||
if (ty::type_has_dynamic_size(ccx.tcx, ety)) {
|
||||
ellty = T_typaram_ptr(ccx.tn);
|
||||
} else {
|
||||
ellty = T_ptr(type_of(ccx, e.span, ety));
|
||||
};
|
||||
sub.bcx.build.PointerCast(sub.val, ellty)
|
||||
}
|
||||
};
|
||||
auto val = sub.bcx.build.GEP(sub.val, [C_int(0), C_int(offset)]);
|
||||
ret lval_mem(sub.bcx, val);
|
||||
}
|
||||
case (ast::expr_self_method(?ident)) {
|
||||
@ -5692,7 +5720,7 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody,
|
||||
// It's a closure. We have to autoderef.
|
||||
auto res = autoderef_lval(bcx, f_res.res.val, fn_ty, true);
|
||||
bcx = res.bcx;
|
||||
fn_ty = ty::type_autoderef(bcx.fcx.lcx.ccx.tcx, fn_ty);
|
||||
fn_ty = res.ty;
|
||||
|
||||
auto pair = res.val;
|
||||
faddr =
|
||||
|
@ -111,7 +111,6 @@ export sequence_is_interior;
|
||||
export struct;
|
||||
export sort_methods;
|
||||
export stmt_node_id;
|
||||
export strip_boxes;
|
||||
export sty;
|
||||
export substitute_type_params;
|
||||
export t;
|
||||
@ -1287,6 +1286,17 @@ fn type_autoderef(&ctxt cx, &ty::t t) -> ty::t {
|
||||
while (true) {
|
||||
alt (struct(cx, t1)) {
|
||||
case (ty::ty_box(?mt)) { t1 = mt.ty; }
|
||||
case (ty::ty_res(_, ?inner, ?tps)) {
|
||||
t1 = substitute_type_params(cx, tps, inner);
|
||||
}
|
||||
case (ty::ty_tag(?did, ?tps)) {
|
||||
auto variants = tag_variants(cx, did);
|
||||
if (vec::len(variants) != 1u ||
|
||||
vec::len(variants.(0).args) != 1u) {
|
||||
break;
|
||||
}
|
||||
t1 = substitute_type_params(cx, tps, variants.(0).args.(0));
|
||||
}
|
||||
case (_) { break; }
|
||||
}
|
||||
}
|
||||
@ -2891,7 +2901,7 @@ fn ret_ty_of_fn(ctxt cx, ast::node_id id) -> t {
|
||||
|
||||
|
||||
// NB: This function requires that the given type has no variables. So, inside
|
||||
// typeck, you should use typeck::strip_boxes() instead.
|
||||
// typeck, you should use typeck::do_autoderef() instead.
|
||||
fn strip_boxes(&ctxt cx, &ty::t t) -> ty::t {
|
||||
auto t1 = t;
|
||||
while (true) {
|
||||
|
@ -819,11 +819,25 @@ mod unify {
|
||||
|
||||
tag autoderef_kind { AUTODEREF_OK; NO_AUTODEREF; }
|
||||
|
||||
fn strip_boxes(&@fn_ctxt fcx, &span sp, &ty::t t) -> ty::t {
|
||||
// FIXME This is almost a duplicate of ty::type_autoderef, with structure_of
|
||||
// instead of ty::struct.
|
||||
fn do_autoderef(&@fn_ctxt fcx, &span sp, &ty::t t) -> ty::t {
|
||||
auto t1 = t;
|
||||
while (true) {
|
||||
alt (structure_of(fcx, sp, t1)) {
|
||||
case (ty::ty_box(?inner)) { t1 = inner.ty; }
|
||||
case (ty::ty_res(_, ?inner, ?tps)) {
|
||||
t1 = ty::substitute_type_params(fcx.ccx.tcx, tps, inner);
|
||||
}
|
||||
case (ty::ty_tag(?did, ?tps)) {
|
||||
auto variants = ty::tag_variants(fcx.ccx.tcx, did);
|
||||
if (vec::len(variants) != 1u ||
|
||||
vec::len(variants.(0).args) != 1u) {
|
||||
ret t1;
|
||||
}
|
||||
t1 = ty::substitute_type_params(fcx.ccx.tcx, tps,
|
||||
variants.(0).args.(0));
|
||||
}
|
||||
case (_) { ret t1; }
|
||||
}
|
||||
}
|
||||
@ -881,8 +895,8 @@ mod demand {
|
||||
auto actual_1 = actual;
|
||||
auto implicit_boxes = 0u;
|
||||
if (adk == AUTODEREF_OK) {
|
||||
expected_1 = strip_boxes(fcx, sp, expected_1);
|
||||
actual_1 = strip_boxes(fcx, sp, actual_1);
|
||||
expected_1 = do_autoderef(fcx, sp, expected_1);
|
||||
actual_1 = do_autoderef(fcx, sp, actual_1);
|
||||
implicit_boxes = count_boxes(fcx, sp, actual);
|
||||
}
|
||||
let vec[mutable ty::t] ty_param_substs = [mutable ];
|
||||
@ -1346,7 +1360,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
||||
|
||||
// We want to autoderef calls but not binds
|
||||
auto fty_stripped =
|
||||
if (is_call) { strip_boxes(fcx, sp, fty) } else { fty };
|
||||
if (is_call) { do_autoderef(fcx, sp, fty) } else { fty };
|
||||
|
||||
// Grab the argument types and the return type.
|
||||
auto arg_tys;
|
||||
@ -1534,7 +1548,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
||||
case (ast::ne) { ty::mk_bool(fcx.ccx.tcx) }
|
||||
case (ast::ge) { ty::mk_bool(fcx.ccx.tcx) }
|
||||
case (ast::gt) { ty::mk_bool(fcx.ccx.tcx) }
|
||||
case (_) { strip_boxes(fcx, expr.span, lhs_t) }
|
||||
case (_) { do_autoderef(fcx, expr.span, lhs_t) }
|
||||
};
|
||||
write::ty_only_fixup(fcx, id, t);
|
||||
}
|
||||
@ -1549,10 +1563,23 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
||||
alt (structure_of(fcx, expr.span, oper_t)) {
|
||||
case (ty::ty_box(?inner)) { oper_t = inner.ty; }
|
||||
case (ty::ty_res(_, ?inner, _)) { oper_t = inner; }
|
||||
case (ty::ty_tag(?id, ?tps)) {
|
||||
auto variants = ty::tag_variants(fcx.ccx.tcx, id);
|
||||
if (vec::len(variants) != 1u ||
|
||||
vec::len(variants.(0).args) != 1u) {
|
||||
fcx.ccx.tcx.sess.span_fatal
|
||||
(expr.span, "can only dereference tags " +
|
||||
"with a single variant which has a " +
|
||||
"single argument");
|
||||
}
|
||||
oper_t = ty::substitute_type_params
|
||||
(fcx.ccx.tcx, tps, variants.(0).args.(0));
|
||||
}
|
||||
case (_) {
|
||||
auto s = "dereferencing non-box type: " +
|
||||
ty_to_str(fcx.ccx.tcx, oper_t);
|
||||
fcx.ccx.tcx.sess.span_fatal(expr.span, s);
|
||||
fcx.ccx.tcx.sess.span_fatal
|
||||
(expr.span, "dereferencing non-" +
|
||||
"dereferenceable type: " +
|
||||
ty_to_str(fcx.ccx.tcx, oper_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1568,7 +1595,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
||||
oper_t)));
|
||||
}
|
||||
}
|
||||
case (_) { oper_t = strip_boxes(fcx, expr.span, oper_t); }
|
||||
case (_) { oper_t = do_autoderef(fcx, expr.span, oper_t); }
|
||||
}
|
||||
write::ty_only_fixup(fcx, id, oper_t);
|
||||
}
|
||||
@ -1859,7 +1886,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
||||
// Pull the return type out of the type of the function.
|
||||
|
||||
auto rt_1;
|
||||
auto fty = strip_boxes(fcx, expr.span,
|
||||
auto fty = do_autoderef(fcx, expr.span,
|
||||
ty::expr_ty(fcx.ccx.tcx, f));
|
||||
alt (structure_of(fcx, expr.span, fty)) {
|
||||
case (ty::ty_fn(_, _, ?rt, _, _)) { rt_1 = rt; }
|
||||
@ -2017,7 +2044,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
||||
case (ast::expr_field(?base, ?field)) {
|
||||
check_expr(fcx, base);
|
||||
auto base_t = expr_ty(fcx.ccx.tcx, base);
|
||||
base_t = strip_boxes(fcx, expr.span, base_t);
|
||||
base_t = do_autoderef(fcx, expr.span, base_t);
|
||||
alt (structure_of(fcx, expr.span, base_t)) {
|
||||
case (ty::ty_tup(?args)) {
|
||||
let uint ix =
|
||||
@ -2063,7 +2090,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
|
||||
case (ast::expr_index(?base, ?idx)) {
|
||||
check_expr(fcx, base);
|
||||
auto base_t = expr_ty(fcx.ccx.tcx, base);
|
||||
base_t = strip_boxes(fcx, expr.span, base_t);
|
||||
base_t = do_autoderef(fcx, expr.span, base_t);
|
||||
check_expr(fcx, idx);
|
||||
auto idx_t = expr_ty(fcx.ccx.tcx, idx);
|
||||
if (!type_is_integral(fcx, idx.span, idx_t)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user