Fix ret/put mis-identification in typechecker. Closes #87.

This commit is contained in:
Graydon Hoare 2010-07-14 09:41:08 -07:00
parent 777002c565
commit 0fdad302b8
2 changed files with 49 additions and 7 deletions

View file

@ -216,6 +216,20 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit =
in
let retval_tvs = Stack.create () in
let fns = Stack.create () in
let push_fn fn =
Stack.push fn fns
in
let pop_fn _ =
ignore (Stack.pop fns)
in
let fn_is_iter() =
(Stack.top fns).Ast.fn_aux.Ast.fn_is_iter
in
let push_retval_tv tv =
Stack.push tv retval_tvs
in
@ -1215,14 +1229,28 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit =
| Ast.STMT_if { Ast.if_test = if_test } ->
unify_expr rval_ctx if_test (ty Ast.TY_bool);
| Ast.STMT_ret atom_opt
| Ast.STMT_put atom_opt ->
| Ast.STMT_ret atom_opt ->
begin
match atom_opt with
None -> unify_ty arg_pass_ctx Ast.TY_nil (retval_tv())
| Some atom -> unify_atom arg_pass_ctx atom (retval_tv())
if fn_is_iter()
then
match atom_opt with
| None -> ()
| Some _ -> err None "Iter returning value"
else
match atom_opt with
| None -> unify_ty arg_pass_ctx Ast.TY_nil (retval_tv())
| Some atom -> unify_atom arg_pass_ctx atom (retval_tv())
end
| Ast.STMT_put atom_opt ->
if fn_is_iter()
then
match atom_opt with
| None -> unify_ty arg_pass_ctx Ast.TY_nil (retval_tv())
| Some atom -> unify_atom arg_pass_ctx atom (retval_tv())
else
err None "Non-iter function with 'put'"
| Ast.STMT_be (callee, args) ->
check_callable (retval_tv()) callee args
@ -1344,11 +1372,17 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit =
in
let enter_fn fn retspec =
push_fn fn;
let out = fn.Ast.fn_output_slot in
push_retval_tv (ref retspec);
unify_slot arg_pass_ctx out.node (Some out.id) (retval_tv())
in
let leave_fn _ =
pop_retval_tv ();
pop_fn ();
in
let visit_obj_fn_pre obj ident fn =
enter_fn fn.node TYSPEC_all;
inner.Walk.visit_obj_fn_pre obj ident fn
@ -1356,7 +1390,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit =
let visit_obj_fn_post obj ident fn =
inner.Walk.visit_obj_fn_post obj ident fn;
pop_retval_tv ();
leave_fn ();
in
let visit_mod_item_pre n p mod_item =
@ -1382,7 +1416,7 @@ let process_crate (cx:ctxt) (crate:Ast.crate) : unit =
match mod_item.node.Ast.decl_item with
| Ast.MOD_ITEM_fn _ ->
pop_retval_tv ();
leave_fn ();
if (Some (path_name())) = cx.ctxt_main_name
then
begin

View file

@ -0,0 +1,8 @@
// error-pattern: Non-iter function
fn f() -> int {
put 10;
}
fn main() {
}