Skip to content

Commit 77ff12c

Browse files
committed
rustboot: Don't use walk to traverse statements in type.ml; fixes redundant checking, improves diagnostics. Also report untyped slots.
1 parent 26ecec4 commit 77ff12c

File tree

6 files changed

+69
-54
lines changed

6 files changed

+69
-54
lines changed

src/boot/me/type.ml

Lines changed: 59 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ type ty_pat =
2020
type fn_ctx = {
2121
fnctx_return_type: Ast.ty;
2222
fnctx_is_iter: bool;
23-
mutable fnctx_just_saw_ret: bool
23+
mutable fnctx_just_saw_ret: bool;
24+
fnctx_blocks: Common.node_id Stack.t;
25+
fnctx_slot_decls: (Ast.slot_key,Common.node_id) Hashtbl.t;
2426
}
2527

2628
exception Type_error of string * string
@@ -188,7 +190,7 @@ let type_error cx expected actual =
188190

189191
(* We explicitly curry [cx] like this to avoid threading it through all the
190192
* inner functions. *)
191-
let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
193+
let check_block (cx:Semant.ctxt) : (fn_ctx -> Ast.block -> unit) =
192194
let pretty_ty_str = Semant.pretty_ty_str cx (Ast.sprintf_ty ()) in
193195

194196
(* Returns the part of the type that matters for typechecking. *)
@@ -894,7 +896,7 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
894896

895897
(* Again as above, we explicitly curry [fn_ctx] to avoid threading it
896898
* through these functions. *)
897-
let check_stmt (fn_ctx:fn_ctx) : (Ast.stmt -> unit) =
899+
let check_block (fn_ctx:fn_ctx) : (Ast.block -> unit) =
898900
let check_ret (stmt:Ast.stmt) : unit =
899901
fn_ctx.fnctx_just_saw_ret <-
900902
match stmt.Common.node with
@@ -904,7 +906,8 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
904906
in
905907

906908
let rec check_block (block:Ast.block) : unit =
907-
Array.iter check_stmt block.Common.node
909+
Stack.push block.Common.id fn_ctx.fnctx_blocks;
910+
Array.iter check_stmt' block.Common.node
908911

909912
and check_stmt (stmt:Ast.stmt) : unit =
910913
check_ret stmt;
@@ -1050,7 +1053,7 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
10501053

10511054
| Ast.STMT_while w | Ast.STMT_do_while w ->
10521055
let (stmts, expr) = w.Ast.while_lval in
1053-
Array.iter check_stmt stmts;
1056+
Array.iter check_stmt' stmts;
10541057
demand Ast.TY_bool (check_expr expr);
10551058
check_block w.Ast.while_body
10561059

@@ -1098,7 +1101,10 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
10981101
let get_pat arm = fst arm.Common.node in
10991102
let pats = Array.map get_pat alt_tag.Ast.alt_tag_arms in
11001103
let ty = check_lval alt_tag.Ast.alt_tag_lval in
1101-
Array.iter (check_pat ty) pats
1104+
let get_block arm = snd arm.Common.node in
1105+
let blocks = Array.map get_block alt_tag.Ast.alt_tag_arms in
1106+
Array.iter (check_pat ty) pats;
1107+
Array.iter check_block blocks
11021108

11031109
| Ast.STMT_alt_type _ -> () (* TODO *)
11041110

@@ -1132,10 +1138,12 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
11321138

11331139
| Ast.STMT_block block -> check_block block
11341140

1135-
| Ast.STMT_decl _ -> () (* always well-typed *)
1136-
in
1141+
| Ast.STMT_decl (Ast.DECL_slot (slot_key, _)) ->
1142+
Hashtbl.add fn_ctx.fnctx_slot_decls slot_key stmt.Common.id
1143+
1144+
| Ast.STMT_decl (Ast.DECL_mod_item _) -> () (* always well-typed *)
11371145

1138-
let check_stmt' stmt =
1146+
and check_stmt' stmt =
11391147
try
11401148
check_stmt stmt
11411149
with Type_error (expected, actual) ->
@@ -1145,9 +1153,9 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
11451153
expected
11461154
actual
11471155
in
1148-
check_stmt'
1156+
check_block
11491157
in
1150-
check_stmt
1158+
check_block
11511159

11521160
let create_tag_graph_nodes (cx:Semant.ctxt) =
11531161
let make_graph_node id _ =
@@ -1259,8 +1267,6 @@ let check_for_tag_cycles (cx:Semant.ctxt) =
12591267
Hashtbl.iter check_node cx.Semant.ctxt_tag_containment
12601268

12611269
let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
1262-
let fn_ctx_stack = Stack.create () in
1263-
12641270
(* Verify that, if main is present, it has the right form. *)
12651271
let verify_main (item_id:Common.node_id) : unit =
12661272
let path_name = Hashtbl.find cx.Semant.ctxt_all_item_names item_id in
@@ -1284,28 +1290,43 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
12841290
in
12851291

12861292
let visitor (cx:Semant.ctxt) (inner:Walk.visitor) : Walk.visitor =
1287-
let push_fn_ctx (ret_ty:Ast.ty) (is_iter:bool) =
1288-
let fn_ctx = {
1293+
let create_fn_ctx (ret_ty:Ast.ty) (is_iter:bool) =
1294+
{
12891295
fnctx_return_type = ret_ty;
12901296
fnctx_is_iter = is_iter;
1291-
fnctx_just_saw_ret = false
1292-
} in
1293-
Stack.push fn_ctx fn_ctx_stack
1297+
fnctx_just_saw_ret = false;
1298+
fnctx_blocks = Stack.create ();
1299+
fnctx_slot_decls = Hashtbl.create 0;
1300+
}
12941301
in
12951302

1296-
let push_fn_ctx_of_ty_fn (ty_fn:Ast.ty_fn) : unit =
1303+
let create_fn_ctx_of_ty_fn (ty_fn:Ast.ty_fn) : fn_ctx =
12971304
let (ty_sig, ty_fn_aux) = ty_fn in
12981305
let ret_ty = ty_sig.Ast.sig_output_slot.Ast.slot_ty in
12991306
let is_iter = ty_fn_aux.Ast.fn_is_iter in
1300-
push_fn_ctx (Common.option_get ret_ty) is_iter
1307+
create_fn_ctx (Common.option_get ret_ty) is_iter
13011308
in
13021309

1303-
let finish_function (item_id:Common.node_id) =
1304-
let fn_ctx = Stack.pop fn_ctx_stack in
1310+
let finish_function (fn_ctx:fn_ctx) (item_id:Common.node_id option) =
13051311
if not fn_ctx.fnctx_just_saw_ret &&
13061312
fn_ctx.fnctx_return_type <> Ast.TY_nil &&
13071313
not fn_ctx.fnctx_is_iter then
1308-
Common.err (Some item_id) "this function must return a value"
1314+
Common.err item_id "this function must return a value";
1315+
1316+
let check_for_slot_types_in_block block_id =
1317+
let check_for_slot_type slot_key defn_id =
1318+
match Hashtbl.find cx.Semant.ctxt_all_defns defn_id with
1319+
Semant.DEFN_slot { Ast.slot_ty = None; Ast.slot_mode = _ } ->
1320+
let stmt_id = Hashtbl.find fn_ctx.fnctx_slot_decls slot_key in
1321+
Common.err
1322+
(Some stmt_id)
1323+
"no type could be inferred for this slot"
1324+
| _ -> ()
1325+
in
1326+
let block_slots = Hashtbl.find cx.Semant.ctxt_block_slots block_id in
1327+
Hashtbl.iter check_for_slot_type block_slots
1328+
in
1329+
Stack.iter check_for_slot_types_in_block fn_ctx.fnctx_blocks
13091330
in
13101331

13111332
let check_fn_ty_validity item_id (ty_sig, _) =
@@ -1328,14 +1349,16 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
13281349
let visit_mod_item_pre _ _ item =
13291350
let { Common.node = item; Common.id = item_id } = item in
13301351
match item.Ast.decl_item with
1331-
Ast.MOD_ITEM_fn _ when
1352+
Ast.MOD_ITEM_fn fn when
13321353
not (Hashtbl.mem cx.Semant.ctxt_required_items item_id) ->
13331354
let fn_ty = Hashtbl.find cx.Semant.ctxt_all_item_types item_id in
13341355
begin
13351356
match fn_ty with
13361357
Ast.TY_fn ty_fn ->
13371358
check_fn_ty_validity item_id ty_fn;
1338-
push_fn_ctx_of_ty_fn ty_fn
1359+
let fn_ctx = create_fn_ctx_of_ty_fn ty_fn in
1360+
check_block cx fn_ctx fn.Ast.fn_body;
1361+
finish_function fn_ctx (Some item_id)
13391362
| _ ->
13401363
Common.bug ()
13411364
"Type.visit_mod_item_pre: fn item didn't have a fn type"
@@ -1346,10 +1369,7 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
13461369
let item_id = item.Common.id in
13471370
verify_main item_id;
13481371
match item.Common.node.Ast.decl_item with
1349-
Ast.MOD_ITEM_fn _ when
1350-
not (Hashtbl.mem cx.Semant.ctxt_required_items item_id) ->
1351-
finish_function item_id
1352-
| Ast.MOD_ITEM_tag (_, id, n) -> populate_tag_graph_node cx id n
1372+
Ast.MOD_ITEM_tag (_, id, n) -> populate_tag_graph_node cx id n
13531373
| _ -> ()
13541374
in
13551375

@@ -1366,33 +1386,21 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
13661386
match tsig.Ast.sig_output_slot with
13671387
{ Ast.slot_ty = Some (Ast.TY_obj (_, methods));
13681388
Ast.slot_mode = _ } ->
1369-
push_fn_ctx_of_ty_fn (Hashtbl.find methods ident)
1389+
let fn_ty = Hashtbl.find methods ident in
1390+
let fn_ctx = create_fn_ctx_of_ty_fn fn_ty in
1391+
let obj_fns = obj.Common.node.Ast.obj_fns in
1392+
let fn = Hashtbl.find obj_fns ident in
1393+
check_block cx fn_ctx fn.Common.node.Ast.fn_body;
1394+
finish_function fn_ctx (Some fn.Common.id)
13701395
| _ -> bad()
13711396
end
13721397
| _ -> bad()
13731398
in
1374-
let visit_obj_fn_post _ _ item = finish_function (item.Common.id) in
1375-
1376-
let visit_obj_drop_pre _ _ = push_fn_ctx Ast.TY_nil false in
1377-
let visit_obj_drop_post _ _ = ignore (Stack.pop fn_ctx_stack) in
13781399

1379-
let visit_stmt_pre (stmt:Ast.stmt) : unit =
1380-
try
1381-
iflog cx
1382-
begin
1383-
fun _ ->
1384-
log cx "";
1385-
log cx "typechecking stmt: %a" Ast.sprintf_stmt stmt;
1386-
log cx "";
1387-
end;
1388-
check_stmt cx (Stack.top fn_ctx_stack) stmt;
1389-
iflog cx
1390-
begin
1391-
fun _ ->
1392-
log cx "finished typechecking stmt: %a" Ast.sprintf_stmt stmt;
1393-
end;
1394-
with Common.Semant_err (None, msg) ->
1395-
raise (Common.Semant_err ((Some stmt.Common.id), msg))
1400+
let visit_obj_drop_pre _ block =
1401+
let fn_ctx = create_fn_ctx Ast.TY_nil false in
1402+
check_block cx fn_ctx block;
1403+
finish_function fn_ctx None
13961404
in
13971405

13981406
let visit_crate_pre _ : unit = create_tag_graph_nodes cx in
@@ -1411,13 +1419,10 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
14111419

14121420
{
14131421
inner with
1414-
Walk.visit_stmt_pre = visit_stmt_pre;
14151422
Walk.visit_mod_item_pre = visit_mod_item_pre;
14161423
Walk.visit_mod_item_post = visit_mod_item_post;
14171424
Walk.visit_obj_fn_pre = visit_obj_fn_pre;
1418-
Walk.visit_obj_fn_post = visit_obj_fn_post;
14191425
Walk.visit_obj_drop_pre = visit_obj_drop_pre;
1420-
Walk.visit_obj_drop_post = visit_obj_drop_post;
14211426
Walk.visit_crate_pre = visit_crate_pre;
14221427
Walk.visit_crate_post = visit_crate_post
14231428
}

src/lib/_uint.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ fn to_str(mutable uint n, uint radix) -> str
5555
case (14u) { ret 'e'; }
5656
case (15u) { ret 'f'; }
5757
}
58+
fail;
5859
}
5960

6061
if (n == 0u) { ret "0"; }

src/lib/deque.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ fn create[T]() -> t[T] {
5353
case (option.some[T](?t)) { ret t; }
5454
case (_) { fail; }
5555
}
56+
fail; // FIXME: remove me when exhaustiveness checking works
5657
}
5758

5859
obj deque[T](mutable uint nelts,

src/lib/list.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ fn foldl[T,U](&list[T] ls, &U u, fn(&T t, U u) -> U f) -> U {
2424
ret u;
2525
}
2626
}
27+
28+
fail; // TODO: remove me when exhaustiveness checking works
2729
}
2830

2931
fn find[T,U](&list[T] ls,
@@ -45,6 +47,8 @@ fn find[T,U](&list[T] ls,
4547
ret none[U];
4648
}
4749
}
50+
51+
fail; // TODO: remove me when exhaustiveness checking works
4852
}
4953

5054
fn length[T](&list[T] ls) -> uint {

src/lib/map.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,15 @@ fn mk_hashmap[K, V](&hashfn[K] hasher, &eqfn[K] eqer) -> hashmap[K, V] {
176176
case (option.some[V](_)) { ret true; }
177177
case (_) { ret false; }
178178
}
179+
fail; // FIXME: remove me when exhaustiveness checking works
179180
}
180181

181182
fn get(&K key) -> V {
182183
alt (find_common[K, V](hasher, eqer, bkts, nbkts, key)) {
183184
case (option.some[V](?val)) { ret val; }
184185
case (_) { fail; }
185186
}
187+
fail; // FIXME: remove me when exhaustiveness checking works
186188
}
187189

188190
fn find(&K key) -> option.t[V] {

src/lib/option.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ fn get[T](&t[T] opt) -> T {
1616
fail;
1717
}
1818
}
19+
fail; // FIXME: remove me when exhaustiveness checking works
1920
}
2021

2122
fn map[T, U](&operator[T, U] f, &t[T] opt) -> t[U] {
@@ -27,6 +28,7 @@ fn map[T, U](&operator[T, U] f, &t[T] opt) -> t[U] {
2728
ret none[U];
2829
}
2930
}
31+
fail; // FIXME: remove me when exhaustiveness checking works
3032
}
3133

3234
// Local Variables:

0 commit comments

Comments
 (0)