rustc: Alias fix part 1 -- Separate out AST modes from typechecker modes, and introduce an "either value or alias" mode

This commit is contained in:
Patrick Walton 2011-05-09 12:27:03 -07:00
parent bc879a4e1e
commit 662e949540
6 changed files with 63 additions and 71 deletions

View File

@ -249,9 +249,9 @@ fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty.arg], ty.t) {
assert (next(st) as char == '[');
let vec[ty.arg] inputs = vec();
while (peek(st) as char != ']') {
auto mode = ast.val;
auto mode = ty.mo_val;
if (peek(st) as char == '&') {
mode = ast.alias;
mode = ty.mo_alias;
st.pos = st.pos + 1u;
}
inputs += vec(rec(mode=mode, ty=parse_ty(st, sd)));

View File

@ -241,7 +241,7 @@ mod Encode {
fn enc_ty_fn(IO.writer w, @ctxt cx, vec[ty.arg] args, ty.t out) {
w.write_char('[');
for (ty.arg arg in args) {
if (arg.mode == ast.alias) { w.write_char('&'); }
if (arg.mode == ty.mo_alias) { w.write_char('&'); }
enc_ty(w, cx, arg.ty);
}
w.write_char(']');

View File

@ -605,12 +605,12 @@ fn type_of_explicit_args(@crate_ctxt cx, vec[ty.arg] inputs) -> vec[TypeRef] {
let vec[TypeRef] atys = vec();
for (ty.arg arg in inputs) {
if (ty.type_has_dynamic_size(cx.tcx, arg.ty)) {
assert (arg.mode == ast.alias);
assert (arg.mode == ty.mo_alias);
atys += vec(T_typaram_ptr(cx.tn));
} else {
let TypeRef t;
alt (arg.mode) {
case (ast.alias) {
case (ty.mo_alias) {
t = T_ptr(type_of_inner(cx, arg.ty));
}
case (_) {
@ -675,7 +675,8 @@ fn type_of_fn_full(@crate_ctxt cx,
atys +=
vec(T_fn_pair(cx.tn,
type_of_fn_full(cx, ast.proto_fn, none[TypeRef],
vec(rec(mode=ast.alias, ty=output)),
vec(rec(mode=ty.mo_alias,
ty=output)),
ty.mk_nil(cx.tcx), 0u)));
}
@ -829,7 +830,7 @@ fn type_of_inner(@crate_ctxt cx, ty.t t) -> TypeRef {
fn type_of_arg(@local_ctxt cx, &ty.arg arg) -> TypeRef {
alt (ty.struct(cx.ccx.tcx, arg.ty)) {
case (ty.ty_param(_)) {
if (arg.mode == ast.alias) {
if (arg.mode == ty.mo_alias) {
ret T_typaram_ptr(cx.ccx.tn);
}
}
@ -839,7 +840,7 @@ fn type_of_arg(@local_ctxt cx, &ty.arg arg) -> TypeRef {
}
auto typ;
if (arg.mode == ast.alias) {
if (arg.mode == ty.mo_alias) {
typ = T_ptr(type_of_inner(cx.ccx, arg.ty));
} else {
typ = type_of_inner(cx.ccx, arg.ty);
@ -3712,7 +3713,7 @@ fn trans_for_each(@block_ctxt cx,
auto iter_body_llty =
type_of_fn_full(lcx.ccx, ast.proto_fn,
none[TypeRef],
vec(rec(mode=ast.alias, ty=decl_ty)),
vec(rec(mode=ty.mo_alias, ty=decl_ty)),
ty.mk_nil(lcx.ccx.tcx), 0u);
let ValueRef lliterbody = decl_internal_fastcall_fn(lcx.ccx.llmod,
@ -4482,7 +4483,7 @@ fn trans_bind_thunk(@local_ctxt cx,
bcx = bound_arg.bcx;
auto val = bound_arg.val;
if (out_arg.mode == ast.val) {
if (out_arg.mode == ty.mo_val) {
if (type_is_immediate(cx.ccx, e_ty)) {
val = bcx.build.Load(val);
bcx = take_ty(bcx, val, e_ty).bcx;
@ -4492,7 +4493,7 @@ fn trans_bind_thunk(@local_ctxt cx,
}
} else if (ty.type_contains_params(cx.ccx.tcx,
out_arg.ty)) {
assert (out_arg.mode == ast.alias);
assert (out_arg.mode == ty.mo_alias);
val = bcx.build.PointerCast(val, llout_arg_ty);
}
@ -4505,7 +4506,7 @@ fn trans_bind_thunk(@local_ctxt cx,
let ValueRef passed_arg = llvm.LLVMGetParam(llthunk, a);
if (ty.type_contains_params(cx.ccx.tcx, out_arg.ty)) {
assert (out_arg.mode == ast.alias);
assert (out_arg.mode == ty.mo_alias);
passed_arg = bcx.build.PointerCast(passed_arg,
llout_arg_ty);
}
@ -4745,7 +4746,7 @@ fn trans_arg_expr(@block_ctxt cx,
auto re = trans_expr(bcx, e);
val = re.val;
bcx = re.bcx;
} else if (arg.mode == ast.alias) {
} else if (arg.mode == ty.mo_alias) {
let lval_result lv;
if (ty.is_lval(e)) {
lv = trans_lval(bcx, e);
@ -4772,13 +4773,13 @@ fn trans_arg_expr(@block_ctxt cx,
bcx = re.bcx;
}
if (arg.mode != ast.alias) {
if (arg.mode != ty.mo_alias) {
bcx = take_ty(bcx, val, e_ty).bcx;
}
if (ty.type_contains_params(cx.fcx.lcx.ccx.tcx, arg.ty)) {
auto lldestty = lldestty0;
if (arg.mode == ast.val) {
if (arg.mode == ty.mo_val) {
// FIXME: we'd prefer to use &&, but rustboot doesn't like it
if (ty.type_is_structural(cx.fcx.lcx.ccx.tcx, e_ty)) {
lldestty = T_ptr(lldestty);
@ -4787,7 +4788,7 @@ fn trans_arg_expr(@block_ctxt cx,
val = bcx.build.PointerCast(val, lldestty);
}
if (arg.mode == ast.val) {
if (arg.mode == ty.mo_val) {
// FIXME: we'd prefer to use &&, but rustboot doesn't like it
if (ty.type_is_structural(cx.fcx.lcx.ccx.tcx, e_ty)) {
// Until here we've been treating structures by pointer;
@ -5496,7 +5497,7 @@ fn trans_put(@block_ctxt cx, &Option.t[@ast.expr] e) -> result {
case (none[@ast.expr]) { }
case (some[@ast.expr](?x)) {
auto e_ty = ty.expr_ty(cx.fcx.lcx.ccx.tcx, x);
auto arg = rec(mode=ast.alias, ty=e_ty);
auto arg = rec(mode=ty.mo_alias, ty=e_ty);
auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, vec(arg));
auto r = trans_arg_expr(bcx, arg, arg_tys.(0), x);
bcx = r.bcx;
@ -6362,10 +6363,7 @@ fn trans_obj(@local_ctxt cx, &ast._obj ob, ast.def_id oid,
// Translate obj ctor args to function arguments.
let vec[ast.arg] fn_args = vec();
for (ast.obj_field f in ob.fields) {
fn_args += vec(rec(mode=ast.alias,
ty=f.ty,
ident=f.ident,
id=f.id));
fn_args += vec(rec(mode=ast.alias, ty=f.ty, ident=f.ident, id=f.id));
}
auto fcx = new_fn_ctxt(cx, llctor_decl);
@ -6814,8 +6812,8 @@ fn decl_native_fn_and_pair(@crate_ctxt ccx,
fn convert_arg_to_i32(@block_ctxt cx,
ValueRef v,
ty.t t,
ast.mode mode) -> ValueRef {
if (mode == ast.val) {
ty.mode mode) -> ValueRef {
if (mode == ty.mo_val) {
if (ty.type_is_integral(cx.fcx.lcx.ccx.tcx, t)) {
auto lldsttype = T_int();
auto llsrctype = type_of(cx.fcx.lcx.ccx, t);
@ -6875,7 +6873,7 @@ fn decl_native_fn_and_pair(@crate_ctxt ccx,
call_args += vec(llarg);
}
if (arg.mode == ast.val) {
if (arg.mode == ty.mo_val) {
drop_args += vec(tup(llarg, arg.ty));
}

View File

@ -35,7 +35,13 @@ import util.typestate_ann.ts_ann;
// Data types
type arg = rec(ast.mode mode, t ty);
tag mode {
mo_val;
mo_alias;
mo_either;
}
type arg = rec(mode mode, t ty);
type field = rec(ast.ident ident, mt mt);
type method = rec(ast.proto proto,
ast.ident ident,
@ -500,12 +506,12 @@ fn path_to_str(&ast.path pth) -> str {
fn ty_to_str(ctxt cx, &t typ) -> str {
fn fn_input_to_str(ctxt cx, &rec(ast.mode mode, t ty) input) -> str {
fn fn_input_to_str(ctxt cx, &rec(mode mode, t ty) input) -> str {
auto s;
if (mode_is_alias(input.mode)) {
s = "&";
} else {
s = "";
alt (input.mode) {
case (mo_val) { s = ""; }
case (mo_alias) { s = "&"; }
case (mo_either) { s = "?"; }
}
ret s + ty_to_str(cx, input.ty);
@ -827,15 +833,6 @@ fn copy_cname(ctxt cx, t struct_ty, t cname_ty) -> t {
ret gen_ty_full(cx, struct(cx, struct_ty), cname_ty.cname);
}
// FIXME: remove me when == works on these tags.
fn mode_is_alias(ast.mode m) -> bool {
alt (m) {
case (ast.val) { ret false; }
case (ast.alias) { ret true; }
}
fail;
}
fn type_is_nil(ctxt cx, t ty) -> bool {
alt (struct(cx, ty)) {
case (ty_nil) { ret true; }
@ -1272,23 +1269,6 @@ fn equal_type_structures(&sty a, &sty b) -> bool {
}
}
fn equal_mode(ast.mode a, ast.mode b) -> bool {
alt (a) {
case (ast.val) {
alt (b) {
case (ast.val) { ret true; }
case (_) { ret false; }
}
}
case (ast.alias) {
alt (b) {
case (ast.alias) { ret true; }
case (_) { ret false; }
}
}
}
}
fn equal_mt(&mt a, &mt b) -> bool {
ret equal_mut(a.mut, b.mut) && eq_ty(a.ty, b.ty);
}
@ -1303,7 +1283,7 @@ fn equal_type_structures(&sty a, &sty b) -> bool {
auto i = 0u;
while (i < len) {
auto arg_a = args_a.(i); auto arg_b = args_b.(i);
if (!equal_mode(arg_a.mode, arg_b.mode)) { ret false; }
if (arg_a.mode != arg_b.mode) { ret false; }
if (!eq_ty(arg_a.ty, arg_b.ty)) { ret false; }
i += 1u;
}
@ -2117,12 +2097,13 @@ mod Unify {
auto actual_input = actual_inputs.(i);
// This should be safe, I think?
// FIXME: It's not. At all.
auto result_mode;
if (mode_is_alias(expected_input.mode) ||
mode_is_alias(actual_input.mode)) {
result_mode = ast.alias;
if (expected_input.mode == mo_alias ||
actual_input.mode == mo_alias) {
result_mode = mo_alias;
} else {
result_mode = ast.val;
result_mode = mo_val;
}
auto result = unify_step(cx, actual_input.ty, expected_input.ty);

View File

@ -19,7 +19,9 @@ import middle.ty.block_ty;
import middle.ty.expr_ty;
import middle.ty.field;
import middle.ty.method;
import middle.ty.mode_is_alias;
import middle.ty.mo_val;
import middle.ty.mo_alias;
import middle.ty.mo_either;
import middle.ty.pat_ty;
import middle.ty.path_to_str;
import middle.ty.struct;
@ -210,6 +212,15 @@ fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_param_count_and_ty tpt,
ret ast.ann_type(t, ty_substs_opt, none[@ts_ann]);
}
fn ast_mode_to_mode(ast.mode mode) -> ty.mode {
auto ty_mode;
alt (mode) {
case (ast.val) { ty_mode = mo_val; }
case (ast.alias) { ty_mode = mo_alias; }
}
ret ty_mode;
}
// Parses the programmer's textual representation of a type into our internal
// notion of a type. `getter` is a function that returns the type
// corresponding to a definition ID.
@ -217,8 +228,9 @@ fn ast_ty_to_ty(ty.ctxt tcx, ty_getter getter, &@ast.ty ast_ty) -> ty.t {
fn ast_arg_to_arg(ty.ctxt tcx,
ty_getter getter,
&rec(ast.mode mode, @ast.ty ty) arg)
-> rec(ast.mode mode, ty.t ty) {
ret rec(mode=arg.mode, ty=ast_ty_to_ty(tcx, getter, arg.ty));
-> rec(ty.mode mode, ty.t ty) {
auto ty_mode = ast_mode_to_mode(arg.mode);
ret rec(mode=ty_mode, ty=ast_ty_to_ty(tcx, getter, arg.ty));
}
fn ast_mt_to_mt(ty.ctxt tcx,
@ -430,8 +442,9 @@ mod Collect {
}
fn ty_of_arg(@ctxt cx, &ast.arg a) -> arg {
auto ty_mode = ast_mode_to_mode(a.mode);
auto f = bind getter(cx, _);
ret rec(mode=a.mode, ty=ast_ty_to_ty(cx.tcx, f, a.ty));
ret rec(mode=ty_mode, ty=ast_ty_to_ty(cx.tcx, f, a.ty));
}
fn ty_of_method(@ctxt cx, &@ast.method m) -> method {
@ -468,7 +481,7 @@ mod Collect {
for (ast.obj_field f in obj_info.fields) {
auto g = bind getter(cx, _);
auto t_field = ast_ty_to_ty(cx.tcx, g, f.ty);
Vec.push[arg](t_inputs, rec(mode=ast.alias, ty=t_field));
Vec.push[arg](t_inputs, rec(mode=ty.mo_alias, ty=t_field));
}
cx.type_cache.insert(obj_ty_id, t_obj);
@ -601,7 +614,7 @@ mod Collect {
let vec[arg] args = vec();
for (ast.variant_arg va in variant.node.args) {
auto arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty);
args += vec(rec(mode=ast.alias, ty=arg_ty));
args += vec(rec(mode=ty.mo_alias, ty=arg_ty));
}
auto tag_t = ty.mk_tag(cx.tcx, tag_id, ty_param_tys);
result_ty = ty.mk_fn(cx.tcx, ast.proto_fn, args, tag_t);
@ -1754,7 +1767,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
args_0 += vec(some[@ast.expr](a_0));
// FIXME: this breaks aliases. We need a ty_fn_arg.
auto arg_ty = rec(mode=ast.val,
auto arg_ty = rec(mode=mo_val,
ty=expr_ty(fcx.ccx.tcx, a_0));
Vec.push[arg](arg_tys_0, arg_ty);
}
@ -1763,7 +1776,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
// FIXME: breaks aliases too?
auto typ = next_ty_var(fcx.ccx);
Vec.push[arg](arg_tys_0, rec(mode=ast.val, ty=typ));
Vec.push[arg](arg_tys_0, rec(mode=mo_val, ty=typ));
}
}
}
@ -2869,7 +2882,7 @@ fn check_item_fn(&@crate_ctxt ccx, &span sp, ast.ident ident, &ast._fn f,
let vec[arg] inputs = vec();
for (ast.arg arg in f.decl.inputs) {
auto input_ty = ast_ty_to_ty_crate(ccx, arg.ty);
inputs += vec(rec(mode=arg.mode, ty=input_ty));
inputs += vec(rec(mode=ast_mode_to_mode(arg.mode), ty=input_ty));
}
auto output_ty = ast_ty_to_ty_crate(ccx, f.decl.output);

View File

@ -939,7 +939,7 @@ fn print_ty_fn(ps s, ast.proto proto, Option.t[str] id,
}
popen_h(s);
fn print_arg(ps s, &ast.ty_arg input) {
if (middle.ty.mode_is_alias(input.mode)) {wrd(s.s, "&");}
if (input.mode == ast.alias) {wrd(s.s, "&");}
print_type(s, input.ty);
}
auto f = print_arg;