diff --git a/CHANGELOG.md b/CHANGELOG.md index e8b70a8..fa9e081 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Type definitions serialised to ACI as `typedefs` field instead of `type_defs` to increase compatibility. ### Removed ### Fixed +- Typechecker crashes if Chain.create or Chain.clone are used without arguments. ## [7.0.1] ### Added diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 2387779..4a8c8cb 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -2856,6 +2856,8 @@ unify0(Env, A, B, Variance, When) -> unify1(_Env, {uvar, _, R}, {uvar, _, R}, _Variance, _When) -> true; +unify1(_Env, {uvar, _, _}, {fun_t, _, _, var_args, _}, _Variance, When) -> + type_error({unify_varargs, When}); unify1(Env, {uvar, A, R}, T, _Variance, When) -> case occurs_check(R, T) of true -> @@ -3625,7 +3627,7 @@ mk_error({multiple_main_contracts, Ann}) -> Msg = "Only one main contract can be defined.", mk_t_err(pos(Ann), Msg); mk_error({unify_varargs, When}) -> - Msg = "Cannot unify variable argument list.", + Msg = "Cannot infer types for variable argument list.", {Pos, Ctxt} = pp_when(When), mk_t_err(Pos, Msg, Ctxt); mk_error({clone_no_contract, Ann}) -> diff --git a/src/aeso_pretty.erl b/src/aeso_pretty.erl index 32208c4..afce62c 100644 --- a/src/aeso_pretty.erl +++ b/src/aeso_pretty.erl @@ -261,6 +261,8 @@ type(Type, Options) -> with_options(Options, fun() -> type(Type) end). -spec type(aeso_syntax:type()) -> doc(). +type(F = {fun_t, _, _, var_args, _}) -> + type(setelement(4, F, [var_args])); type({fun_t, _, Named, Args, Ret}) -> follow(hsep(args_type(Named ++ Args), text("=>")), type(Ret)); type({type_sig, _, Named, Args, Ret}) -> @@ -288,7 +290,9 @@ type(T = {id, _, _}) -> name(T); type(T = {qid, _, _}) -> name(T); type(T = {con, _, _}) -> name(T); type(T = {qcon, _, _}) -> name(T); -type(T = {tvar, _, _}) -> name(T). +type(T = {tvar, _, _}) -> name(T); + +type(var_args) -> text("var_args"). -spec args_type([aeso_syntax:type()]) -> doc(). args_type(Args) -> diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index 3652aad..0ca006b 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -1139,6 +1139,19 @@ failing_contracts() -> " `oracle(string, (int) => int)`\n" "The response type must not be higher-order (contain function types)">> ]) + , ?TYPE_ERROR(var_args_unify_let, + [< 'b`">> + ]) + , ?TYPE_ERROR(var_args_unify_fun_call, + [< 'b) => 'b`\n" + "to arguments\n" + " `Chain.create : (value : int, var_args) => 'c`">> + ]) ]. validation_test_() -> diff --git a/test/contracts/var_args_unify_fun_call.aes b/test/contracts/var_args_unify_fun_call.aes new file mode 100644 index 0000000..28f0b8a --- /dev/null +++ b/test/contracts/var_args_unify_fun_call.aes @@ -0,0 +1,7 @@ +contract C = + stateful function g(h) = + h() + + stateful entrypoint f() = + g(Chain.create) + 123 diff --git a/test/contracts/var_args_unify_let.aes b/test/contracts/var_args_unify_let.aes new file mode 100644 index 0000000..18bfc0e --- /dev/null +++ b/test/contracts/var_args_unify_let.aes @@ -0,0 +1,4 @@ +main contract C = + stateful entrypoint f() = + let x = Chain.clone + 123