Skip to content

Commit 5955e23

Browse files
committed
Typecheck assignment exprs, redo decl checking, propagate ty_vars. Enable another test.
1 parent 79a3811 commit 5955e23

File tree

2 files changed

+97
-53
lines changed

2 files changed

+97
-53
lines changed

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ TEST_XFAILS_SELF := $(filter-out \
525525
hello.rs \
526526
int.rs \
527527
item-name-overload.rs \
528+
lazy-init.rs \
528529
multiline-comment.rs \
529530
), \
530531
$(wildcard test/*/*.rs test/*/*.rc))

src/comp/middle/typeck.rs

Lines changed: 96 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import std.option.some;
1717
type ty_table = hashmap[ast.def_id, @ty];
1818
type env = rec(session.session sess,
1919
@ty_table item_types,
20+
hashmap[int,@ty] bindings,
2021
mutable int next_var_id);
2122

2223
type arg = rec(ast.mode mode, @ty ty);
@@ -245,6 +246,7 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty {
245246
// ast_ty_to_ty.
246247
fn ast_ty_to_ty_env(@env e, &@ast.ty ast_ty) -> @ty {
247248
fn getter(@env e, ast.def_id id) -> @ty {
249+
check (e.item_types.contains_key(id));
248250
ret e.item_types.get(id);
249251
}
250252
auto f = bind getter(e, _);
@@ -285,6 +287,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) {
285287
fn trans_ty_item_id_to_ty(@hashmap[ast.def_id,@ast.item] id_to_ty_item,
286288
@ty_table item_to_ty,
287289
ast.def_id id) -> @ty {
290+
check (id_to_ty_item.contains_key(id));
288291
auto item = id_to_ty_item.get(id);
289292
ret trans_ty_item_to_ty(id_to_ty_item, item_to_ty, item);
290293
}
@@ -317,6 +320,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) {
317320
case (ast.item_ty(?ident, ?referent_ty, ?def_id, _)) {
318321
if (item_to_ty.contains_key(def_id)) {
319322
// Avoid repeating work.
323+
check (item_to_ty.contains_key(def_id));
320324
ret item_to_ty.get(def_id);
321325
}
322326

@@ -423,7 +427,7 @@ fn type_of(@ast.expr expr) -> @ty {
423427

424428
// Type unification
425429

426-
fn unify(@ty expected, @ty actual) -> unify_result {
430+
fn unify(&@env e, @ty expected, @ty actual) -> unify_result {
427431
// Wraps the given type in an appropriate cname.
428432
//
429433
// TODO: This doesn't do anything yet. We should carry the cname up from
@@ -440,7 +444,7 @@ fn unify(@ty expected, @ty actual) -> unify_result {
440444
ret ures_err(terr_mismatch, expected, actual);
441445
}
442446

443-
fn unify_step(@ty expected, @ty actual, &hashmap[int,@ty] bindings)
447+
fn unify_step(&@env e, @ty expected, @ty actual)
444448
-> unify_result {
445449
// TODO: rewrite this using tuple pattern matching when available, to
446450
// avoid all this rightward drift and spikiness.
@@ -456,8 +460,7 @@ fn unify(@ty expected, @ty actual) -> unify_result {
456460
case (ty_box(?expected_sub)) {
457461
alt (actual.struct) {
458462
case (ty_box(?actual_sub)) {
459-
auto result = unify_step(expected_sub, actual_sub,
460-
bindings);
463+
auto result = unify_step(e, expected_sub, actual_sub);
461464
alt (result) {
462465
case (ures_ok(?result_sub)) {
463466
ret ures_ok(plain_ty(ty_box(result_sub)));
@@ -479,8 +482,7 @@ fn unify(@ty expected, @ty actual) -> unify_result {
479482
case (ty_vec(?expected_sub)) {
480483
alt (actual.struct) {
481484
case (ty_vec(?actual_sub)) {
482-
auto result = unify_step(expected_sub, actual_sub,
483-
bindings);
485+
auto result = unify_step(e, expected_sub, actual_sub);
484486
alt (result) {
485487
case (ures_ok(?result_sub)) {
486488
ret ures_ok(plain_ty(ty_vec(result_sub)));
@@ -524,9 +526,8 @@ fn unify(@ty expected, @ty actual) -> unify_result {
524526
ret ures_err(err, expected, actual);
525527
}
526528

527-
auto result = unify_step(expected_elem._1,
528-
actual_elem._1,
529-
bindings);
529+
auto result = unify_step(e, expected_elem._1,
530+
actual_elem._1);
530531
alt (result) {
531532
case (ures_ok(?rty)) {
532533
result_elems += vec(tup(expected_elem._0,
@@ -576,9 +577,8 @@ fn unify(@ty expected, @ty actual) -> unify_result {
576577
result_mode = ast.val;
577578
}
578579

579-
auto result = unify_step(expected_input.ty,
580-
actual_input.ty,
581-
bindings);
580+
auto result = unify_step(e, expected_input.ty,
581+
actual_input.ty);
582582

583583
alt (result) {
584584
case (ures_ok(?rty)) {
@@ -596,8 +596,8 @@ fn unify(@ty expected, @ty actual) -> unify_result {
596596

597597
// Check the output.
598598
auto result_out;
599-
auto result = unify_step(expected_output,
600-
actual_output, bindings);
599+
auto result = unify_step(e, expected_output,
600+
actual_output);
601601
alt (result) {
602602
case (ures_ok(?rty)) {
603603
result_out = rty;
@@ -618,12 +618,13 @@ fn unify(@ty expected, @ty actual) -> unify_result {
618618
}
619619

620620
case (ty_var(?expected_id)) {
621-
if (bindings.contains_key(expected_id)) {
622-
auto binding = bindings.get(expected_id);
623-
ret unify_step(binding, actual, bindings);
621+
if (e.bindings.contains_key(expected_id)) {
622+
check (e.bindings.contains_key(expected_id));
623+
auto binding = e.bindings.get(expected_id);
624+
ret unify_step(e, binding, actual);
624625
}
625626

626-
bindings.insert(expected_id, actual);
627+
e.bindings.insert(expected_id, actual);
627628
ret ures_ok(actual);
628629
}
629630
}
@@ -632,19 +633,13 @@ fn unify(@ty expected, @ty actual) -> unify_result {
632633
fail;
633634
}
634635

635-
fn hash_int(&int x) -> uint { ret x as uint; }
636-
fn eq_int(&int a, &int b) -> bool { ret a == b; }
637-
auto hasher = hash_int;
638-
auto eqer = eq_int;
639-
auto bindings = map.mk_hashmap[int,@ty](hasher, eqer);
640-
641-
ret unify_step(expected, actual, bindings);
636+
ret unify_step(e, expected, actual);
642637
}
643638

644639
// Requires that the two types unify, and prints an error message if they
645640
// don't. Returns the unified type.
646641
fn demand(&@env e, &span sp, @ty expected, @ty actual) -> @ty {
647-
alt (unify(expected, actual)) {
642+
alt (unify(e, expected, actual)) {
648643
case (ures_ok(?ty)) {
649644
ret ty;
650645
}
@@ -666,30 +661,45 @@ fn demand(&@env e, &span sp, @ty expected, @ty actual) -> @ty {
666661
// with the previously-stored type for this local.
667662
fn demand_local(&@env e, &span sp, &@ty_table locals, ast.def_id local_id,
668663
@ty t) {
664+
check (locals.contains_key(local_id));
669665
auto prev_ty = locals.get(local_id);
670666
auto unified_ty = demand(e, sp, prev_ty, t);
671667
locals.insert(local_id, unified_ty);
672668
}
673669

674670
// Returns true if the two types unify and false if they don't.
675-
fn are_compatible(@ty expected, @ty actual) -> bool {
676-
alt (unify(expected, actual)) {
671+
fn are_compatible(&@env e, @ty expected, @ty actual) -> bool {
672+
alt (unify(e, expected, actual)) {
677673
case (ures_ok(_)) { ret true; }
678674
case (ures_err(_, _, _)) { ret false; }
679675
}
680676
}
681677

682678
// Writeback: the phase that writes inferred types back into the AST.
683679

684-
fn writeback_local(&@ty_table locals, &span sp, @ast.local local)
680+
fn resolve_vars(@env e, @ty t) -> @ty {
681+
alt (t.struct) {
682+
case (ty_var(?v)) {
683+
check (e.bindings.contains_key(v));
684+
ret resolve_vars(e, e.bindings.get(v));
685+
}
686+
}
687+
ret t;
688+
}
689+
690+
fn writeback_local(@env e, &@ty_table locals, &span sp, @ast.local local)
685691
-> @ast.decl {
686-
auto local_wb = @rec(ann=ast.ann_type(locals.get(local.id)) with *local);
692+
if (!locals.contains_key(local.id)) {
693+
e.sess.err("unable to determine type of local: " + local.ident);
694+
}
695+
auto local_ty = resolve_vars(e, locals.get(local.id));
696+
auto local_wb = @rec(ann=ast.ann_type(local_ty) with *local);
687697
ret @fold.respan[ast.decl_](sp, ast.decl_local(local_wb));
688698
}
689699

690700
fn writeback(&@env e, &@ty_table locals, &ast.block block) -> ast.block {
691701
auto fld = fold.new_identity_fold[@ty_table]();
692-
auto f = writeback_local; // FIXME: trans_const_lval bug
702+
auto f = bind writeback_local(e, _, _, _);
693703
fld = @rec(fold_decl_local = f with *fld);
694704
ret fold.fold_block[@ty_table](locals, fld, block);
695705
}
@@ -753,8 +763,14 @@ fn check_expr(&@env e, &@ty_table locals, @ast.expr expr) -> @ast.expr {
753763
case (ast.expr_name(?name, ?defopt, _)) {
754764
auto ty = @rec(struct=ty_nil, cname=none[str]);
755765
alt (option.get[ast.def](defopt)) {
756-
case (ast.def_arg(?id)) { ty = locals.get(id); }
757-
case (ast.def_local(?id)) { ty = locals.get(id); }
766+
case (ast.def_arg(?id)) {
767+
check (locals.contains_key(id));
768+
ty = locals.get(id);
769+
}
770+
case (ast.def_local(?id)) {
771+
check (locals.contains_key(id));
772+
ty = locals.get(id);
773+
}
758774
case (_) {
759775
// FIXME: handle other names.
760776
e.sess.unimpl("definition variant for: "
@@ -767,6 +783,17 @@ fn check_expr(&@env e, &@ty_table locals, @ast.expr expr) -> @ast.expr {
767783
ast.ann_type(ty)));
768784
}
769785

786+
case (ast.expr_assign(?lhs, ?rhs, _)) {
787+
auto lhs_1 = check_expr(e, locals, lhs);
788+
auto rhs_1 = check_expr(e, locals, rhs);
789+
auto lhs_t = type_of(lhs_1);
790+
auto rhs_t = type_of(rhs_1);
791+
demand(e, expr.span, lhs_t, rhs_t);
792+
ret @fold.respan[ast.expr_](expr.span,
793+
ast.expr_assign(lhs_1, rhs_1,
794+
ast.ann_type(rhs_t)));
795+
}
796+
770797
case (_) {
771798
// TODO
772799
ret expr;
@@ -780,29 +807,36 @@ fn check_stmt(@env e, @ty_table locals, @ty ret_ty, &@ast.stmt stmt)
780807
case (ast.stmt_decl(?decl)) {
781808
alt (decl.node) {
782809
case (ast.decl_local(?local)) {
783-
alt (local.init) {
784-
case (none[@ast.expr]) {
785-
// empty
810+
811+
auto local_ty;
812+
alt (local.ty) {
813+
case (none[@ast.ty]) {
814+
// Auto slot. Assign a ty_var.
815+
local_ty = plain_ty(ty_var(e.next_var_id));
816+
e.next_var_id += 1;
817+
}
818+
819+
case (some[@ast.ty](?ast_ty)) {
820+
local_ty = ast_ty_to_ty_env(e, ast_ty);
786821
}
822+
}
823+
locals.insert(local.id, local_ty);
787824

825+
auto rhs_ty = local_ty;
826+
auto init = local.init;
827+
alt (local.init) {
788828
case (some[@ast.expr](?expr)) {
789829
auto expr_t = check_expr(e, locals, expr);
790-
locals.insert(local.id, type_of(expr_t));
791-
792-
alt (local.ty) {
793-
case (none[@ast.ty]) {
794-
// Nothing to do. We'll figure out the
795-
// type later.
796-
}
797-
798-
case (some[@ast.ty](?ast_ty)) {
799-
auto ty = ast_ty_to_ty_env(e, ast_ty);
800-
demand_local(e, decl.span, locals,
801-
local.id, ty);
802-
}
803-
}
830+
rhs_ty = type_of(expr_t);
831+
init = some[@ast.expr](expr_t);
804832
}
805833
}
834+
demand(e, decl.span, local_ty, rhs_ty);
835+
auto local_1 = @rec(init = init with *local);
836+
auto decl_1 = @rec(node=ast.decl_local(local_1)
837+
with *decl);
838+
ret @fold.respan[ast.stmt_](stmt.span,
839+
ast.stmt_decl(decl_1));
806840
}
807841

808842
case (ast.decl_item(_)) {
@@ -816,7 +850,7 @@ fn check_stmt(@env e, @ty_table locals, @ty ret_ty, &@ast.stmt stmt)
816850
case (ast.stmt_ret(?expr_opt)) {
817851
alt (expr_opt) {
818852
case (none[@ast.expr]) {
819-
if (!are_compatible(ret_ty, plain_ty(ty_nil))) {
853+
if (!are_compatible(e, ret_ty, plain_ty(ty_nil))) {
820854
e.sess.err("ret; in function returning non-void");
821855
}
822856

@@ -846,7 +880,7 @@ fn check_stmt(@env e, @ty_table locals, @ty ret_ty, &@ast.stmt stmt)
846880

847881
case (ast.stmt_expr(?expr)) {
848882
auto expr_t = check_expr(e, locals, expr);
849-
if (!are_compatible(type_of(expr_t), plain_ty(ty_nil))) {
883+
if (!are_compatible(e, type_of(expr_t), plain_ty(ty_nil))) {
850884
// TODO: real warning function
851885
log "warning: expression used as statement should have " +
852886
"void type";
@@ -891,7 +925,16 @@ fn check_fn(&@env e, &span sp, ast.ident ident, &ast._fn f, ast.def_id id,
891925

892926
fn check_crate(session.session sess, @ast.crate crate) -> @ast.crate {
893927
auto result = collect_item_types(crate);
894-
auto e = @rec(sess=sess, item_types=result._1, mutable next_var_id=0);
928+
929+
fn hash_int(&int x) -> uint { ret x as uint; }
930+
fn eq_int(&int a, &int b) -> bool { ret a == b; }
931+
auto hasher = hash_int;
932+
auto eqer = eq_int;
933+
934+
auto e = @rec(sess=sess,
935+
item_types=result._1,
936+
bindings = map.mk_hashmap[int,@ty](hasher, eqer),
937+
mutable next_var_id=0);
895938

896939
auto fld = fold.new_identity_fold[@env]();
897940
auto f = check_fn; // FIXME: trans_const_lval bug

0 commit comments

Comments
 (0)