Fail on function definitions in contracts other than the main contract

This commit is contained in:
Ulf Norell 2019-10-01 13:13:27 +02:00
parent 482d22d46b
commit 2d6d506d63
3 changed files with 39 additions and 12 deletions

View File

@ -707,20 +707,34 @@ check_unexpected(Xs) ->
check_modifiers(Env, Contracts) ->
create_type_errors(),
[ case C of
{contract, _, Con, Decls} ->
check_modifiers1(contract, Decls),
case {lists:keymember(letfun, 1, Decls),
[ D || D <- Decls, aeso_syntax:get_ann(entrypoint, D, false) ]} of
{true, []} -> type_error({contract_has_no_entrypoints, Con});
_ -> ok
end;
{namespace, _, _, Decls} -> check_modifiers1(namespace, Decls);
{pragma, Ann, Pragma} -> check_pragma(Env, Ann, Pragma);
Decl -> type_error({bad_top_level_decl, Decl})
end || C <- Contracts ],
check_modifiers_(Env, Contracts),
destroy_and_report_type_errors(Env).
check_modifiers_(Env, [{contract, _, Con, Decls} | Rest]) ->
IsMain = Rest == [],
check_modifiers1(contract, Decls),
case {lists:keymember(letfun, 1, Decls),
[ D || D <- Decls, aeso_syntax:get_ann(entrypoint, D, false) ]} of
{true, []} -> type_error({contract_has_no_entrypoints, Con});
_ when not IsMain ->
case [ {Ann, Id} || {letfun, Ann, Id, _, _, _} <- Decls ] of
[{Ann, Id} | _] -> type_error({definition_in_non_main_contract, Ann, Id});
[] -> ok
end;
_ -> ok
end,
check_modifiers_(Env, Rest);
check_modifiers_(Env, [{namespace, _, _, Decls} | Rest]) ->
check_modifiers1(namespace, Decls),
check_modifiers_(Env, Rest);
check_modifiers_(Env, [{pragma, Ann, Pragma} | Rest]) ->
check_pragma(Env, Ann, Pragma),
check_modifiers_(Env, Rest);
check_modifiers_(Env, [Decl | Rest]) ->
type_error({bad_top_level_decl, Decl}),
check_modifiers_(Env, Rest);
check_modifiers_(_Env, []) -> ok.
-spec check_pragma(env(), aeso_syntax:ann(), aeso_syntax:pragma()) -> ok.
check_pragma(_Env, Ann, {compiler, Op, Ver}) ->
case aeso_compiler:numeric_version() of
@ -2359,6 +2373,10 @@ mk_error({contract_has_no_entrypoints, Con}) ->
"contract functions must be declared with the 'entrypoint' keyword instead of\n"
"'function'.\n", [pp_expr("", Con), pp_loc(Con)]),
mk_t_err(pos(Con), Msg);
mk_error({definition_in_non_main_contract, Ann, {id, _, Id}}) ->
Msg = "Only the main contract can contain defined functions or entrypoints.\n",
Cxt = io_lib:format("Fix: replace the definition of '~s' by a type signature.\n", [Id]),
mk_t_err(pos(Ann), Msg, Cxt);
mk_error({unbound_type, Type}) ->
Msg = io_lib:format("Unbound type ~s (at ~s).\n", [pp_type("", Type), pp_loc(Type)]),
mk_t_err(pos(Type), Msg);

View File

@ -573,6 +573,10 @@ failing_contracts() ->
<<?Pos(2, 1)
"Cannot compile with this version of the compiler,\n"
"because it does not satisfy the constraint ", Version/binary, " == 9.9.9">>])
, ?TYPE_ERROR(multiple_contracts,
[<<?Pos(2, 3)
"Only the main contract can contain defined functions or entrypoints.\n"
"Fix: replace the definition of 'foo' by a type signature.">>])
].
-define(Path(File), "code_errors/" ??File).

View File

@ -0,0 +1,5 @@
contract ContractOne =
entrypoint foo() = "foo"
contract ContractTwo =
entrypoint bar() = "bar"