rustc: Don't generate so many variables when typechecking functions; remove mo_either

This commit is contained in:
Patrick Walton 2011-06-08 17:57:06 -07:00
parent 8691a1a1e5
commit 7527084e62
3 changed files with 51 additions and 50 deletions

View File

@ -73,7 +73,6 @@ fn check_expr(ctx cx, &@ast::expr ex) {
auto i = 0u;
let vec[def_id] listed = [];
for (ty::arg argty in argtys) {
// FIXME Treat mo_either specially here?
if (argty.mode != ty::mo_val) {
alt (check_rooted(cx, args.(i), false)) {
case (some(?did)) {

View File

@ -42,7 +42,6 @@ import util::data::interner;
tag mode {
mo_val;
mo_alias;
mo_either;
}
type arg = rec(mode mode, t ty);
@ -486,7 +485,6 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
alt (input.mode) {
case (mo_val) { s = ""; }
case (mo_alias) { s = "&"; }
case (mo_either) { s = "?"; }
}
ret s + ty_to_str(cx, input.ty);
@ -1944,13 +1942,9 @@ mod unify {
auto expected_input = expected_inputs.(i);
auto actual_input = actual_inputs.(i);
// Unify the result modes. "mo_either" unifies with both modes.
// Unify the result modes.
auto result_mode;
if (expected_input.mode == mo_either) {
result_mode = actual_input.mode;
} else if (actual_input.mode == mo_either) {
result_mode = expected_input.mode;
} else if (expected_input.mode != actual_input.mode) {
if (expected_input.mode != actual_input.mode) {
// FIXME this is the wrong error
ret fn_common_res_err(ures_err(terr_arg_count));
} else {

View File

@ -18,7 +18,6 @@ import middle::ty::field;
import middle::ty::method;
import middle::ty::mo_val;
import middle::ty::mo_alias;
import middle::ty::mo_either;
import middle::ty::node_type_table;
import middle::ty::pat_ty;
import middle::ty::path_to_str;
@ -1401,52 +1400,60 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
// A generic function to factor out common logic from call and bind
// expressions.
fn check_call_or_bind(&@fn_ctxt fcx, &@ast::expr f,
fn check_call_or_bind(&@fn_ctxt fcx, &span sp, &@ast::expr f,
&vec[option::t[@ast::expr]] args) {
// Check the function.
check_expr(fcx, f);
// Check the arguments and generate the argument signature.
let vec[option::t[@ast::expr]] args_0 = [];
let vec[arg] arg_tys_0 = [];
// Get the function type. We need to have resolved it enough to know
// it's a ty_fn or ty_native_fn.
auto fty = expr_ty(fcx.ccx.tcx, f);
fty = ty::unify::resolve_all_vars(fcx.ccx.tcx, fcx.var_bindings, fty);
// Grab the argument types and the return type.
auto arg_tys;
alt (ty::struct(fcx.ccx.tcx, fty)) {
case (ty::ty_fn(_, ?arg_tys_0, _, _)) {
arg_tys = arg_tys_0;
}
case (ty::ty_native_fn(_, ?arg_tys_0, _)) {
arg_tys = arg_tys_0;
}
case (_) {
fcx.ccx.tcx.sess.span_err(f.span, "mismatched types: " +
"expected function or native function but found " +
ty_to_str(fcx.ccx.tcx, fty));
}
}
// Check that the correct number of arguments were supplied.
auto expected_arg_count = vec::len[ty::arg](arg_tys);
auto supplied_arg_count = vec::len[option::t[@ast::expr]](args);
if (expected_arg_count != supplied_arg_count) {
fcx.ccx.tcx.sess.span_err(sp,
#fmt("this function takes %u parameter%s but %u parameter%s \
supplied",
expected_arg_count,
if (expected_arg_count == 1u) { "" } else { "s" },
supplied_arg_count,
if (supplied_arg_count == 1u) { " was" }
else { "s were" }));
}
// Check the arguments.
// TODO: iter2
auto i = 0u;
for (option::t[@ast::expr] a_opt in args) {
alt (a_opt) {
case (some(?a)) {
check_expr(fcx, a);
auto typ = expr_ty(fcx.ccx.tcx, a);
vec::push[arg](arg_tys_0, rec(mode=mo_either, ty=typ));
}
case (none) {
auto typ = next_ty_var(fcx);
vec::push[arg](arg_tys_0, rec(mode=mo_either, ty=typ));
demand::simple(fcx, a.span, arg_tys.(i).ty,
expr_ty(fcx.ccx.tcx, a));
}
case (none) { /* no-op */ }
}
i += 1u;
}
auto rt_0 = next_ty_var(fcx);
auto t_0;
alt (struct(fcx.ccx.tcx, expr_ty(fcx.ccx.tcx, f))) {
case (ty::ty_fn(?proto, _, _, ?cf)) {
t_0 = ty::mk_fn(fcx.ccx.tcx, proto, arg_tys_0, rt_0, cf);
}
case (ty::ty_native_fn(?abi, _, _)) {
t_0 = ty::mk_native_fn(fcx.ccx.tcx, abi, arg_tys_0, rt_0);
}
case (?u) {
fcx.ccx.tcx.sess.span_err(f.span,
"check_call_or_bind(): fn expr doesn't have fn type,"
+ " instead having: " +
ty_to_str(fcx.ccx.tcx,
expr_ty(fcx.ccx.tcx, f)));
}
}
// Unify the callee and arguments.
auto f_ty = ty::expr_ty(fcx.ccx.tcx, f);
auto f_tps = ty::expr_ty_params_and_ty(fcx.ccx.tcx, f)._0;
auto tpt_1 = demand::full(fcx, f.span, f_ty, t_0, f_tps,
NO_AUTODEREF);
//replace_expr_type(fcx, f, tpt_1);
}
// A generic function for checking assignment expressions
@ -1461,14 +1468,15 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
}
// A generic function for checking call expressions
fn check_call(&@fn_ctxt fcx, &@ast::expr f, &vec[@ast::expr] args) {
fn check_call(&@fn_ctxt fcx, &span sp, &@ast::expr f,
&vec[@ast::expr] args) {
let vec[option::t[@ast::expr]] args_opt_0 = [];
for (@ast::expr arg in args) {
args_opt_0 += [some[@ast::expr](arg)];
}
// Call the generic checker.
check_call_or_bind(fcx, f, args_opt_0);
check_call_or_bind(fcx, sp, f, args_opt_0);
}
// A generic function for checking for or for-each loops
@ -1861,7 +1869,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
case (ast::expr_bind(?f, ?args, ?a)) {
// Call the generic checker.
check_call_or_bind(fcx, f, args);
check_call_or_bind(fcx, expr.span, f, args);
// Pull the argument and return types out.
auto proto_1;
@ -1904,7 +1912,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
function name onto purity-designation */
require_pure_call(fcx.ccx, fcx.purity, f, expr.span);
check_call(fcx, f, args);
check_call(fcx, expr.span, f, args);
// Pull the return type out of the type of the function.
auto rt_1 = ty::mk_nil(fcx.ccx.tcx); // FIXME: typestate botch
@ -1959,7 +1967,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
}
case (ast::expr_spawn(_, _, ?f, ?args, ?a)) {
check_call(fcx, f, args);
check_call(fcx, expr.span, f, args);
auto fty = expr_ty(fcx.ccx.tcx, f);
auto ret_ty = ty::ret_ty_of_fn_ty(fcx.ccx.tcx, fty);