Skip to content

Commit 1ac01e1

Browse files
committed
Ensure that functions that should return a value do; issue 41
1 parent 4d413af commit 1ac01e1

File tree

6 files changed

+45
-6
lines changed

6 files changed

+45
-6
lines changed

src/boot/me/type.ml

+32-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ type ltype =
1313

1414
type fn_ctx = {
1515
fnctx_return_type: Ast.ty;
16-
fnctx_is_iter: bool
16+
fnctx_is_iter: bool;
17+
mutable fnctx_just_saw_ret: bool
1718
}
1819

1920
exception Type_error of string * Ast.ty
@@ -627,10 +628,19 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
627628
(* Again as above, we explicitly curry [fn_ctx] to avoid threading it
628629
* through these functions. *)
629630
let check_stmt (fn_ctx:fn_ctx) : (Ast.stmt -> unit) =
631+
let check_ret (stmt:Ast.stmt) : unit =
632+
fn_ctx.fnctx_just_saw_ret <-
633+
match stmt.Common.node with
634+
Ast.STMT_ret _ | Ast.STMT_be _ | Ast.STMT_fail
635+
| Ast.STMT_yield _ -> true
636+
| _ -> false
637+
in
638+
630639
let rec check_block (block:Ast.block) : unit =
631640
Array.iter check_stmt block.Common.node
632641

633642
and check_stmt (stmt:Ast.stmt) : unit =
643+
check_ret stmt;
634644
match stmt.Common.node with
635645
Ast.STMT_spawn (dst, _, callee, args) ->
636646
infer_lval Ast.TY_task dst;
@@ -841,7 +851,11 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
841851

842852
let visitor (cx:Semant.ctxt) (inner:Walk.visitor) : Walk.visitor =
843853
let push_fn_ctx (ret_ty:Ast.ty) (is_iter:bool) =
844-
let fn_ctx = { fnctx_return_type = ret_ty; fnctx_is_iter = is_iter } in
854+
let fn_ctx = {
855+
fnctx_return_type = ret_ty;
856+
fnctx_is_iter = is_iter;
857+
fnctx_just_saw_ret = false
858+
} in
845859
Stack.push fn_ctx fn_ctx_stack
846860
in
847861

@@ -852,10 +866,19 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
852866
push_fn_ctx (Common.option_get ret_ty) is_iter
853867
in
854868

869+
let finish_function (item_id:Common.node_id) =
870+
let fn_ctx = Stack.pop fn_ctx_stack in
871+
if not fn_ctx.fnctx_just_saw_ret &&
872+
fn_ctx.fnctx_return_type <> Ast.TY_nil &&
873+
not fn_ctx.fnctx_is_iter then
874+
Common.err (Some item_id) "this function must return a value"
875+
in
876+
855877
let visit_mod_item_pre _ _ item =
856878
let { Common.node = item; Common.id = item_id } = item in
857879
match item.Ast.decl_item with
858-
Ast.MOD_ITEM_fn _ ->
880+
Ast.MOD_ITEM_fn _ when
881+
not (Hashtbl.mem cx.Semant.ctxt_required_items item_id) ->
859882
let fn_ty = Hashtbl.find cx.Semant.ctxt_all_item_types item_id in
860883
begin
861884
match fn_ty with
@@ -867,9 +890,12 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
867890
| _ -> ()
868891
in
869892
let visit_mod_item_post _ _ item =
870-
verify_main item.Common.id;
893+
let item_id = item.Common.id in
894+
verify_main item_id;
871895
match item.Common.node.Ast.decl_item with
872-
Ast.MOD_ITEM_fn _ -> ignore (Stack.pop fn_ctx_stack)
896+
Ast.MOD_ITEM_fn _ when
897+
not (Hashtbl.mem cx.Semant.ctxt_required_items item_id) ->
898+
finish_function item_id
873899
| _ -> ()
874900
in
875901

@@ -884,7 +910,7 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
884910
"Type.visit_obj_fn_pre: item doesn't have an object type (%a)"
885911
Ast.sprintf_ty obj_ty
886912
in
887-
let visit_obj_fn_post _ _ _ = ignore (Stack.pop fn_ctx_stack) in
913+
let visit_obj_fn_post _ _ item = finish_function (item.Common.id) in
888914

889915
let visit_obj_drop_pre _ _ = push_fn_ctx Ast.TY_nil false in
890916
let visit_obj_drop_post _ _ = ignore (Stack.pop fn_ctx_stack) in

src/lib/_io.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ fn new_buf() -> vec[u8] {
1515
}
1616
// FIXME (issue #93): should be:
1717
// ret _vec.alloc[u8](default_bufsz());
18+
ret v;
1819
}
1920

2021
fn new_buf_reader(str s) -> buf_reader {

src/lib/_str.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ native "rust" mod rustrt {
99
}
1010

1111
fn is_utf8(vec[u8] v) -> bool {
12+
fail; // FIXME
1213
}
1314

1415
fn alloc(uint n_bytes) -> str {

src/test/compile-fail/impure-pred.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ io fn lt(int a, int b) -> bool {
99
let port[int] p = port();
1010
let chan[int] c = chan(p);
1111
c <| 10;
12+
ret true;
1213
}
1314

1415
fn main() {
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// error-pattern: return
2+
3+
fn f() -> int {
4+
}
5+
6+
fn main() {
7+
f();
8+
}
9+

src/test/run-pass/complex.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ fn foo(int x) -> int {
2121
let t z;
2222
z = 0x55;
2323
foo(z);
24+
ret 0;
2425
}
2526

2627
fn main() {

0 commit comments

Comments
 (0)