PT-163053747 Add missing type check of init function #494
@ -352,12 +352,25 @@ check_fundecl(_, {fun_decl, _Attrib, {id, _, Name}, Type}) ->
|
|||||||
infer_nonrec(Env, LetFun) ->
|
infer_nonrec(Env, LetFun) ->
|
||||||
create_constraints(),
|
create_constraints(),
|
||||||
NewLetFun = infer_letfun(Env, LetFun),
|
NewLetFun = infer_letfun(Env, LetFun),
|
||||||
|
check_special_funs(Env, NewLetFun),
|
||||||
solve_constraints(),
|
solve_constraints(),
|
||||||
destroy_and_report_unsolved_constraints(),
|
destroy_and_report_unsolved_constraints(),
|
||||||
Result = {TypeSig, _} = instantiate(NewLetFun),
|
Result = {TypeSig, _} = instantiate(NewLetFun),
|
||||||
print_typesig(TypeSig),
|
print_typesig(TypeSig),
|
||||||
Result.
|
Result.
|
||||||
|
|
||||||
|
%% Currenty only the init function.
|
||||||
|
check_special_funs(_Env, {{"init", Type}, _}) ->
|
||||||
|
{type_sig, Ann, _Named, _Args, Res} = Type,
|
||||||
|
State =
|
||||||
|
%% We might have implicit (no) state.
|
||||||
|
case lookup_type({id, [], "state"}) of
|
||||||
|
false -> {tuple_t, [{origin, system}], []};
|
||||||
|
_ -> {id, [{origin, system}], "state"}
|
||||||
|
end,
|
||||||
|
unify(Res, State, {checking_init_type, Ann});
|
||||||
|
check_special_funs(_, _) -> ok.
|
||||||
|
|
||||||
typesig_to_fun_t({type_sig, Ann, Named, Args, Res}) -> {fun_t, Ann, Named, Args, Res}.
|
typesig_to_fun_t({type_sig, Ann, Named, Args, Res}) -> {fun_t, Ann, Named, Args, Res}.
|
||||||
|
|
||||||
infer_letrec(Env, {letrec, Attrs, Defs}) ->
|
infer_letrec(Env, {letrec, Attrs, Defs}) ->
|
||||||
@ -1502,6 +1515,9 @@ pp_when({check_expr, Expr, Inferred0, Expected0}) ->
|
|||||||
"against the expected type\n~s\n",
|
"against the expected type\n~s\n",
|
||||||
[pp_loc(Expr), pp_typed(" ", Expr, Inferred),
|
[pp_loc(Expr), pp_typed(" ", Expr, Inferred),
|
||||||
pp_type(" ", Expected)]);
|
pp_type(" ", Expected)]);
|
||||||
|
pp_when({checking_init_type, Ann}) ->
|
||||||
|
io_lib:format("when checking that 'init' returns a value of type 'state' at ~s\n",
|
||||||
|
[pp_loc(Ann)]);
|
||||||
pp_when(unknown) -> "".
|
pp_when(unknown) -> "".
|
||||||
|
|
||||||
-spec pp_why_record(why_record()) -> iolist().
|
-spec pp_why_record(why_record()) -> iolist().
|
||||||
|
@ -133,4 +133,12 @@ failing_contracts() ->
|
|||||||
"Repeated name x in pattern\n"
|
"Repeated name x in pattern\n"
|
||||||
" x :: x (at line 26, column 7)\n",
|
" x :: x (at line 26, column 7)\n",
|
||||||
"No record type with fields y, z (at line 14, column 22)\n"]}
|
"No record type with fields y, z (at line 14, column 22)\n"]}
|
||||||
|
, {"init_type_error",
|
||||||
|
["Cannot unify string\n"
|
||||||
|
" and map(int, int)\n"
|
||||||
|
"when checking that 'init' returns a value of type 'state' at line 7, column 3\n"]}
|
||||||
|
, {"missing_state_type",
|
||||||
|
["Cannot unify string\n"
|
||||||
|
" and ()\n"
|
||||||
|
"when checking that 'init' returns a value of type 'state' at line 5, column 3\n"]}
|
||||||
].
|
].
|
||||||
|
8
test/contracts/init_type_error.aes
Normal file
8
test/contracts/init_type_error.aes
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
contract InitTypeError =
|
||||||
|
|
||||||
|
type state = map(int, int)
|
||||||
|
|
||||||
|
// Check that the compiler catches ill-typed init function
|
||||||
|
function init() = "not the right type!"
|
||||||
|
|
6
test/contracts/missing_state_type.aes
Normal file
6
test/contracts/missing_state_type.aes
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
contract MissingStateType =
|
||||||
|
|
||||||
|
// Check that we get a type error also for implicit state
|
||||||
|
function init() = "should be ()"
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user