rustc: Remove generalize_ty. Instead, maintain an explicit type parameter substitution list.
This commit is contained in:
@@ -742,6 +742,10 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef {
|
|||||||
case (ty.ty_param(_)) {
|
case (ty.ty_param(_)) {
|
||||||
llty = T_i8();
|
llty = T_i8();
|
||||||
}
|
}
|
||||||
|
case (ty.ty_bound_param(_)) {
|
||||||
|
log "ty_bound_param in trans.type_of";
|
||||||
|
fail;
|
||||||
|
}
|
||||||
case (ty.ty_type) { llty = T_ptr(T_tydesc(cx.tn)); }
|
case (ty.ty_type) { llty = T_ptr(T_tydesc(cx.tn)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1144,6 +1148,7 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint {
|
|||||||
auto tup_ty = ty.plain_tup_ty(args);
|
auto tup_ty = ty.plain_tup_ty(args);
|
||||||
|
|
||||||
// Perform any type parameter substitutions.
|
// Perform any type parameter substitutions.
|
||||||
|
tup_ty = ty.bind_params_in_type(tup_ty);
|
||||||
tup_ty = ty.substitute_type_params(subtys, tup_ty);
|
tup_ty = ty.substitute_type_params(subtys, tup_ty);
|
||||||
|
|
||||||
// Here we possibly do a recursive call.
|
// Here we possibly do a recursive call.
|
||||||
@@ -1216,7 +1221,8 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result {
|
|||||||
let vec[@ty.t] raw_tys = variant.args;
|
let vec[@ty.t] raw_tys = variant.args;
|
||||||
let vec[@ty.t] tys = vec();
|
let vec[@ty.t] tys = vec();
|
||||||
for (@ty.t raw_ty in raw_tys) {
|
for (@ty.t raw_ty in raw_tys) {
|
||||||
auto t = ty.substitute_type_params(tps, raw_ty);
|
auto t = ty.bind_params_in_type(raw_ty);
|
||||||
|
t = ty.substitute_type_params(tps, t);
|
||||||
tys += vec(t);
|
tys += vec(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1390,7 +1396,8 @@ fn GEP_tag(@block_ctxt cx,
|
|||||||
auto i = 0;
|
auto i = 0;
|
||||||
let vec[@ty.t] true_arg_tys = vec();
|
let vec[@ty.t] true_arg_tys = vec();
|
||||||
for (@ty.t aty in arg_tys) {
|
for (@ty.t aty in arg_tys) {
|
||||||
auto arg_ty = ty.substitute_type_params(ty_substs, aty);
|
auto arg_ty = ty.bind_params_in_type(aty);
|
||||||
|
arg_ty = ty.substitute_type_params(ty_substs, arg_ty);
|
||||||
true_arg_tys += vec(arg_ty);
|
true_arg_tys += vec(arg_ty);
|
||||||
if (i == ix) {
|
if (i == ix) {
|
||||||
elem_ty = arg_ty;
|
elem_ty = arg_ty;
|
||||||
@@ -2118,8 +2125,9 @@ fn iter_structural_ty_full(@block_ctxt cx,
|
|||||||
auto llfldp_b = rslt.val;
|
auto llfldp_b = rslt.val;
|
||||||
variant_cx = rslt.bcx;
|
variant_cx = rslt.bcx;
|
||||||
|
|
||||||
auto ty_subst =
|
auto ty_subst = ty.bind_params_in_type(a.ty);
|
||||||
ty.substitute_type_params(tps, a.ty);
|
ty_subst =
|
||||||
|
ty.substitute_type_params(tps, ty_subst);
|
||||||
|
|
||||||
auto llfld_a =
|
auto llfld_a =
|
||||||
load_if_immediate(variant_cx,
|
load_if_immediate(variant_cx,
|
||||||
@@ -2501,15 +2509,10 @@ fn target_type(@crate_ctxt cx, @ty.t t) -> @ty.t {
|
|||||||
ret t;
|
ret t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts an annotation to a type
|
||||||
fn node_ann_type(@crate_ctxt cx, &ast.ann a) -> @ty.t {
|
fn node_ann_type(@crate_ctxt cx, &ast.ann a) -> @ty.t {
|
||||||
alt (a) {
|
ret target_type(cx, ty.ann_to_monotype(a));
|
||||||
case (ast.ann_none) {
|
|
||||||
cx.sess.bug("missing type annotation");
|
|
||||||
}
|
|
||||||
case (ast.ann_type(?t, _, _)) {
|
|
||||||
ret target_type(cx, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_ann_ty_params(&ast.ann a) -> vec[@ty.t] {
|
fn node_ann_ty_params(&ast.ann a) -> vec[@ty.t] {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import front.creader;
|
|||||||
import util.common;
|
import util.common;
|
||||||
import util.common.new_def_hash;
|
import util.common.new_def_hash;
|
||||||
import util.common.span;
|
import util.common.span;
|
||||||
|
import util.typestate_ann.ts_ann;
|
||||||
|
|
||||||
// Data types
|
// Data types
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ tag sty {
|
|||||||
ty_var(int); // ephemeral type var
|
ty_var(int); // ephemeral type var
|
||||||
ty_local(ast.def_id); // type of a local var
|
ty_local(ast.def_id); // type of a local var
|
||||||
ty_param(uint); // fn/tag type param
|
ty_param(uint); // fn/tag type param
|
||||||
|
ty_bound_param(uint); // bound param, only paths
|
||||||
ty_type;
|
ty_type;
|
||||||
ty_native;
|
ty_native;
|
||||||
// TODO: ty_fn_arg(@t), for a possibly-aliased function argument
|
// TODO: ty_fn_arg(@t), for a possibly-aliased function argument
|
||||||
@@ -67,10 +69,9 @@ tag sty {
|
|||||||
// Data structures used in type unification
|
// Data structures used in type unification
|
||||||
|
|
||||||
type unify_handler = obj {
|
type unify_handler = obj {
|
||||||
fn resolve_local(ast.def_id id) -> @t;
|
fn resolve_local(ast.def_id id) -> option.t[@t];
|
||||||
fn record_local(ast.def_id id, @t ty);
|
fn record_local(ast.def_id id, @t ty); // TODO: -> unify_result
|
||||||
fn unify_expected_param(uint id, @t expected, @t actual) -> unify_result;
|
fn record_param(uint index, @t binding) -> unify_result;
|
||||||
fn unify_actual_param(uint id, @t expected, @t actual) -> unify_result;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tag type_err {
|
tag type_err {
|
||||||
@@ -249,6 +250,10 @@ fn ty_to_str(&@t typ) -> str {
|
|||||||
case (ty_param(?id)) {
|
case (ty_param(?id)) {
|
||||||
s += "'" + _str.unsafe_from_bytes(vec(('a' as u8) + (id as u8)));
|
s += "'" + _str.unsafe_from_bytes(vec(('a' as u8) + (id as u8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case (ty_bound_param(?id)) {
|
||||||
|
s += "''" + _str.unsafe_from_bytes(vec(('a' as u8) + (id as u8)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret s;
|
ret s;
|
||||||
@@ -341,9 +346,10 @@ fn fold_ty(ty_fold fld, @t ty) -> @t {
|
|||||||
}
|
}
|
||||||
ret rewrap(ty, ty_obj(new_methods));
|
ret rewrap(ty, ty_obj(new_methods));
|
||||||
}
|
}
|
||||||
case (ty_var(_)) { ret fld.fold_simple_ty(ty); }
|
case (ty_var(_)) { ret fld.fold_simple_ty(ty); }
|
||||||
case (ty_local(_)) { ret fld.fold_simple_ty(ty); }
|
case (ty_local(_)) { ret fld.fold_simple_ty(ty); }
|
||||||
case (ty_param(_)) { ret fld.fold_simple_ty(ty); }
|
case (ty_param(_)) { ret fld.fold_simple_ty(ty); }
|
||||||
|
case (ty_bound_param(_)) { ret fld.fold_simple_ty(ty); }
|
||||||
}
|
}
|
||||||
|
|
||||||
fail;
|
fail;
|
||||||
@@ -603,6 +609,50 @@ fn ann_to_type(&ast.ann ann) -> @t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ann_to_type_params(&ast.ann ann) -> vec[@t] {
|
||||||
|
alt (ann) {
|
||||||
|
case (ast.ann_none) {
|
||||||
|
log "ann_to_type_params() called on node with no type params";
|
||||||
|
fail;
|
||||||
|
}
|
||||||
|
case (ast.ann_type(_, ?tps, _)) {
|
||||||
|
alt (tps) {
|
||||||
|
case (none[vec[@ty.t]]) {
|
||||||
|
let vec[@t] result = vec();
|
||||||
|
ret result;
|
||||||
|
}
|
||||||
|
case (some[vec[@ty.t]](?tps)) { ret tps; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the type of an annotation, with type parameter substitutions
|
||||||
|
// performed if applicable.
|
||||||
|
fn ann_to_monotype(ast.ann a) -> @ty.t {
|
||||||
|
// TODO: Refactor to use recursive pattern matching when we're more
|
||||||
|
// confident that it works.
|
||||||
|
alt (a) {
|
||||||
|
case (ast.ann_none) {
|
||||||
|
log "ann_to_monotype() called on expression with no type!";
|
||||||
|
fail;
|
||||||
|
}
|
||||||
|
case (ast.ann_type(?typ, ?tps_opt, _)) {
|
||||||
|
alt (tps_opt) {
|
||||||
|
case (none[vec[@ty.t]]) { ret typ; }
|
||||||
|
case (some[vec[@ty.t]](?tps)) {
|
||||||
|
ret substitute_type_params(tps, typ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turns a type into an ann_type, using defaults for other fields.
|
||||||
|
fn triv_ann(@ty.t typ) -> ast.ann {
|
||||||
|
ret ast.ann_type(typ, none[vec[@ty.t]], none[@ts_ann]);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the number of distinct type parameters in the given type.
|
// Returns the number of distinct type parameters in the given type.
|
||||||
fn count_ty_params(@t ty) -> uint {
|
fn count_ty_params(@t ty) -> uint {
|
||||||
state obj ty_param_counter(@mutable vec[uint] param_indices) {
|
state obj ty_param_counter(@mutable vec[uint] param_indices) {
|
||||||
@@ -631,6 +681,22 @@ fn count_ty_params(@t ty) -> uint {
|
|||||||
ret _vec.len[uint](*param_indices);
|
ret _vec.len[uint](*param_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_contains_vars(@t typ) -> bool {
|
||||||
|
state obj ty_var_counter(@mutable bool flag) {
|
||||||
|
fn fold_simple_ty(@t typ) -> @t {
|
||||||
|
alt (typ.struct) {
|
||||||
|
case (ty_var(_)) { *flag = true; }
|
||||||
|
case (_) { /* fall through */ }
|
||||||
|
}
|
||||||
|
ret typ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let @mutable bool flag = @mutable false;
|
||||||
|
fold_ty(ty_var_counter(flag), typ);
|
||||||
|
ret *flag;
|
||||||
|
}
|
||||||
|
|
||||||
// Type accessors for substructures of types
|
// Type accessors for substructures of types
|
||||||
|
|
||||||
fn ty_fn_args(@t fty) -> vec[arg] {
|
fn ty_fn_args(@t fty) -> vec[arg] {
|
||||||
@@ -739,12 +805,14 @@ fn block_ty(&ast.block b) -> @t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
|
||||||
|
// doesn't provide type parameter substitutions.
|
||||||
fn pat_ty(@ast.pat pat) -> @t {
|
fn pat_ty(@ast.pat pat) -> @t {
|
||||||
alt (pat.node) {
|
alt (pat.node) {
|
||||||
case (ast.pat_wild(?ann)) { ret ann_to_type(ann); }
|
case (ast.pat_wild(?ann)) { ret ann_to_monotype(ann); }
|
||||||
case (ast.pat_lit(_, ?ann)) { ret ann_to_type(ann); }
|
case (ast.pat_lit(_, ?ann)) { ret ann_to_monotype(ann); }
|
||||||
case (ast.pat_bind(_, _, ?ann)) { ret ann_to_type(ann); }
|
case (ast.pat_bind(_, _, ?ann)) { ret ann_to_monotype(ann); }
|
||||||
case (ast.pat_tag(_, _, _, ?ann)) { ret ann_to_type(ann); }
|
case (ast.pat_tag(_, _, _, ?ann)) { ret ann_to_monotype(ann); }
|
||||||
}
|
}
|
||||||
fail; // not reached
|
fail; // not reached
|
||||||
}
|
}
|
||||||
@@ -795,10 +863,83 @@ fn expr_ann(@ast.expr expr) -> option.t[ast.ann] {
|
|||||||
fail;
|
fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the type of an expression as a monotype.
|
||||||
|
//
|
||||||
|
// NB: This type doesn't provide type parameter substitutions; e.g. if you
|
||||||
|
// ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
|
||||||
|
// instead of "fn(&T) -> T with T = int". If this isn't what you want, see
|
||||||
|
// expr_ty_params_and_ty() below.
|
||||||
fn expr_ty(@ast.expr expr) -> @t {
|
fn expr_ty(@ast.expr expr) -> @t {
|
||||||
alt (expr_ann(expr)) {
|
alt (expr_ann(expr)) {
|
||||||
case (none[ast.ann]) { ret plain_ty(ty_nil); }
|
case (none[ast.ann]) { ret plain_ty(ty_nil); }
|
||||||
case (some[ast.ann](?a)) { ret ann_to_type(a); }
|
case (some[ast.ann](?a)) { ret ann_to_monotype(a); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expr_ty_params_and_ty(@ast.expr expr) -> tup(vec[@t], @t) {
|
||||||
|
alt (expr_ann(expr)) {
|
||||||
|
case (none[ast.ann]) {
|
||||||
|
let vec[@t] tps = vec();
|
||||||
|
ret tup(tps, plain_ty(ty_nil));
|
||||||
|
}
|
||||||
|
case (some[ast.ann](?a)) {
|
||||||
|
ret tup(ann_to_type_params(a), ann_to_type(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expr_has_ty_params(@ast.expr expr) -> bool {
|
||||||
|
// FIXME: Rewrite using complex patterns when they're trustworthy.
|
||||||
|
alt (expr_ann(expr)) {
|
||||||
|
case (none[ast.ann]) { fail; }
|
||||||
|
case (some[ast.ann](?a)) {
|
||||||
|
alt (a) {
|
||||||
|
case (ast.ann_none) { fail; }
|
||||||
|
case (ast.ann_type(_, ?tps_opt, _)) {
|
||||||
|
ret !option.is_none[vec[@t]](tps_opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: At the moment this works only for call, bind, and path expressions.
|
||||||
|
fn replace_expr_type(@ast.expr expr, tup(vec[@t], @t) new_tyt) -> @ast.expr {
|
||||||
|
auto new_tps;
|
||||||
|
if (expr_has_ty_params(expr)) {
|
||||||
|
new_tps = some[vec[@t]](new_tyt._0);
|
||||||
|
} else {
|
||||||
|
new_tps = none[vec[@t]];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ann = ast.ann_type(new_tyt._1, new_tps, none[@ts_ann]);
|
||||||
|
|
||||||
|
alt (expr.node) {
|
||||||
|
case (ast.expr_call(?callee, ?args, _)) {
|
||||||
|
ret @fold.respan[ast.expr_](expr.span,
|
||||||
|
ast.expr_call(callee, args, ann));
|
||||||
|
}
|
||||||
|
case (ast.expr_self_method(?ident, _)) {
|
||||||
|
ret @fold.respan[ast.expr_](expr.span,
|
||||||
|
ast.expr_self_method(ident, ann));
|
||||||
|
}
|
||||||
|
case (ast.expr_bind(?callee, ?args, _)) {
|
||||||
|
ret @fold.respan[ast.expr_](expr.span,
|
||||||
|
ast.expr_bind(callee, args, ann));
|
||||||
|
}
|
||||||
|
case (ast.expr_field(?e, ?i, _)) {
|
||||||
|
ret @fold.respan[ast.expr_](expr.span,
|
||||||
|
ast.expr_field(e, i, ann));
|
||||||
|
}
|
||||||
|
case (ast.expr_path(?p, ?dopt, _)) {
|
||||||
|
ret @fold.respan[ast.expr_](expr.span,
|
||||||
|
ast.expr_path(p, dopt, ann));
|
||||||
|
}
|
||||||
|
case (_) {
|
||||||
|
log "unhandled expr type in replace_expr_type(): " +
|
||||||
|
pretty.pprust.expr_to_str(expr);
|
||||||
|
fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1135,31 +1276,33 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
ret ures_ok(actual);
|
ret ures_ok(actual);
|
||||||
}
|
}
|
||||||
case (ty.ty_local(?actual_id)) {
|
case (ty.ty_local(?actual_id)) {
|
||||||
auto actual_ty = handler.resolve_local(actual_id);
|
auto result_ty;
|
||||||
auto result = unify_step(bindings,
|
alt (handler.resolve_local(actual_id)) {
|
||||||
expected,
|
case (none[@ty.t]) { result_ty = expected; }
|
||||||
actual_ty,
|
case (some[@ty.t](?actual_ty)) {
|
||||||
handler);
|
auto result = unify_step(bindings,
|
||||||
alt (result) {
|
expected,
|
||||||
case (ures_ok(?result_ty)) {
|
actual_ty,
|
||||||
handler.record_local(actual_id, result_ty);
|
handler);
|
||||||
|
alt (result) {
|
||||||
|
case (ures_ok(?rty)) { result_ty = rty; }
|
||||||
|
case (_) { ret result; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case (_) { /* empty */ }
|
|
||||||
}
|
}
|
||||||
ret result;
|
|
||||||
|
handler.record_local(actual_id, result_ty);
|
||||||
|
ret ures_ok(result_ty);
|
||||||
}
|
}
|
||||||
case (ty.ty_param(?actual_id)) {
|
case (ty.ty_bound_param(?actual_id)) {
|
||||||
alt (expected.struct) {
|
alt (expected.struct) {
|
||||||
|
case (ty.ty_local(_)) {
|
||||||
|
log "TODO: bound param unifying with local";
|
||||||
|
fail;
|
||||||
|
}
|
||||||
|
|
||||||
// These two unify via logic lower down. Fall through.
|
|
||||||
case (ty.ty_local(_)) { }
|
|
||||||
case (ty.ty_var(_)) { }
|
|
||||||
|
|
||||||
// More-concrete types can unify against params here.
|
|
||||||
case (_) {
|
case (_) {
|
||||||
ret handler.unify_actual_param(actual_id,
|
ret handler.record_param(actual_id, expected);
|
||||||
expected,
|
|
||||||
actual);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1177,6 +1320,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
case (ty.ty_str) { ret struct_cmp(expected, actual); }
|
case (ty.ty_str) { ret struct_cmp(expected, actual); }
|
||||||
case (ty.ty_type) { ret struct_cmp(expected, actual); }
|
case (ty.ty_type) { ret struct_cmp(expected, actual); }
|
||||||
case (ty.ty_native) { ret struct_cmp(expected, actual); }
|
case (ty.ty_native) { ret struct_cmp(expected, actual); }
|
||||||
|
case (ty.ty_param(_)) { ret struct_cmp(expected, actual); }
|
||||||
|
|
||||||
case (ty.ty_tag(?expected_id, ?expected_tps)) {
|
case (ty.ty_tag(?expected_id, ?expected_tps)) {
|
||||||
alt (actual.struct) {
|
alt (actual.struct) {
|
||||||
@@ -1510,23 +1654,27 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case (ty.ty_local(?expected_id)) {
|
case (ty.ty_local(?expected_id)) {
|
||||||
auto expected_ty = handler.resolve_local(expected_id);
|
auto result_ty;
|
||||||
auto result = unify_step(bindings,
|
alt (handler.resolve_local(expected_id)) {
|
||||||
expected_ty,
|
case (none[@ty.t]) { result_ty = actual; }
|
||||||
actual,
|
case (some[@ty.t](?expected_ty)) {
|
||||||
handler);
|
auto result = unify_step(bindings,
|
||||||
alt (result) {
|
expected_ty,
|
||||||
case (ures_ok(?result_ty)) {
|
actual,
|
||||||
handler.record_local(expected_id, result_ty);
|
handler);
|
||||||
|
alt (result) {
|
||||||
|
case (ures_ok(?rty)) { result_ty = rty; }
|
||||||
|
case (_) { ret result; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case (_) { /* empty */ }
|
|
||||||
}
|
}
|
||||||
ret result;
|
|
||||||
|
handler.record_local(expected_id, result_ty);
|
||||||
|
ret ures_ok(result_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
case (ty.ty_param(?expected_id)) {
|
case (ty.ty_bound_param(?expected_id)) {
|
||||||
ret handler.unify_expected_param(expected_id, expected,
|
ret handler.record_param(expected_id, actual);
|
||||||
actual);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1599,7 +1747,8 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
|
|||||||
alt (ures) {
|
alt (ures) {
|
||||||
case (ures_ok(?t)) {
|
case (ures_ok(?t)) {
|
||||||
auto set_types = unify_sets(bindings);
|
auto set_types = unify_sets(bindings);
|
||||||
ret ures_ok(substitute(bindings, set_types, t));
|
auto t2 = substitute(bindings, set_types, t);
|
||||||
|
ret ures_ok(t2);
|
||||||
}
|
}
|
||||||
case (_) { ret ures; }
|
case (_) { ret ures; }
|
||||||
}
|
}
|
||||||
@@ -1652,58 +1801,15 @@ fn type_err_to_str(&ty.type_err err) -> str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type parameter resolution, used in translation and typechecking
|
// Performs bound type parameter replacement using the supplied mapping from
|
||||||
|
|
||||||
fn resolve_ty_params(ty_param_count_and_ty ty_params_and_polyty,
|
|
||||||
@t monoty) -> vec[@t] {
|
|
||||||
// TODO: Use a vector, not a hashmap here.
|
|
||||||
obj resolve_ty_params_handler(@hashmap[uint,@t] bindings) {
|
|
||||||
fn resolve_local(ast.def_id id) -> @t { log "resolve local"; fail; }
|
|
||||||
fn record_local(ast.def_id id, @t ty) { log "record local"; fail; }
|
|
||||||
fn unify_expected_param(uint id, @t expected, @t actual)
|
|
||||||
-> unify_result {
|
|
||||||
bindings.insert(id, actual);
|
|
||||||
ret ures_ok(actual);
|
|
||||||
}
|
|
||||||
fn unify_actual_param(uint id, @t expected, @t actual)
|
|
||||||
-> unify_result {
|
|
||||||
bindings.insert(id, expected);
|
|
||||||
ret ures_ok(expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bindings = @common.new_uint_hash[@t]();
|
|
||||||
auto handler = resolve_ty_params_handler(bindings);
|
|
||||||
|
|
||||||
auto unify_res = unify(ty_params_and_polyty._1, monoty, handler);
|
|
||||||
alt (unify_res) {
|
|
||||||
case (ures_ok(_)) { /* fall through */ }
|
|
||||||
case (ures_err(_,?exp,?act)) {
|
|
||||||
log "resolve_ty_params mismatch: " + ty_to_str(exp) + " " +
|
|
||||||
ty_to_str(act);
|
|
||||||
fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let vec[@t] result_tys = vec();
|
|
||||||
auto ty_param_count = ty_params_and_polyty._0;
|
|
||||||
auto i = 0u;
|
|
||||||
while (i < ty_param_count) {
|
|
||||||
check (bindings.contains_key(i));
|
|
||||||
result_tys += vec(bindings.get(i));
|
|
||||||
i += 1u;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret result_tys;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Performs type parameter replacement using the supplied mapping from
|
|
||||||
// parameter IDs to types.
|
// parameter IDs to types.
|
||||||
fn substitute_type_params(vec[@t] bindings, @t typ) -> @t {
|
fn substitute_type_params(vec[@t] bindings, @t typ) -> @t {
|
||||||
state obj param_replacer(vec[@t] bindings) {
|
state obj param_replacer(vec[@t] bindings) {
|
||||||
fn fold_simple_ty(@t typ) -> @t {
|
fn fold_simple_ty(@t typ) -> @t {
|
||||||
alt (typ.struct) {
|
alt (typ.struct) {
|
||||||
case (ty_param(?param_index)) { ret bindings.(param_index); }
|
case (ty_bound_param(?param_index)) {
|
||||||
|
ret bindings.(param_index);
|
||||||
|
}
|
||||||
case (_) { ret typ; }
|
case (_) { ret typ; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1712,6 +1818,29 @@ fn substitute_type_params(vec[@t] bindings, @t typ) -> @t {
|
|||||||
ret fold_ty(replacer, typ);
|
ret fold_ty(replacer, typ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts type parameters in a type to bound type parameters.
|
||||||
|
fn bind_params_in_type(@t typ) -> @t {
|
||||||
|
state obj folder(() env) {
|
||||||
|
fn fold_simple_ty(@t typ) -> @t {
|
||||||
|
alt (typ.struct) {
|
||||||
|
case (ty_bound_param(?index)) {
|
||||||
|
log "bind_params_in_type() called on type that already " +
|
||||||
|
"has bound params in it";
|
||||||
|
fail;
|
||||||
|
}
|
||||||
|
case (ty_param(?index)) {
|
||||||
|
ret plain_ty(ty_bound_param(index));
|
||||||
|
}
|
||||||
|
case (_) {
|
||||||
|
ret typ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret fold_ty(folder(()), typ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn def_has_ty_params(&ast.def def) -> bool {
|
fn def_has_ty_params(&ast.def def) -> bool {
|
||||||
alt (def) {
|
alt (def) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import util.common.span;
|
|||||||
import middle.ty;
|
import middle.ty;
|
||||||
import middle.ty.ann_to_type;
|
import middle.ty.ann_to_type;
|
||||||
import middle.ty.arg;
|
import middle.ty.arg;
|
||||||
|
import middle.ty.bind_params_in_type;
|
||||||
import middle.ty.block_ty;
|
import middle.ty.block_ty;
|
||||||
import middle.ty.expr_ty;
|
import middle.ty.expr_ty;
|
||||||
import middle.ty.field;
|
import middle.ty.field;
|
||||||
@@ -19,6 +20,7 @@ import middle.ty.mode_is_alias;
|
|||||||
import middle.ty.pat_ty;
|
import middle.ty.pat_ty;
|
||||||
import middle.ty.path_to_str;
|
import middle.ty.path_to_str;
|
||||||
import middle.ty.plain_ty;
|
import middle.ty.plain_ty;
|
||||||
|
import middle.ty.triv_ann;
|
||||||
import middle.ty.ty_to_str;
|
import middle.ty.ty_to_str;
|
||||||
import middle.ty.type_is_integral;
|
import middle.ty.type_is_integral;
|
||||||
import middle.ty.type_is_scalar;
|
import middle.ty.type_is_scalar;
|
||||||
@@ -61,41 +63,12 @@ type fn_ctxt = rec(@ty.t ret_ty,
|
|||||||
// Used for ast_ty_to_ty() below.
|
// Used for ast_ty_to_ty() below.
|
||||||
type ty_getter = fn(ast.def_id) -> ty.ty_param_count_and_ty;
|
type ty_getter = fn(ast.def_id) -> ty.ty_param_count_and_ty;
|
||||||
|
|
||||||
// Turns a type into an ann_type, using defaults for other fields.
|
|
||||||
fn triv_ann(@ty.t t) -> ann {
|
|
||||||
ret ast.ann_type(t, none[vec[@ty.t]], none[@ts_ann]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to fill in the annotation for things that have uninteresting
|
// Used to fill in the annotation for things that have uninteresting
|
||||||
// types
|
// types
|
||||||
fn boring_ann() -> ann {
|
fn boring_ann() -> ann {
|
||||||
ret triv_ann(plain_ty(ty_nil));
|
ret triv_ann(plain_ty(ty_nil));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces parameter types inside a type with type variables.
|
|
||||||
fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t {
|
|
||||||
state obj ty_generalizer(@crate_ctxt cx,
|
|
||||||
@hashmap[uint,@ty.t] ty_params_to_ty_vars) {
|
|
||||||
fn fold_simple_ty(@ty.t t) -> @ty.t {
|
|
||||||
alt (t.struct) {
|
|
||||||
case (ty.ty_param(?pid)) {
|
|
||||||
if (ty_params_to_ty_vars.contains_key(pid)) {
|
|
||||||
ret ty_params_to_ty_vars.get(pid);
|
|
||||||
}
|
|
||||||
auto var_ty = next_ty_var(cx);
|
|
||||||
ty_params_to_ty_vars.insert(pid, var_ty);
|
|
||||||
ret var_ty;
|
|
||||||
}
|
|
||||||
case (_) { /* fall through */ }
|
|
||||||
}
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto generalizer = ty_generalizer(cx, @common.new_uint_hash[@ty.t]());
|
|
||||||
ret ty.fold_ty(generalizer, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Substitutes the user's explicit types for the parameters in a path
|
// Substitutes the user's explicit types for the parameters in a path
|
||||||
// expression.
|
// expression.
|
||||||
fn substitute_ty_params(&@crate_ctxt ccx,
|
fn substitute_ty_params(&@crate_ctxt ccx,
|
||||||
@@ -106,7 +79,7 @@ fn substitute_ty_params(&@crate_ctxt ccx,
|
|||||||
state obj ty_substituter(@crate_ctxt ccx, vec[@ty.t] supplied) {
|
state obj ty_substituter(@crate_ctxt ccx, vec[@ty.t] supplied) {
|
||||||
fn fold_simple_ty(@ty.t typ) -> @ty.t {
|
fn fold_simple_ty(@ty.t typ) -> @ty.t {
|
||||||
alt (typ.struct) {
|
alt (typ.struct) {
|
||||||
case (ty.ty_param(?pid)) { ret supplied.(pid); }
|
case (ty.ty_bound_param(?pid)) { ret supplied.(pid); }
|
||||||
case (_) { ret typ; }
|
case (_) { ret typ; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +163,7 @@ fn ty_param_count_and_ty_for_def(@fn_ctxt fcx, &ast.def defn)
|
|||||||
fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_param_count_and_ty tpt,
|
fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_param_count_and_ty tpt,
|
||||||
&span sp) -> ast.ann {
|
&span sp) -> ast.ann {
|
||||||
auto ty_param_count = tpt._0;
|
auto ty_param_count = tpt._0;
|
||||||
auto t = tpt._1;
|
auto t = bind_params_in_type(tpt._1);
|
||||||
|
|
||||||
auto ty_substs_opt;
|
auto ty_substs_opt;
|
||||||
auto ty_substs_len = _vec.len[@ast.ty](pth.node.types);
|
auto ty_substs_len = _vec.len[@ast.ty](pth.node.types);
|
||||||
@@ -208,15 +181,15 @@ fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_param_count_and_ty tpt,
|
|||||||
"parameters");
|
"parameters");
|
||||||
fail;
|
fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = substitute_ty_params(fcx.ccx, t, ty_param_count, ty_substs, sp);
|
|
||||||
} else {
|
} else {
|
||||||
ty_substs_opt = none[vec[@ty.t]];
|
// We will acquire the type parameters through unification.
|
||||||
|
let vec[@ty.t] ty_substs = vec();
|
||||||
if (ty_param_count > 0u) {
|
auto i = 0u;
|
||||||
// We will acquire the type parameters through unification.
|
while (i < ty_param_count) {
|
||||||
t = generalize_ty(fcx.ccx, t);
|
ty_substs += vec(next_ty_var(fcx.ccx));
|
||||||
|
i += 1u;
|
||||||
}
|
}
|
||||||
|
ty_substs_opt = some[vec[@ty.t]](ty_substs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret ast.ann_type(t, ty_substs_opt, none[@ts_ann]);
|
ret ast.ann_type(t, ty_substs_opt, none[@ts_ann]);
|
||||||
@@ -249,11 +222,12 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t {
|
|||||||
//
|
//
|
||||||
// TODO: Make sure the number of supplied bindings matches the number
|
// TODO: Make sure the number of supplied bindings matches the number
|
||||||
// of type parameters in the typedef. Emit a friendly error otherwise.
|
// of type parameters in the typedef. Emit a friendly error otherwise.
|
||||||
|
auto bound_ty = bind_params_in_type(params_opt_and_ty._1);
|
||||||
let vec[@ty.t] param_bindings = vec();
|
let vec[@ty.t] param_bindings = vec();
|
||||||
for (@ast.ty ast_ty in args) {
|
for (@ast.ty ast_ty in args) {
|
||||||
param_bindings += vec(ast_ty_to_ty(getter, ast_ty));
|
param_bindings += vec(ast_ty_to_ty(getter, ast_ty));
|
||||||
}
|
}
|
||||||
ret ty.substitute_type_params(param_bindings, params_opt_and_ty._1);
|
ret ty.substitute_type_params(param_bindings, bound_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mut = ast.imm;
|
auto mut = ast.imm;
|
||||||
@@ -337,7 +311,8 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret @rec(struct=sty, cname=cname);
|
auto typ = @rec(struct=sty, cname=cname);
|
||||||
|
ret typ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A convenience function to use a crate_ctxt to resolve names for
|
// A convenience function to use a crate_ctxt to resolve names for
|
||||||
@@ -843,43 +818,72 @@ fn collect_item_types(session.session sess, @ast.crate crate)
|
|||||||
ret tup(crate_, type_cache, id_to_ty_item);
|
ret tup(crate_, type_cache, id_to_ty_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unify(&@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> ty.unify_result {
|
|
||||||
obj unify_handler(@fn_ctxt fcx) {
|
// Type unification
|
||||||
fn resolve_local(ast.def_id id) -> @ty.t {
|
|
||||||
if (!fcx.locals.contains_key(id)) {
|
mod Unify {
|
||||||
ret next_ty_var(fcx.ccx);
|
fn simple(@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> ty.unify_result {
|
||||||
}
|
// FIXME: horrid botch
|
||||||
ret fcx.locals.get(id);
|
let vec[mutable @ty.t] param_substs =
|
||||||
}
|
vec(mutable plain_ty(ty.ty_nil));
|
||||||
fn record_local(ast.def_id id, @ty.t t) {
|
_vec.pop[mutable @ty.t](param_substs);
|
||||||
fcx.locals.insert(id, t);
|
ret with_params(fcx, expected, actual, param_substs);
|
||||||
}
|
|
||||||
fn unify_expected_param(uint id, @ty.t expected, @ty.t actual)
|
|
||||||
-> ty.unify_result {
|
|
||||||
alt (actual.struct) {
|
|
||||||
case (ty.ty_param(?actual_id)) {
|
|
||||||
if (id == actual_id) { ret ty.ures_ok(expected); }
|
|
||||||
}
|
|
||||||
case (_) { /* fall through */ }
|
|
||||||
}
|
|
||||||
ret ty.ures_err(ty.terr_mismatch, expected, actual);
|
|
||||||
}
|
|
||||||
fn unify_actual_param(uint id, @ty.t expected, @ty.t actual)
|
|
||||||
-> ty.unify_result {
|
|
||||||
alt (expected.struct) {
|
|
||||||
case (ty.ty_param(?expected_id)) {
|
|
||||||
if (id == expected_id) { ret ty.ures_ok(actual); }
|
|
||||||
}
|
|
||||||
case (_) { /* fall through */ }
|
|
||||||
}
|
|
||||||
ret ty.ures_err(ty.terr_mismatch, expected, actual);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto handler = unify_handler(fcx);
|
fn with_params(@fn_ctxt fcx, @ty.t expected, @ty.t actual,
|
||||||
ret ty.unify(expected, actual, handler);
|
vec[mutable @ty.t] param_substs) -> ty.unify_result {
|
||||||
|
obj unify_handler(@fn_ctxt fcx, vec[mutable @ty.t] param_substs) {
|
||||||
|
fn resolve_local(ast.def_id id) -> option.t[@ty.t] {
|
||||||
|
alt (fcx.locals.find(id)) {
|
||||||
|
case (none[@ty.t]) { ret none[@ty.t]; }
|
||||||
|
case (some[@ty.t](?existing_type)) {
|
||||||
|
if (ty.type_contains_vars(existing_type)) {
|
||||||
|
// Not fully resolved yet. The writeback phase
|
||||||
|
// will mop up.
|
||||||
|
ret none[@ty.t];
|
||||||
|
}
|
||||||
|
ret some[@ty.t](existing_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn record_local(ast.def_id id, @ty.t new_type) {
|
||||||
|
auto unified_type;
|
||||||
|
alt (fcx.locals.find(id)) {
|
||||||
|
case (none[@ty.t]) { unified_type = new_type; }
|
||||||
|
case (some[@ty.t](?old_type)) {
|
||||||
|
alt (with_params(fcx, old_type, new_type,
|
||||||
|
param_substs)) {
|
||||||
|
case (ty.ures_ok(?ut)) { unified_type = ut; }
|
||||||
|
case (_) { fail; /* FIXME */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fcx.locals.insert(id, unified_type);
|
||||||
|
}
|
||||||
|
fn record_param(uint index, @ty.t binding) -> ty.unify_result {
|
||||||
|
// Unify with the appropriate type in the parameter
|
||||||
|
// substitution list.
|
||||||
|
auto old_subst = param_substs.(index);
|
||||||
|
|
||||||
|
auto result = with_params(fcx, old_subst, binding,
|
||||||
|
param_substs);
|
||||||
|
alt (result) {
|
||||||
|
case (ty.ures_ok(?new_subst)) {
|
||||||
|
param_substs.(index) = new_subst;
|
||||||
|
ret ty.ures_ok(plain_ty(ty.ty_bound_param(index)));
|
||||||
|
}
|
||||||
|
case (_) { ret result; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto handler = unify_handler(fcx, param_substs);
|
||||||
|
ret ty.unify(expected, actual, handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tag autoderef_kind {
|
tag autoderef_kind {
|
||||||
AUTODEREF_OK;
|
AUTODEREF_OK;
|
||||||
NO_AUTODEREF;
|
NO_AUTODEREF;
|
||||||
@@ -919,51 +923,107 @@ fn count_boxes(@ty.t t) -> uint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn demand(&@fn_ctxt fcx, &span sp, @ty.t expected, @ty.t actual) -> @ty.t {
|
// Demands - procedures that require that two types unify and emit an error
|
||||||
be demand_full(fcx, sp, expected, actual, NO_AUTODEREF);
|
// message if they don't.
|
||||||
}
|
|
||||||
|
|
||||||
|
type ty_param_substs_and_ty = tup(vec[@ty.t], @ty.t);
|
||||||
|
|
||||||
// Requires that the two types unify, and prints an error message if they
|
mod Demand {
|
||||||
// don't. Returns the unified type.
|
fn simple(@fn_ctxt fcx, &span sp, @ty.t expected, @ty.t actual) -> @ty.t {
|
||||||
|
let vec[@ty.t] tps = vec();
|
||||||
fn demand_full(&@fn_ctxt fcx, &span sp,
|
ret full(fcx, sp, expected, actual, tps, NO_AUTODEREF)._1;
|
||||||
@ty.t expected, @ty.t actual, autoderef_kind adk) -> @ty.t {
|
|
||||||
|
|
||||||
auto expected_1 = expected;
|
|
||||||
auto actual_1 = actual;
|
|
||||||
auto implicit_boxes = 0u;
|
|
||||||
|
|
||||||
if (adk == AUTODEREF_OK) {
|
|
||||||
expected_1 = strip_boxes(expected);
|
|
||||||
actual_1 = strip_boxes(actual);
|
|
||||||
implicit_boxes = count_boxes(actual);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
alt (unify(fcx, expected_1, actual_1)) {
|
fn autoderef(@fn_ctxt fcx, &span sp, @ty.t expected, @ty.t actual,
|
||||||
case (ty.ures_ok(?t)) { ret add_boxes(implicit_boxes, t); }
|
autoderef_kind adk) -> @ty.t {
|
||||||
|
let vec[@ty.t] tps = vec();
|
||||||
|
ret full(fcx, sp, expected, actual, tps, adk)._1;
|
||||||
|
}
|
||||||
|
|
||||||
case (ty.ures_err(?err, ?expected, ?actual)) {
|
// Requires that the two types unify, and prints an error message if they
|
||||||
fcx.ccx.sess.span_err(sp, "mismatched types: expected "
|
// don't. Returns the unified type and the type parameter substitutions.
|
||||||
+ ty_to_str(expected) + " but found "
|
|
||||||
+ ty_to_str(actual) + " (" +
|
|
||||||
ty.type_err_to_str(err) + ")");
|
|
||||||
|
|
||||||
// TODO: In the future, try returning "expected", reporting the
|
fn full(@fn_ctxt fcx, &span sp, @ty.t expected, @ty.t actual,
|
||||||
// error, and continue.
|
vec[@ty.t] ty_param_substs_0, autoderef_kind adk)
|
||||||
fail;
|
-> ty_param_substs_and_ty {
|
||||||
|
|
||||||
|
auto expected_1 = expected;
|
||||||
|
auto actual_1 = actual;
|
||||||
|
auto implicit_boxes = 0u;
|
||||||
|
|
||||||
|
if (adk == AUTODEREF_OK) {
|
||||||
|
expected_1 = strip_boxes(expected_1);
|
||||||
|
actual_1 = strip_boxes(actual_1);
|
||||||
|
implicit_boxes = count_boxes(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
let vec[mutable @ty.t] ty_param_substs =
|
||||||
|
vec(mutable plain_ty(ty.ty_nil));
|
||||||
|
_vec.pop[mutable @ty.t](ty_param_substs); // FIXME: horrid botch
|
||||||
|
for (@ty.t ty_param_subst in ty_param_substs_0) {
|
||||||
|
ty_param_substs += vec(mutable ty_param_subst);
|
||||||
|
}
|
||||||
|
|
||||||
|
alt (Unify.with_params(fcx, expected_1, actual_1, ty_param_substs)) {
|
||||||
|
case (ty.ures_ok(?t)) {
|
||||||
|
// TODO: Use "freeze", when we have it.
|
||||||
|
let vec[@ty.t] result_ty_param_substs = vec();
|
||||||
|
for (mutable @ty.t ty_param_subst in ty_param_substs) {
|
||||||
|
result_ty_param_substs += vec(ty_param_subst);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret tup(result_ty_param_substs, add_boxes(implicit_boxes, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
case (ty.ures_err(?err, ?expected, ?actual)) {
|
||||||
|
fcx.ccx.sess.span_err(sp, "mismatched types: expected "
|
||||||
|
+ ty_to_str(expected) + " but found "
|
||||||
|
+ ty_to_str(actual) + " (" +
|
||||||
|
ty.type_err_to_str(err) + ")");
|
||||||
|
|
||||||
|
// TODO: In the future, try returning "expected", reporting
|
||||||
|
// the error, and continue.
|
||||||
|
fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns true if the two types unify and false if they don't.
|
// Returns true if the two types unify and false if they don't.
|
||||||
fn are_compatible(&@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> bool {
|
fn are_compatible(&@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> bool {
|
||||||
alt (unify(fcx, expected, actual)) {
|
alt (Unify.simple(fcx, expected, actual)) {
|
||||||
case (ty.ures_ok(_)) { ret true; }
|
case (ty.ures_ok(_)) { ret true; }
|
||||||
case (ty.ures_err(_, _, _)) { ret false; }
|
case (ty.ures_err(_, _, _)) { ret false; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the types of the arguments to a tag variant.
|
||||||
|
fn variant_arg_types(@crate_ctxt ccx, &span sp, ast.def_id vid,
|
||||||
|
vec[@ty.t] tag_ty_params) -> vec[@ty.t] {
|
||||||
|
auto ty_param_count = _vec.len[@ty.t](tag_ty_params);
|
||||||
|
|
||||||
|
let vec[@ty.t] result = vec();
|
||||||
|
|
||||||
|
auto tpt = ty.lookup_item_type(ccx.sess, ccx.type_cache, vid);
|
||||||
|
alt (tpt._1.struct) {
|
||||||
|
case (ty.ty_fn(_, ?ins, _)) {
|
||||||
|
// N-ary variant.
|
||||||
|
for (ty.arg arg in ins) {
|
||||||
|
auto arg_ty = bind_params_in_type(arg.ty);
|
||||||
|
arg_ty = substitute_ty_params(ccx, arg_ty, ty_param_count,
|
||||||
|
tag_ty_params, sp);
|
||||||
|
result += vec(arg_ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case (_) {
|
||||||
|
// Nullary variant. Do nothing, as there are no arguments.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// The "push-down" phase, which takes a typed grammar production and pushes
|
// The "push-down" phase, which takes a typed grammar production and pushes
|
||||||
// its type down into its constituent parts.
|
// its type down into its constituent parts.
|
||||||
@@ -992,83 +1052,51 @@ mod Pushdown {
|
|||||||
|
|
||||||
alt (pat.node) {
|
alt (pat.node) {
|
||||||
case (ast.pat_wild(?ann)) {
|
case (ast.pat_wild(?ann)) {
|
||||||
auto t = demand(fcx, pat.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, pat.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
p_1 = ast.pat_wild(ast.ann_type(t, none[vec[@ty.t]],
|
p_1 = ast.pat_wild(ast.ann_type(t, none[vec[@ty.t]],
|
||||||
none[@ts_ann]));
|
none[@ts_ann]));
|
||||||
}
|
}
|
||||||
case (ast.pat_lit(?lit, ?ann)) {
|
case (ast.pat_lit(?lit, ?ann)) {
|
||||||
auto t = demand(fcx, pat.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, pat.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
p_1 = ast.pat_lit(lit, ast.ann_type(t, none[vec[@ty.t]],
|
p_1 = ast.pat_lit(lit, ast.ann_type(t, none[vec[@ty.t]],
|
||||||
none[@ts_ann]));
|
none[@ts_ann]));
|
||||||
}
|
}
|
||||||
case (ast.pat_bind(?id, ?did, ?ann)) {
|
case (ast.pat_bind(?id, ?did, ?ann)) {
|
||||||
auto t = demand(fcx, pat.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, pat.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
fcx.locals.insert(did, t);
|
fcx.locals.insert(did, t);
|
||||||
p_1 = ast.pat_bind(id, did, ast.ann_type(t,
|
p_1 = ast.pat_bind(id, did, ast.ann_type(t,
|
||||||
none[vec[@ty.t]],
|
none[vec[@ty.t]],
|
||||||
none[@ts_ann]));
|
none[@ts_ann]));
|
||||||
}
|
}
|
||||||
case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) {
|
case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) {
|
||||||
auto t = demand(fcx, pat.span, expected, ann_to_type(ann));
|
// Take the variant's type parameters out of the expected
|
||||||
|
// type.
|
||||||
// FIXME: This is probably more convoluted than it has to be.
|
auto tag_tps;
|
||||||
// Refactor to use the type cache.
|
alt (expected.struct) {
|
||||||
|
case (ty.ty_tag(_, ?tps)) { tag_tps = tps; }
|
||||||
// Figure out the type parameters of the tag.
|
|
||||||
auto tag_id = option.get[ast.variant_def](vdef_opt)._0;
|
|
||||||
|
|
||||||
auto tpt = ty.lookup_item_type(fcx.ccx.sess,
|
|
||||||
fcx.ccx.type_cache, tag_id);
|
|
||||||
auto ty_params = tpt._0;
|
|
||||||
|
|
||||||
// Take the type parameters out of the expected type.
|
|
||||||
auto ty_param_substs;
|
|
||||||
alt (t.struct) {
|
|
||||||
case (ty.ty_tag(_, ?tps)) { ty_param_substs = tps; }
|
|
||||||
case (_) {
|
case (_) {
|
||||||
log "pushdown_pat(): expected type for tag pat " +
|
log "tag pattern type not actually a tag?!";
|
||||||
"isn't actually a tag?!";
|
|
||||||
fail;
|
fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto tps_opt = some[vec[@ty.t]](ty_param_substs);
|
|
||||||
|
|
||||||
// The type of the tag isn't enough; we also have to get the
|
|
||||||
// type of the variant, which is either a tag type in the case
|
|
||||||
// of nullary variants or a function type in the case of n-ary
|
|
||||||
// variants.
|
|
||||||
|
|
||||||
|
// Get the types of the arguments of the variant.
|
||||||
auto vdef = option.get[ast.variant_def](vdef_opt);
|
auto vdef = option.get[ast.variant_def](vdef_opt);
|
||||||
auto variant_ty = ty.lookup_item_type(fcx.ccx.sess,
|
auto arg_tys = variant_arg_types(fcx.ccx, pat.span, vdef._1,
|
||||||
fcx.ccx.type_cache,
|
tag_tps);
|
||||||
vdef._1)._1;
|
|
||||||
|
|
||||||
auto subpats_len = _vec.len[@ast.pat](subpats);
|
let vec[@ast.pat] subpats_1 = vec();
|
||||||
alt (variant_ty.struct) {
|
auto i = 0u;
|
||||||
case (ty.ty_tag(_, _)) {
|
for (@ast.pat subpat in subpats) {
|
||||||
// Nullary tag variant.
|
subpats_1 += vec(pushdown_pat(fcx, arg_tys.(i), subpat));
|
||||||
check (subpats_len == 0u);
|
i += 1u;
|
||||||
p_1 = ast.pat_tag(id, subpats, vdef_opt,
|
|
||||||
ast.ann_type(t, tps_opt,
|
|
||||||
none[@ts_ann]));
|
|
||||||
}
|
|
||||||
case (ty.ty_fn(_, ?args, ?tag_ty)) {
|
|
||||||
// N-ary tag variant.
|
|
||||||
let vec[@ast.pat] new_subpats = vec();
|
|
||||||
auto i = 0u;
|
|
||||||
for (arg a in args) {
|
|
||||||
auto subpat_ty = substitute_ty_params(fcx.ccx,
|
|
||||||
a.ty, ty_params, ty_param_substs, pat.span);
|
|
||||||
auto new_subpat = pushdown_pat(fcx, subpat_ty,
|
|
||||||
subpats.(i));
|
|
||||||
new_subpats += vec(new_subpat);
|
|
||||||
i += 1u;
|
|
||||||
}
|
|
||||||
p_1 = ast.pat_tag(id, new_subpats, vdef_opt,
|
|
||||||
ast.ann_type(tag_ty, tps_opt,
|
|
||||||
none[@ts_ann]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: push down type from "expected".
|
||||||
|
p_1 = ast.pat_tag(id, subpats_1, vdef_opt, ann);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1087,14 +1115,15 @@ mod Pushdown {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pushdown_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
|
fn pushdown_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
|
||||||
autoderef_kind adk) -> @ast.expr {
|
autoderef_kind adk) -> @ast.expr {
|
||||||
auto e_1;
|
auto e_1;
|
||||||
|
|
||||||
alt (e.node) {
|
alt (e.node) {
|
||||||
case (ast.expr_vec(?es_0, ?mut, ?ann)) {
|
case (ast.expr_vec(?es_0, ?mut, ?ann)) {
|
||||||
// TODO: enforce mutability
|
// TODO: enforce mutability
|
||||||
|
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
let vec[@ast.expr] es_1 = vec();
|
let vec[@ast.expr] es_1 = vec();
|
||||||
alt (t.struct) {
|
alt (t.struct) {
|
||||||
case (ty.ty_vec(?mt)) {
|
case (ty.ty_vec(?mt)) {
|
||||||
@@ -1110,7 +1139,8 @@ mod Pushdown {
|
|||||||
e_1 = ast.expr_vec(es_1, mut, triv_ann(t));
|
e_1 = ast.expr_vec(es_1, mut, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_tup(?es_0, ?ann)) {
|
case (ast.expr_tup(?es_0, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
let vec[ast.elt] elts_1 = vec();
|
let vec[ast.elt] elts_1 = vec();
|
||||||
alt (t.struct) {
|
alt (t.struct) {
|
||||||
case (ty.ty_tup(?mts)) {
|
case (ty.ty_tup(?mts)) {
|
||||||
@@ -1133,7 +1163,8 @@ mod Pushdown {
|
|||||||
|
|
||||||
auto base_1 = base_0;
|
auto base_1 = base_0;
|
||||||
|
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
let vec[ast.field] fields_1 = vec();
|
let vec[ast.field] fields_1 = vec();
|
||||||
alt (t.struct) {
|
alt (t.struct) {
|
||||||
case (ty.ty_rec(?field_mts)) {
|
case (ty.ty_rec(?field_mts)) {
|
||||||
@@ -1186,43 +1217,49 @@ mod Pushdown {
|
|||||||
e_1 = ast.expr_rec(fields_1, base_1, triv_ann(t));
|
e_1 = ast.expr_rec(fields_1, base_1, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_bind(?sube, ?es, ?ann)) {
|
case (ast.expr_bind(?sube, ?es, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_bind(sube, es, triv_ann(t));
|
e_1 = ast.expr_bind(sube, es, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_call(?sube, ?es, ?ann)) {
|
case (ast.expr_call(?sube, ?es, ?ann)) {
|
||||||
// NB: we call 'demand_full' and pass in adk only in cases
|
// NB: we call 'Demand.autoderef' and pass in adk only in
|
||||||
// where e is an expression that could *possibly* produce a
|
// cases where e is an expression that could *possibly*
|
||||||
// box; things like expr_binary or expr_bind can't, so there's
|
// produce a box; things like expr_binary or expr_bind can't,
|
||||||
// no need.
|
// so there's no need.
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
ann_to_type(ann), adk);
|
ann_to_type(ann), adk);
|
||||||
e_1 = ast.expr_call(sube, es, triv_ann(t));
|
e_1 = ast.expr_call(sube, es, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_self_method(?id, ?ann)) {
|
case (ast.expr_self_method(?id, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_self_method(id, triv_ann(t));
|
e_1 = ast.expr_self_method(id, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_binary(?bop, ?lhs, ?rhs, ?ann)) {
|
case (ast.expr_binary(?bop, ?lhs, ?rhs, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_binary(bop, lhs, rhs, triv_ann(t));
|
e_1 = ast.expr_binary(bop, lhs, rhs, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_unary(?uop, ?sube, ?ann)) {
|
case (ast.expr_unary(?uop, ?sube, ?ann)) {
|
||||||
// See note in expr_unary for why we're calling demand_full.
|
// See note in expr_unary for why we're calling
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
// Demand.autoderef.
|
||||||
ann_to_type(ann), adk);
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann), adk);
|
||||||
e_1 = ast.expr_unary(uop, sube, triv_ann(t));
|
e_1 = ast.expr_unary(uop, sube, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_lit(?lit, ?ann)) {
|
case (ast.expr_lit(?lit, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_lit(lit, triv_ann(t));
|
e_1 = ast.expr_lit(lit, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_cast(?sube, ?ast_ty, ?ann)) {
|
case (ast.expr_cast(?sube, ?ast_ty, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_cast(sube, ast_ty, triv_ann(t));
|
e_1 = ast.expr_cast(sube, ast_ty, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_if(?cond, ?then_0, ?else_0, ?ann)) {
|
case (ast.expr_if(?cond, ?then_0, ?else_0, ?ann)) {
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
ann_to_type(ann), adk);
|
ann_to_type(ann), adk);
|
||||||
auto then_1 = pushdown_block(fcx, expected, then_0);
|
auto then_1 = pushdown_block(fcx, expected, then_0);
|
||||||
|
|
||||||
auto else_1;
|
auto else_1;
|
||||||
@@ -1236,53 +1273,61 @@ mod Pushdown {
|
|||||||
e_1 = ast.expr_if(cond, then_1, else_1, triv_ann(t));
|
e_1 = ast.expr_if(cond, then_1, else_1, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_for(?decl, ?seq, ?bloc, ?ann)) {
|
case (ast.expr_for(?decl, ?seq, ?bloc, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_for(decl, seq, bloc, triv_ann(t));
|
e_1 = ast.expr_for(decl, seq, bloc, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_for_each(?decl, ?seq, ?bloc, ?ann)) {
|
case (ast.expr_for_each(?decl, ?seq, ?bloc, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_for_each(decl, seq, bloc, triv_ann(t));
|
e_1 = ast.expr_for_each(decl, seq, bloc, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_while(?cond, ?bloc, ?ann)) {
|
case (ast.expr_while(?cond, ?bloc, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_while(cond, bloc, triv_ann(t));
|
e_1 = ast.expr_while(cond, bloc, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_do_while(?bloc, ?cond, ?ann)) {
|
case (ast.expr_do_while(?bloc, ?cond, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_do_while(bloc, cond, triv_ann(t));
|
e_1 = ast.expr_do_while(bloc, cond, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_block(?bloc, ?ann)) {
|
case (ast.expr_block(?bloc, ?ann)) {
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
ann_to_type(ann), adk);
|
ann_to_type(ann), adk);
|
||||||
e_1 = ast.expr_block(bloc, triv_ann(t));
|
e_1 = ast.expr_block(bloc, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_assign(?lhs_0, ?rhs_0, ?ann)) {
|
case (ast.expr_assign(?lhs_0, ?rhs_0, ?ann)) {
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
ann_to_type(ann), adk);
|
ann_to_type(ann), adk);
|
||||||
auto lhs_1 = pushdown_expr(fcx, expected, lhs_0);
|
auto lhs_1 = pushdown_expr(fcx, expected, lhs_0);
|
||||||
auto rhs_1 = pushdown_expr(fcx, expected, rhs_0);
|
auto rhs_1 = pushdown_expr(fcx, expected, rhs_0);
|
||||||
e_1 = ast.expr_assign(lhs_1, rhs_1, triv_ann(t));
|
e_1 = ast.expr_assign(lhs_1, rhs_1, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_assign_op(?op, ?lhs_0, ?rhs_0, ?ann)) {
|
case (ast.expr_assign_op(?op, ?lhs_0, ?rhs_0, ?ann)) {
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
ann_to_type(ann), adk);
|
ann_to_type(ann), adk);
|
||||||
auto lhs_1 = pushdown_expr(fcx, expected, lhs_0);
|
auto lhs_1 = pushdown_expr(fcx, expected, lhs_0);
|
||||||
auto rhs_1 = pushdown_expr(fcx, expected, rhs_0);
|
auto rhs_1 = pushdown_expr(fcx, expected, rhs_0);
|
||||||
e_1 = ast.expr_assign_op(op, lhs_1, rhs_1, triv_ann(t));
|
e_1 = ast.expr_assign_op(op, lhs_1, rhs_1, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_field(?lhs, ?rhs, ?ann)) {
|
case (ast.expr_field(?lhs, ?rhs, ?ann)) {
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
ann_to_type(ann), adk);
|
ann_to_type(ann), adk);
|
||||||
e_1 = ast.expr_field(lhs, rhs, triv_ann(t));
|
e_1 = ast.expr_field(lhs, rhs, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_index(?base, ?index, ?ann)) {
|
case (ast.expr_index(?base, ?index, ?ann)) {
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
ann_to_type(ann), adk);
|
ann_to_type(ann), adk);
|
||||||
e_1 = ast.expr_index(base, index, triv_ann(t));
|
e_1 = ast.expr_index(base, index, triv_ann(t));
|
||||||
}
|
}
|
||||||
case (ast.expr_path(?pth, ?d, ?ann)) {
|
case (ast.expr_path(?pth, ?d, ?ann)) {
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto tp_substs_0 = ty.ann_to_type_params(ann);
|
||||||
ann_to_type(ann), adk);
|
auto t_0 = ann_to_type(ann);
|
||||||
|
|
||||||
|
auto result_0 = Demand.full(fcx, e.span, expected, t_0,
|
||||||
|
tp_substs_0, adk);
|
||||||
|
auto t = result_0._1;
|
||||||
|
|
||||||
// Fill in the type parameter substitutions if they weren't
|
// Fill in the type parameter substitutions if they weren't
|
||||||
// provided by the programmer.
|
// provided by the programmer.
|
||||||
@@ -1296,11 +1341,7 @@ mod Pushdown {
|
|||||||
case (ast.ann_type(_, ?tps_opt, _)) {
|
case (ast.ann_type(_, ?tps_opt, _)) {
|
||||||
alt (tps_opt) {
|
alt (tps_opt) {
|
||||||
case (none[vec[@ty.t]]) {
|
case (none[vec[@ty.t]]) {
|
||||||
auto defn = option.get[ast.def](d);
|
ty_params_opt = none[vec[@ty.t]];
|
||||||
auto tpt =
|
|
||||||
ty_param_count_and_ty_for_def(fcx, defn);
|
|
||||||
auto tps = ty.resolve_ty_params(tpt, t);
|
|
||||||
ty_params_opt = some[vec[@ty.t]](tps);
|
|
||||||
}
|
}
|
||||||
case (some[vec[@ty.t]](?tps)) {
|
case (some[vec[@ty.t]](?tps)) {
|
||||||
ty_params_opt = some[vec[@ty.t]](tps);
|
ty_params_opt = some[vec[@ty.t]](tps);
|
||||||
@@ -1314,8 +1355,8 @@ mod Pushdown {
|
|||||||
none[@ts_ann]));
|
none[@ts_ann]));
|
||||||
}
|
}
|
||||||
case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?ann)) {
|
case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?ann)) {
|
||||||
auto t = demand_full(fcx, e.span, expected,
|
auto t = Demand.autoderef(fcx, e.span, expected,
|
||||||
ann_to_type(ann), adk);
|
ann_to_type(ann), adk);
|
||||||
e_1 = ast.expr_ext(p, args, body, expanded, triv_ann(t));
|
e_1 = ast.expr_ext(p, args, body, expanded, triv_ann(t));
|
||||||
}
|
}
|
||||||
/* FIXME: should this check the type annotations? */
|
/* FIXME: should this check the type annotations? */
|
||||||
@@ -1329,12 +1370,14 @@ mod Pushdown {
|
|||||||
case (ast.expr_check_expr(_,_)) { e_1 = e.node; }
|
case (ast.expr_check_expr(_,_)) { e_1 = e.node; }
|
||||||
|
|
||||||
case (ast.expr_port(?ann)) {
|
case (ast.expr_port(?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
e_1 = ast.expr_port(triv_ann(t));
|
e_1 = ast.expr_port(triv_ann(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
case (ast.expr_chan(?es, ?ann)) {
|
case (ast.expr_chan(?es, ?ann)) {
|
||||||
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
|
auto t = Demand.simple(fcx, e.span, expected,
|
||||||
|
ann_to_type(ann));
|
||||||
let @ast.expr es_1;
|
let @ast.expr es_1;
|
||||||
alt (t.struct) {
|
alt (t.struct) {
|
||||||
case (ty.ty_chan(?subty)) {
|
case (ty.ty_chan(?subty)) {
|
||||||
@@ -1354,7 +1397,7 @@ mod Pushdown {
|
|||||||
let vec[ast.arm] arms_1 = vec();
|
let vec[ast.arm] arms_1 = vec();
|
||||||
for (ast.arm arm_0 in arms_0) {
|
for (ast.arm arm_0 in arms_0) {
|
||||||
auto block_1 = pushdown_block(fcx, expected, arm_0.block);
|
auto block_1 = pushdown_block(fcx, expected, arm_0.block);
|
||||||
t = demand(fcx, e.span, t, block_ty(block_1));
|
t = Demand.simple(fcx, e.span, t, block_ty(block_1));
|
||||||
auto arm_1 = rec(pat=arm_0.pat, block=block_1,
|
auto arm_1 = rec(pat=arm_0.pat, block=block_1,
|
||||||
index=arm_0.index);
|
index=arm_0.index);
|
||||||
arms_1 += vec(arm_1);
|
arms_1 += vec(arm_1);
|
||||||
@@ -1404,7 +1447,7 @@ mod Pushdown {
|
|||||||
ret fold.respan[ast.block_](bloc.span, block_);
|
ret fold.respan[ast.block_](bloc.span, block_);
|
||||||
}
|
}
|
||||||
case (none[@ast.expr]) {
|
case (none[@ast.expr]) {
|
||||||
demand(fcx, bloc.span, expected, plain_ty(ty.ty_nil));
|
Demand.simple(fcx, bloc.span, expected, plain_ty(ty.ty_nil));
|
||||||
ret bloc;
|
ret bloc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1443,14 +1486,14 @@ fn resolve_local_types_in_annotation(&option.t[@fn_ctxt] env, ast.ann ann)
|
|||||||
|
|
||||||
auto fcx = option.get[@fn_ctxt](env);
|
auto fcx = option.get[@fn_ctxt](env);
|
||||||
alt (ann) {
|
alt (ann) {
|
||||||
case (ast.ann_none) {
|
case (ast.ann_none) {
|
||||||
log "warning: no type for expression";
|
log "warning: no type for expression";
|
||||||
ret ann;
|
ret ann;
|
||||||
}
|
}
|
||||||
case (ast.ann_type(?typ, ?tps, ?ts_info)) {
|
case (ast.ann_type(?typ, ?tps, ?ts_info)) {
|
||||||
auto new_type = ty.fold_ty(folder(fcx), ann_to_type(ann));
|
auto new_type = ty.fold_ty(folder(fcx), ann_to_type(ann));
|
||||||
ret ast.ann_type(new_type, tps, ts_info);
|
ret ast.ann_type(new_type, tps, ts_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1623,42 +1666,13 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unify and write back to the function.
|
// Unify the callee and arguments.
|
||||||
auto f_1 = Pushdown.pushdown_expr(fcx, t_0, f_0);
|
auto tpt_0 = ty.expr_ty_params_and_ty(f_0);
|
||||||
|
auto tpt_1 = Demand.full(fcx, f.span, tpt_0._1, t_0, tpt_0._0,
|
||||||
|
NO_AUTODEREF);
|
||||||
|
auto f_1 = ty.replace_expr_type(f_0, tpt_1);
|
||||||
|
|
||||||
// Take the argument types out of the resulting function type.
|
ret tup(f_1, args_0);
|
||||||
auto t_1 = expr_ty(f_1);
|
|
||||||
|
|
||||||
if (!ty.is_fn_ty(t_1)) {
|
|
||||||
fcx.ccx.sess.span_err(f_1.span,
|
|
||||||
"mismatched types: callee has " +
|
|
||||||
"non-function type: " +
|
|
||||||
ty_to_str(t_1));
|
|
||||||
}
|
|
||||||
|
|
||||||
let vec[arg] arg_tys_1 = ty.ty_fn_args(t_1);
|
|
||||||
let @ty.t rt_1 = ty.ty_fn_ret(t_1);
|
|
||||||
|
|
||||||
// Unify and write back to the arguments.
|
|
||||||
auto i = 0u;
|
|
||||||
let vec[option.t[@ast.expr]] args_1 = vec();
|
|
||||||
while (i < _vec.len[option.t[@ast.expr]](args_0)) {
|
|
||||||
alt (args_0.(i)) {
|
|
||||||
case (some[@ast.expr](?e_0)) {
|
|
||||||
auto arg_ty_1 = arg_tys_1.(i);
|
|
||||||
auto e_1 = Pushdown.pushdown_expr(fcx, arg_ty_1.ty, e_0);
|
|
||||||
_vec.push[option.t[@ast.expr]](args_1,
|
|
||||||
some[@ast.expr](e_1));
|
|
||||||
}
|
|
||||||
case (none[@ast.expr]) {
|
|
||||||
_vec.push[option.t[@ast.expr]](args_1, none[@ast.expr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i += 1u;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret tup(f_1, args_1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A generic function for checking assignment expressions
|
// A generic function for checking assignment expressions
|
||||||
@@ -1767,10 +1781,25 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
|||||||
auto t = plain_ty(ty.ty_nil);
|
auto t = plain_ty(ty.ty_nil);
|
||||||
check (defopt != none[ast.def]);
|
check (defopt != none[ast.def]);
|
||||||
auto defn = option.get[ast.def](defopt);
|
auto defn = option.get[ast.def](defopt);
|
||||||
|
|
||||||
auto tpt = ty_param_count_and_ty_for_def(fcx, defn);
|
auto tpt = ty_param_count_and_ty_for_def(fcx, defn);
|
||||||
auto ann = instantiate_path(fcx, pth, tpt, expr.span);
|
|
||||||
ret @fold.respan[ast.expr_](expr.span,
|
if (ty.def_has_ty_params(defn)) {
|
||||||
ast.expr_path(pth, defopt, ann));
|
auto ann = instantiate_path(fcx, pth, tpt, expr.span);
|
||||||
|
ret @fold.respan[ast.expr_](expr.span,
|
||||||
|
ast.expr_path(pth, defopt, ann));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The definition doesn't take type parameters. If the programmer
|
||||||
|
// supplied some, that's an error.
|
||||||
|
if (_vec.len[@ast.ty](pth.node.types) > 0u) {
|
||||||
|
fcx.ccx.sess.span_err(expr.span, "this kind of value does " +
|
||||||
|
"not take type parameters");
|
||||||
|
fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto e = ast.expr_path(pth, defopt, triv_ann(tpt._1));
|
||||||
|
ret @fold.respan[ast.expr_](expr.span, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
case (ast.expr_ext(?p, ?args, ?body, ?expanded, _)) {
|
case (ast.expr_ext(?p, ?args, ?body, ?expanded, _)) {
|
||||||
@@ -1863,7 +1892,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
|||||||
|
|
||||||
case (ast.expr_check_expr(?e, _)) {
|
case (ast.expr_check_expr(?e, _)) {
|
||||||
auto expr_t = check_expr(fcx, e);
|
auto expr_t = check_expr(fcx, e);
|
||||||
demand(fcx, expr.span, plain_ty(ty.ty_bool), expr_ty(expr_t));
|
Demand.simple(fcx, expr.span, plain_ty(ty.ty_bool),
|
||||||
|
expr_ty(expr_t));
|
||||||
ret @fold.respan[ast.expr_]
|
ret @fold.respan[ast.expr_]
|
||||||
(expr.span, ast.expr_check_expr(expr_t, boring_ann()));
|
(expr.span, ast.expr_check_expr(expr_t, boring_ann()));
|
||||||
}
|
}
|
||||||
@@ -2020,8 +2050,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
|||||||
let vec[@ast.pat] pats_0 = vec();
|
let vec[@ast.pat] pats_0 = vec();
|
||||||
for (ast.arm arm in arms) {
|
for (ast.arm arm in arms) {
|
||||||
auto pat_0 = check_pat(fcx, arm.pat);
|
auto pat_0 = check_pat(fcx, arm.pat);
|
||||||
pattern_ty = demand(fcx, pat_0.span, pattern_ty,
|
pattern_ty = Demand.simple(fcx, pat_0.span, pattern_ty,
|
||||||
pat_ty(pat_0));
|
pat_ty(pat_0));
|
||||||
pats_0 += vec(pat_0);
|
pats_0 += vec(pat_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2036,8 +2066,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
|||||||
let vec[ast.block] blocks_0 = vec();
|
let vec[ast.block] blocks_0 = vec();
|
||||||
for (ast.arm arm in arms) {
|
for (ast.arm arm in arms) {
|
||||||
auto block_0 = check_block(fcx, arm.block);
|
auto block_0 = check_block(fcx, arm.block);
|
||||||
result_ty = demand(fcx, block_0.span, result_ty,
|
result_ty = Demand.simple(fcx, block_0.span, result_ty,
|
||||||
block_ty(block_0));
|
block_ty(block_0));
|
||||||
blocks_0 += vec(block_0);
|
blocks_0 += vec(block_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2232,7 +2262,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
|||||||
for (@ast.expr e in args) {
|
for (@ast.expr e in args) {
|
||||||
auto expr_1 = check_expr(fcx, e);
|
auto expr_1 = check_expr(fcx, e);
|
||||||
auto expr_t = expr_ty(expr_1);
|
auto expr_t = expr_ty(expr_1);
|
||||||
demand(fcx, expr.span, t, expr_t);
|
Demand.simple(fcx, expr.span, t, expr_t);
|
||||||
_vec.push[@ast.expr](args_1,expr_1);
|
_vec.push[@ast.expr](args_1,expr_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2310,7 +2340,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
|||||||
auto found = false;
|
auto found = false;
|
||||||
for (ty.field bf in base_fields) {
|
for (ty.field bf in base_fields) {
|
||||||
if (_str.eq(f.ident, bf.ident)) {
|
if (_str.eq(f.ident, bf.ident)) {
|
||||||
demand(fcx, expr.span, f.mt.ty, bf.mt.ty);
|
Demand.simple(fcx, expr.span, f.mt.ty,
|
||||||
|
bf.mt.ty);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2378,9 +2409,9 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case (_) {
|
case (_) {
|
||||||
fcx.ccx.sess.unimpl("base type for expr_field "
|
fcx.ccx.sess.span_unimpl(expr.span,
|
||||||
+ "in typeck.check_expr: "
|
"base type for expr_field in typeck.check_expr: " +
|
||||||
+ ty_to_str(base_t));
|
ty_to_str(base_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2512,6 +2543,7 @@ fn check_decl_local(&@fn_ctxt fcx, &@ast.decl decl) -> @ast.decl {
|
|||||||
expr_0);
|
expr_0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto init_0 = rec(expr = expr_1 with init);
|
auto init_0 = rec(expr = expr_1 with init);
|
||||||
initopt = some[ast.initializer](init_0);
|
initopt = some[ast.initializer](init_0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,15 @@ fn expr_to_str(&@ast.expr e) -> str {
|
|||||||
ret writer.get_str();
|
ret writer.get_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pat_to_str(&@ast.pat p) -> str {
|
||||||
|
auto writer = io.string_writer();
|
||||||
|
auto s = @rec(s=pp.mkstate(writer.get_writer(), 78u),
|
||||||
|
comments=option.none[vec[lexer.cmnt]],
|
||||||
|
mutable cur_cmnt=0u);
|
||||||
|
print_pat(s, p);
|
||||||
|
ret writer.get_str();
|
||||||
|
}
|
||||||
|
|
||||||
impure fn hbox(ps s) {
|
impure fn hbox(ps s) {
|
||||||
pp.hbox(s.s, indent_unit);
|
pp.hbox(s.s, indent_unit);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,6 +252,23 @@ rust_task::start(uintptr_t exit_task_glue,
|
|||||||
transition(&dom->newborn_tasks, &dom->running_tasks);
|
transition(&dom->newborn_tasks, &dom->running_tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void
|
||||||
|
rust_task::print_stack_trace()
|
||||||
|
{
|
||||||
|
void *addrs[256];
|
||||||
|
uintptr_t sp = this->rust_sp;
|
||||||
|
|
||||||
|
// We need to be careful to not use any Rust stack space here, since this
|
||||||
|
// may be called on stack overflow.
|
||||||
|
asm("xchgl %0, %%esp\n"
|
||||||
|
"pushl $256\n"
|
||||||
|
"pushl %1\n"
|
||||||
|
"calll %3\n"
|
||||||
|
"xchgl %%esp, %0\n"
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
rust_task::grow(size_t n_frame_bytes)
|
rust_task::grow(size_t n_frame_bytes)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user