All checks were successful
Sophia Tests / tests (push) Successful in 48m54s
A few references to oracles still remain, but they have been removed as a feature, at least. Reviewed-on: #985 Reviewed-by: Ulf Wiger <ulfwiger@qpq.swiss> Co-authored-by: Craig Everett <zxq9@zxq9.com> Co-committed-by: Craig Everett <zxq9@zxq9.com>
1252 lines
61 KiB
Erlang
1252 lines
61 KiB
Erlang
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
|
%%%-------------------------------------------------------------------
|
|
%%% @copyright (C) 2018, Aeternity Anstalt
|
|
%%% @doc Test Sophia language compiler.
|
|
%%%
|
|
%%% @end
|
|
%%%-------------------------------------------------------------------
|
|
|
|
-module(so_compiler_tests).
|
|
|
|
-compile([export_all, nowarn_export_all]).
|
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
run_test(Test) ->
|
|
TestFun = list_to_atom(lists:concat([Test, "_test_"])),
|
|
[ begin
|
|
io:format("~s\n", [Label]),
|
|
Fun()
|
|
end || {Label, Fun} <- ?MODULE:TestFun() ],
|
|
ok.
|
|
|
|
%% Very simply test compile the given contracts. Only basic checks
|
|
%% are made on the output, just that it is a binary which indicates
|
|
%% that the compilation worked.
|
|
simple_compile_test_() ->
|
|
[ {"Testing the " ++ ContractName ++ " contract",
|
|
fun() ->
|
|
case compile(ContractName) of
|
|
#{fate_code := Code} ->
|
|
Code1 = gmb_fate_code:deserialize(gmb_fate_code:serialize(Code)),
|
|
?assertMatch({X, X}, {Code1, Code});
|
|
Error -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
|
|
end
|
|
end} || ContractName <- compilable_contracts()] ++
|
|
[ {"Test file not found error",
|
|
fun() ->
|
|
{error, Errors} = so_compiler:file("does_not_exist.aes"),
|
|
ExpErr = <<"File error:\ndoes_not_exist.aes: no such file or directory">>,
|
|
check_errors([ExpErr], Errors)
|
|
end} ] ++
|
|
[ {"Testing error messages of " ++ ContractName,
|
|
fun() ->
|
|
Errors = compile(ContractName, [warn_all, warn_error]),
|
|
check_errors(ExpectedErrors, Errors)
|
|
end} ||
|
|
{ContractName, ExpectedErrors} <- failing_contracts() ] ++
|
|
[ {"Testing include with explicit files",
|
|
fun() ->
|
|
FileSystem = maps:from_list(
|
|
[ begin
|
|
{ok, Bin} = file:read_file(filename:join([so_test_utils:contract_path(), File])),
|
|
{File, Bin}
|
|
end || File <- ["included.aes", "../contracts/included2.aes"] ]),
|
|
#{byte_code := Code1} = compile("include", [{include, {explicit_files, FileSystem}}]),
|
|
#{byte_code := Code2} = compile("include"),
|
|
?assertMatch(true, Code1 == Code2)
|
|
end} ] ++
|
|
[ {"Testing deadcode elimination",
|
|
fun() ->
|
|
#{ byte_code := NoDeadCode } = compile("nodeadcode"),
|
|
#{ byte_code := DeadCode } = compile("deadcode"),
|
|
SizeNoDeadCode = byte_size(NoDeadCode),
|
|
SizeDeadCode = byte_size(DeadCode),
|
|
Delta = 20,
|
|
?assertMatch({_, _, true}, {SizeDeadCode, SizeNoDeadCode, SizeDeadCode + Delta < SizeNoDeadCode}),
|
|
ok
|
|
end} ] ++
|
|
[ {"Testing warning messages",
|
|
fun() ->
|
|
#{ warnings := Warnings } = compile("warnings", [warn_all]),
|
|
#{ warnings := [] } = compile("warning_unused_include_no_include", [warn_all]),
|
|
#{ warnings := [] } = compile("warning_used_record_typedef", [warn_all]),
|
|
check_warnings(warnings(), Warnings)
|
|
end} ] ++
|
|
[].
|
|
|
|
%% Check if all modules in the standard library compile
|
|
stdlib_test_() ->
|
|
{ok, Files} = file:list_dir(so_stdlib:stdlib_include_path()),
|
|
[ { "Testing " ++ File ++ " from the stdlib",
|
|
fun() ->
|
|
String = "include \"" ++ File ++ "\"\nmain contract Test =\n entrypoint f(x) = x",
|
|
Options = [{src_file, File}],
|
|
case so_compiler:from_string(String, Options) of
|
|
{ok, #{fate_code := Code}} ->
|
|
Code1 = gmb_fate_code:deserialize(gmb_fate_code:serialize(Code)),
|
|
?assertMatch({X, X}, {Code1, Code});
|
|
{error, Error} -> io:format("\n\n~p\n\n", [Error]), print_and_throw(Error)
|
|
end
|
|
end} || File <- Files,
|
|
lists:suffix(".aes", File)
|
|
].
|
|
|
|
check_errors(no_error, Actual) -> ?assertMatch(#{}, Actual);
|
|
check_errors(Expect, #{}) ->
|
|
?assertEqual({error, Expect}, ok);
|
|
check_errors(Expect0, Actual0) ->
|
|
Expect = lists:sort(Expect0),
|
|
Actual = [ list_to_binary(string:trim(so_errors:pp(Err))) || Err <- Actual0 ],
|
|
case {Expect -- Actual, Actual -- Expect} of
|
|
{[], Extra} -> ?assertMatch({unexpected, []}, {unexpected, Extra});
|
|
{Missing, []} -> ?assertMatch({missing, []}, {missing, Missing});
|
|
{Missing, Extra} -> ?assertEqual(Missing, Extra)
|
|
end.
|
|
|
|
check_warnings(Expect0, Actual0) ->
|
|
Expect = lists:sort(Expect0),
|
|
Actual = [ list_to_binary(string:trim(so_warnings:pp(Warn))) || Warn <- Actual0 ],
|
|
case {Expect -- Actual, Actual -- Expect} of
|
|
{[], Extra} -> ?assertMatch({unexpected, []}, {unexpected, Extra});
|
|
{Missing, []} -> ?assertMatch({missing, []}, {missing, Missing});
|
|
{Missing, Extra} -> ?assertEqual(Missing, Extra)
|
|
end.
|
|
|
|
compile(Name) ->
|
|
compile( Name, [{include, {file_system, [so_test_utils:contract_path()]}}]).
|
|
|
|
compile(Name, Options) ->
|
|
String = so_test_utils:read_contract(Name),
|
|
Options1 =
|
|
case lists:member(Name, debug_mode_contracts()) of
|
|
true -> [debug_mode];
|
|
false -> []
|
|
end ++
|
|
[ {src_file, Name ++ ".aes"}
|
|
, {include, {file_system, [so_test_utils:contract_path()]}}
|
|
] ++ Options,
|
|
case so_compiler:from_string(String, Options1) of
|
|
{ok, Map} -> Map;
|
|
{error, ErrorString} when is_binary(ErrorString) -> ErrorString;
|
|
{error, Errors} -> Errors
|
|
end.
|
|
|
|
%% compilable_contracts() -> [ContractName].
|
|
%% The currently compilable contracts.
|
|
|
|
compilable_contracts() ->
|
|
["complex_types",
|
|
"counter",
|
|
"dutch_auction",
|
|
"environment",
|
|
"factorial",
|
|
"functions",
|
|
"fundme",
|
|
"identity",
|
|
"maps",
|
|
"remote_call",
|
|
"remote_call_ambiguous_record",
|
|
"simple",
|
|
"simple_storage",
|
|
"spend_test",
|
|
"stack",
|
|
"test",
|
|
"builtin_bug",
|
|
"builtin_map_get_bug",
|
|
"lc_record_bug",
|
|
"nodeadcode",
|
|
"deadcode",
|
|
"variant_types",
|
|
"state_handling",
|
|
"events",
|
|
"include",
|
|
"relative_include",
|
|
"basic_auth",
|
|
"basic_auth_tx",
|
|
"bitcoin_auth",
|
|
"address_literals",
|
|
"bytes_equality",
|
|
"address_chain",
|
|
"namespace_bug",
|
|
"bytes_to_x",
|
|
"bytes_concat",
|
|
"bytes_misc",
|
|
"aens",
|
|
"aens_update",
|
|
"tuple_match",
|
|
"cyclic_include",
|
|
"stdlib_include",
|
|
"double_include",
|
|
"manual_stdlib_include",
|
|
"list_comp",
|
|
"payable",
|
|
"unapplied_builtins",
|
|
"underscore_number_literals",
|
|
"pairing_crypto",
|
|
"qualified_constructor",
|
|
"let_patterns",
|
|
"lhs_matching",
|
|
"more_strings",
|
|
"protected_call",
|
|
"hermetization_turnoff",
|
|
"multiple_contracts",
|
|
"clone",
|
|
"clone_simple",
|
|
"create",
|
|
"child_contract_init_bug",
|
|
"using_namespace",
|
|
"assign_patterns",
|
|
"patterns_guards",
|
|
"pipe_operator",
|
|
"polymorphism_contract_implements_interface",
|
|
"polymorphism_contract_multi_interface",
|
|
"polymorphism_contract_interface_extends_interface",
|
|
"polymorphism_contract_interface_extensions",
|
|
"polymorphism_contract_interface_same_decl_multi_interface",
|
|
"polymorphism_contract_interface_same_name_same_type",
|
|
"polymorphism_variance_switching_chain_create",
|
|
"polymorphism_variance_switching_void_supertype",
|
|
"polymorphism_variance_switching_unify_with_interface_decls",
|
|
"polymorphism_preserve_or_add_payable_contract",
|
|
"polymorphism_preserve_or_add_payable_entrypoint",
|
|
"polymorphism_preserve_or_remove_stateful_entrypoint",
|
|
"missing_init_fun_state_unit",
|
|
"complex_compare_leq",
|
|
"complex_compare",
|
|
"higher_order_compare",
|
|
"higher_order_map_keys",
|
|
"higher_order_state",
|
|
"polymorphic_compare",
|
|
"polymorphic_entrypoint",
|
|
"polymorphic_entrypoint_return",
|
|
"polymorphic_map_keys",
|
|
"unapplied_contract_call",
|
|
"resolve_field_constraint_by_arity",
|
|
"toplevel_constants",
|
|
"ceres",
|
|
"test" % Custom general-purpose test file. Keep it last on the list.
|
|
].
|
|
|
|
debug_mode_contracts() ->
|
|
["hermetization_turnoff"].
|
|
|
|
%% Contracts that should produce type errors
|
|
|
|
-define(Pos(Kind, File, Line, Col), (list_to_binary(Kind))/binary, " error in '",
|
|
(list_to_binary(File))/binary, ".aes' at line " ??Line ", col " ??Col ":\n").
|
|
-define(Pos(Line, Col), ?Pos(__Kind, __File, Line, Col)).
|
|
|
|
-define(ERROR(Kind, Name, Errs),
|
|
(fun() ->
|
|
__Kind = Kind,
|
|
__File = ??Name,
|
|
{__File, Errs}
|
|
end)()).
|
|
|
|
-define(TYPE_ERROR(Name, Errs), ?ERROR("Type", Name, Errs)).
|
|
-define(PARSE_ERROR(Name, Errs), ?ERROR("Parse", Name, Errs)).
|
|
|
|
-define(PosW(Kind, File, Line, Col), (list_to_binary(Kind))/binary, " in '",
|
|
(list_to_binary(File))/binary, ".aes' at line " ??Line ", col " ??Col ":\n").
|
|
-define(PosW(Line, Col), ?PosW(__Kind, __File, Line, Col)).
|
|
|
|
-define(WARNING(Name, Warns),
|
|
(fun() ->
|
|
__Kind = "Warning",
|
|
__File = ??Name,
|
|
Warns
|
|
end)()).
|
|
|
|
warnings() ->
|
|
?WARNING(warnings,
|
|
[<<?PosW(0, 0)
|
|
"The file `Triple.aes` is included but not used.">>,
|
|
<<?PosW(13, 3)
|
|
"The function `h` is defined but never used.">>,
|
|
<<?PosW(19, 3)
|
|
"The type `unused_type` is defined but never used.">>,
|
|
<<?PosW(23, 54)
|
|
"Negative spend.">>,
|
|
<<?PosW(27, 9)
|
|
"The definition of `x` shadows an older definition at line 26, column 9.">>,
|
|
<<?PosW(30, 36)
|
|
"Division by zero.">>,
|
|
<<?PosW(32, 3)
|
|
"The function `unused_stateful` is unnecessarily marked as stateful.">>,
|
|
<<?PosW(35, 31)
|
|
"The variable `unused_arg` is defined but never used.">>,
|
|
<<?PosW(36, 9)
|
|
"The variable `unused_var` is defined but never used.">>,
|
|
<<?PosW(41, 3)
|
|
"The function `unused_function` is defined but never used.">>,
|
|
<<?PosW(42, 3)
|
|
"The function `recursive_unused_function` is defined but never used.">>,
|
|
<<?PosW(43, 3)
|
|
"The function `called_unused_function1` is defined but never used.">>,
|
|
<<?PosW(44, 3)
|
|
"The function `called_unused_function2` is defined but never used.">>,
|
|
<<?PosW(48, 5)
|
|
"Unused return value.">>,
|
|
<<?PosW(60, 5)
|
|
"The function `dec` is defined but never used.">>,
|
|
<<?PosW(73, 9)
|
|
"The definition of `const` shadows an older definition at line 70, column 3.">>,
|
|
<<?PosW(84, 7)
|
|
"The constant `c` is defined but never used.">>
|
|
]).
|
|
|
|
failing_contracts() ->
|
|
{ok, V} = so_compiler:numeric_version(),
|
|
Version = list_to_binary(string:join([integer_to_list(N) || N <- V], ".")),
|
|
%% Parse errors
|
|
[ ?PARSE_ERROR(field_parse_error,
|
|
[<<?Pos(5, 26)
|
|
"Cannot use nested fields or keys in record construction: p.x">>])
|
|
, ?PARSE_ERROR(vsemi, [<<?Pos(3, 3) "Unexpected indentation. Did you forget a '}'?">>])
|
|
, ?PARSE_ERROR(vclose, [<<?Pos(4, 3) "Unexpected indentation. Did you forget a ']'?">>])
|
|
, ?PARSE_ERROR(indent_fail, [<<?Pos(3, 2) "Unexpected token 'entrypoint'.">>])
|
|
, ?PARSE_ERROR(assign_pattern_to_pattern, [<<?Pos(3, 22) "Unexpected token '='.">>])
|
|
|
|
%% Type errors
|
|
, ?TYPE_ERROR(name_clash,
|
|
[<<?Pos(4, 3)
|
|
"Duplicate definitions of `double_def` at\n"
|
|
" - line 3, column 3\n"
|
|
" - line 4, column 3">>,
|
|
<<?Pos(7, 3)
|
|
"Duplicate definitions of `abort` at\n"
|
|
" - (builtin location)\n"
|
|
" - line 7, column 3">>,
|
|
<<?Pos(8, 3)
|
|
"Duplicate definitions of `require` at\n"
|
|
" - (builtin location)\n"
|
|
" - line 8, column 3">>,
|
|
<<?Pos(9, 3)
|
|
"Duplicate definitions of `put` at\n"
|
|
" - (builtin location)\n"
|
|
" - line 9, column 3">>,
|
|
<<?Pos(10, 3)
|
|
"Duplicate definitions of `state` at\n"
|
|
" - (builtin location)\n"
|
|
" - line 10, column 3">>])
|
|
, ?TYPE_ERROR(type_errors,
|
|
[<<?Pos(17, 23)
|
|
"Unbound variable `zz`">>,
|
|
<<?Pos(26, 9)
|
|
"Cannot unify `int` and `list(int)`\n"
|
|
"when checking the application of\n"
|
|
" `(::) : (int, list(int)) => list(int)`\n"
|
|
"to arguments\n"
|
|
" `x : int`\n"
|
|
" `x : int`">>,
|
|
<<?Pos(9, 48)
|
|
"Cannot unify `string` and `int`\n"
|
|
"when checking the assignment of the field `x : map(string, string)` "
|
|
"to the old value `__x` and the new value `__x {[\"foo\"] @ x = x + 1} : map(string, int)`">>,
|
|
<<?Pos(34, 47)
|
|
"Cannot unify `int` and `string`\n"
|
|
"when checking the type of the expression `1 : int` "
|
|
"against the expected type `string`">>,
|
|
<<?Pos(34, 52)
|
|
"Cannot unify `string` and `int`\n"
|
|
"when checking the type of the expression `\"bla\" : string` "
|
|
"against the expected type `int`">>,
|
|
<<?Pos(32, 18)
|
|
"Cannot unify `string` and `int`\n"
|
|
"when checking the type of the expression `\"x\" : string` "
|
|
"against the expected type `int`">>,
|
|
<<?Pos(11, 58)
|
|
"Cannot unify `string` and `int`\n"
|
|
"when checking the type of the expression `\"foo\" : string` "
|
|
"against the expected type `int`">>,
|
|
<<?Pos(38, 13)
|
|
"Cannot unify `int` and `string`\n"
|
|
"when comparing the types of the if-branches\n"
|
|
" - w : int (at line 38, column 13)\n"
|
|
" - z : string (at line 39, column 10)">>,
|
|
<<?Pos(22, 40)
|
|
"Not a record type: `string`\n"
|
|
"arising from the projection of the field `y`">>,
|
|
<<?Pos(21, 44)
|
|
"Not a record type: `string`\n"
|
|
"arising from an assignment of the field `y`">>,
|
|
<<?Pos(20, 40)
|
|
"Not a record type: `string`\n"
|
|
"arising from an assignment of the field `y`">>,
|
|
<<?Pos(19, 37)
|
|
"Not a record type: `string`\n"
|
|
"arising from an assignment of the field `y`">>,
|
|
<<?Pos(13, 27)
|
|
"Ambiguous record type with field `y` could be one of\n"
|
|
" - `r` (at line 4, column 10)\n"
|
|
" - `r'` (at line 5, column 10)">>,
|
|
<<?Pos(26, 7)
|
|
"Repeated name `x` in the pattern `x :: x`">>,
|
|
<<?Pos(44, 14)
|
|
"Repeated names `x`, `y` in the pattern `(x : int, y, x : string, y : bool)`">>,
|
|
<<?Pos(44, 39)
|
|
"Cannot unify `int` and `string`\n"
|
|
"when checking the type of the expression `x : int` "
|
|
"against the expected type `string`">>,
|
|
<<?Pos(44, 72)
|
|
"Cannot unify `int` and `string`\n"
|
|
"when checking the type of the expression `x : int` "
|
|
"against the expected type `string`">>,
|
|
<<?Pos(14, 24)
|
|
"No record type with fields `y`, `z`">>,
|
|
<<?Pos(15, 26)
|
|
"The field `z` is missing when constructing an element of type `r2`">>,
|
|
<<?Pos(15, 24)
|
|
"Record type `r2` does not have field `y`">>,
|
|
<<?Pos(47, 5)
|
|
"Let binding must be followed by an expression.">>,
|
|
<<?Pos(50, 5)
|
|
"Let binding must be followed by an expression.">>,
|
|
<<?Pos(54, 5)
|
|
"Let binding must be followed by an expression.">>,
|
|
<<?Pos(58, 5)
|
|
"Let binding must be followed by an expression.">>,
|
|
<<?Pos(63, 5)
|
|
"Cannot unify `int` and `bool`\n"
|
|
"when checking the type of the expression `id(n) : int` "
|
|
"against the expected type `bool`">>])
|
|
, ?TYPE_ERROR(init_type_error,
|
|
[<<?Pos(7, 3)
|
|
"Cannot unify `string` and `map(int, int)`\n"
|
|
"when checking that `init` returns a value of type `state`">>])
|
|
, ?TYPE_ERROR(missing_state_type,
|
|
[<<?Pos(5, 3)
|
|
"Cannot unify `string` and `unit`\n"
|
|
"when checking that `init` returns a value of type `state`">>])
|
|
, ?TYPE_ERROR(missing_fields_in_record_expression,
|
|
[<<?Pos(7, 42)
|
|
"The field `x` is missing when constructing an element of type `r('a)`">>,
|
|
<<?Pos(8, 42)
|
|
"The field `y` is missing when constructing an element of type `r(int)`">>,
|
|
<<?Pos(6, 42)
|
|
"The fields `y`, `z` are missing when constructing an element of type `r('a)`">>])
|
|
, ?TYPE_ERROR(namespace_clash_builtin,
|
|
[<<?Pos(4, 10)
|
|
"The contract `Call` has the same name as a namespace at (builtin location)">>])
|
|
, ?TYPE_ERROR(namespace_clash_included,
|
|
[<<?Pos(5, 11)
|
|
"The namespace `BLS12_381` has the same name as a namespace at line 1, column 11 in BLS12_381.aes">>])
|
|
, ?TYPE_ERROR(namespace_clash_same_file,
|
|
[<<?Pos(4, 11)
|
|
"The namespace `Nmsp` has the same name as a namespace at line 1, column 11">>])
|
|
, ?TYPE_ERROR(bad_events,
|
|
[<<?Pos(9, 25)
|
|
"The indexed type `string` is not a word type">>,
|
|
<<?Pos(10, 25)
|
|
"The indexed type `alias_string` equals `string` which is not a word type">>])
|
|
, ?TYPE_ERROR(bad_events2,
|
|
[<<?Pos(9, 7)
|
|
"The event constructor `BadEvent1` has too many non-indexed values (max 1)">>,
|
|
<<?Pos(10, 7)
|
|
"The event constructor `BadEvent2` has too many indexed values (max 3)">>])
|
|
, ?TYPE_ERROR(type_clash,
|
|
[<<?Pos(12, 42)
|
|
"Cannot unify `int` and `string`\n"
|
|
"when checking the type of the expression `r.foo() : map(int, string)` "
|
|
"against the expected type `map(string, int)`">>,
|
|
<<?Pos(12, 42)
|
|
"Cannot unify `string` and `int`\n"
|
|
"when checking the type of the expression `r.foo() : map(int, string)` "
|
|
"against the expected type `map(string, int)`">>])
|
|
, ?TYPE_ERROR(not_toplevel_include,
|
|
[<<?Pos(2, 11)
|
|
"Include of `included.aes` is not allowed, include only allowed at top level.">>])
|
|
, ?TYPE_ERROR(not_toplevel_namespace,
|
|
[<<?Pos(2, 13)
|
|
"Nested namespaces are not allowed. Namespace `Foo` is not defined at top level.">>])
|
|
, ?TYPE_ERROR(not_toplevel_contract,
|
|
[<<?Pos(2, 12)
|
|
"Nested contracts are not allowed. Contract `Con` is not defined at top level.">>])
|
|
, ?TYPE_ERROR(bad_address_literals,
|
|
[<<?Pos(9, 5)
|
|
"Cannot unify `address` and `Remote`\n"
|
|
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
|
"against the expected type `Remote`">>,
|
|
<<?Pos(7, 5)
|
|
"Cannot unify `address` and `bytes(32)`\n"
|
|
"when checking the type of the expression `ak_2gx9MEFxKvY9vMG5YnqnXWv1hCsX7rgnfvBLJS4aQurustR1rt : address` "
|
|
"against the expected type `bytes(32)`">>,
|
|
<<?Pos(12, 5)
|
|
"The type `address` is not a contract type\n"
|
|
"when checking that the contract literal "
|
|
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
|
"has the type `address`">>,
|
|
<<?Pos(14, 5)
|
|
"The type `bytes(32)` is not a contract type\n"
|
|
"when checking that the contract literal "
|
|
"`ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` "
|
|
"has the type `bytes(32)`">>,
|
|
<<?Pos(16, 5),
|
|
"The type `address` is not a contract type\n"
|
|
"when checking that the call to `Address.to_contract` "
|
|
"has the type `address`">>])
|
|
, ?TYPE_ERROR(stateful,
|
|
[<<?Pos(13, 35)
|
|
"Cannot reference stateful function `Chain.spend` in the definition of non-stateful function `fail1`.">>,
|
|
<<?Pos(14, 35)
|
|
"Cannot reference stateful function `local_spend` in the definition of non-stateful function `fail2`.">>,
|
|
<<?Pos(16, 15)
|
|
"Cannot reference stateful function `Chain.spend` in the definition of non-stateful function `fail3`.">>,
|
|
<<?Pos(20, 31)
|
|
"Cannot reference stateful function `Chain.spend` in the definition of non-stateful function `fail4`.">>,
|
|
<<?Pos(35, 47)
|
|
"Cannot reference stateful function `Chain.spend` in the definition of non-stateful function `fail5`.">>,
|
|
<<?Pos(48, 57)
|
|
"Cannot pass non-zero value argument `1000` in the definition of non-stateful function `fail6`.">>,
|
|
<<?Pos(49, 56)
|
|
"Cannot pass non-zero value argument `1000` in the definition of non-stateful function `fail7`.">>,
|
|
<<?Pos(52, 17)
|
|
"Cannot pass non-zero value argument `1000` in the definition of non-stateful function `fail8`.">>])
|
|
, ?TYPE_ERROR(bad_init_state_access,
|
|
[<<?Pos(11, 5)
|
|
"The `init` function should return the initial state as its result and cannot write the state, "
|
|
"but it calls\n"
|
|
" - `set_state` (at line 11, column 5), which calls\n"
|
|
" - `roundabout` (at line 8, column 38), which calls\n"
|
|
" - `put` (at line 7, column 39)">>,
|
|
<<?Pos(12, 5)
|
|
"The `init` function should return the initial state as its result and cannot read the state, "
|
|
"but it calls\n"
|
|
" - `new_state` (at line 12, column 5), which calls\n"
|
|
" - `state` (at line 5, column 29)">>,
|
|
<<?Pos(13, 13)
|
|
"The `init` function should return the initial state as its result and cannot read the state, "
|
|
"but it calls\n"
|
|
" - `state` (at line 13, column 13)">>])
|
|
, ?TYPE_ERROR(modifier_checks,
|
|
[<<?Pos(11, 3)
|
|
"The function `all_the_things` cannot be both public and private.">>,
|
|
<<?Pos(3, 3)
|
|
"Namespaces cannot contain entrypoints. Use `function` instead.">>,
|
|
<<?Pos(5, 10)
|
|
"The contract `Remote` has no entrypoints. Since Sophia version 3.2, "
|
|
"public contract functions must be declared with the `entrypoint` "
|
|
"keyword instead of `function`.">>,
|
|
<<?Pos(12, 3)
|
|
"The entrypoint `wha` cannot be private. Use `function` instead.">>,
|
|
<<?Pos(6, 3)
|
|
"Use `entrypoint` for declaration of `foo`: `entrypoint foo : () => unit`">>,
|
|
<<?Pos(10, 3)
|
|
"Use `entrypoint` instead of `function` for public function `foo`: `entrypoint foo() = ()`">>,
|
|
<<?Pos(6, 3)
|
|
"Use `entrypoint` instead of `function` for public function `foo`: `entrypoint foo : () => unit`">>])
|
|
, ?TYPE_ERROR(list_comp_not_a_list,
|
|
[<<?Pos(2, 36)
|
|
"Cannot unify `int` and `list('a)`\n"
|
|
"when checking rvalue of list comprehension binding `1 : int` against type `list('a)`">>
|
|
])
|
|
, ?TYPE_ERROR(list_comp_if_not_bool,
|
|
[<<?Pos(2, 44)
|
|
"Cannot unify `int` and `bool`\n"
|
|
"when checking the type of the expression `3 : int` against the expected type `bool`">>
|
|
])
|
|
, ?TYPE_ERROR(list_comp_bad_shadow,
|
|
[<<?Pos(2, 53)
|
|
"Cannot unify `string` and `int`\n"
|
|
"when checking the type of the pattern `x : int` against the expected type `string`">>
|
|
])
|
|
, ?TYPE_ERROR(map_as_map_key,
|
|
[<<?Pos(5, 47)
|
|
"Invalid key type `map(int, int)`\n"
|
|
"Map keys cannot contain other maps.">>,
|
|
<<?Pos(6, 31)
|
|
"Invalid key type `list(map(int, int))`\n"
|
|
"Map keys cannot contain other maps.">>,
|
|
<<?Pos(6, 31)
|
|
"Invalid key type `lm`\n"
|
|
"Map keys cannot contain other maps.">>])
|
|
, ?TYPE_ERROR(calling_init_function,
|
|
[<<?Pos(7, 28)
|
|
"The 'init' function is called exclusively by the create contract transaction "
|
|
"and cannot be called from the contract code.">>])
|
|
, ?TYPE_ERROR(bad_top_level_decl,
|
|
[<<?Pos(1, 1) "The definition of 'square' must appear inside a contract or namespace.">>])
|
|
, ?TYPE_ERROR(missing_event_type,
|
|
[<<?Pos(3, 5)
|
|
"Unbound variable `Chain.event`\n"
|
|
"Did you forget to define the event type?">>])
|
|
, ?TYPE_ERROR(bad_bytes_to_x,
|
|
[<<?Pos(3, 35)
|
|
"Cannot resolve length of byte array in\n"
|
|
" the result of a call to Bytes.to_fixed_size">>,
|
|
<<?Pos(4, 36)
|
|
"Cannot unify `bytes()` and `bytes(4)`\nwhen checking the application of\n"
|
|
" `Bytes.to_fixed_size : (bytes()) => option('a)`\n"
|
|
"to arguments\n"
|
|
" `b : bytes(4)`">>,
|
|
<<?Pos(4, 36)
|
|
"Cannot resolve length of byte array in\n"
|
|
" the result of a call to Bytes.to_fixed_size">>,
|
|
<<?Pos(5, 35)
|
|
"Cannot resolve length of byte array in\n"
|
|
" the first argument of a call to Bytes.to_any_size">>])
|
|
, ?TYPE_ERROR(bad_bytes_concat,
|
|
[<<?Pos(12, 40)
|
|
"Failed to resolve byte array lengths in call to Bytes.concat with arguments of type\n"
|
|
" - 'g (at line 12, column 20)\n"
|
|
" - 'h (at line 12, column 23)\n"
|
|
"and result type\n"
|
|
" - bytes(10) (at line 12, column 28)">>,
|
|
<<?Pos(13, 28)
|
|
"Failed to resolve byte array lengths in call to Bytes.concat with arguments of type\n"
|
|
" - 'd (at line 13, column 20)\n"
|
|
" - 'e (at line 13, column 23)\n"
|
|
"and result type\n"
|
|
" - 'f (at line 13, column 14)">>,
|
|
<<?Pos(15, 5)
|
|
"Cannot unify `bytes(26)` and `bytes(25)`\n"
|
|
"when checking the type of the expression `Bytes.concat(x, y) : bytes(26)` "
|
|
"against the expected type `bytes(25)`">>,
|
|
<<?Pos(17, 5)
|
|
"Failed to resolve byte array lengths in call to Bytes.concat with arguments of type\n"
|
|
" - bytes(6) (at line 16, column 24)\n"
|
|
" - 'b (at line 16, column 34)\n"
|
|
"and result type\n"
|
|
" - 'c (at line 16, column 39)">>,
|
|
<<?Pos(19, 25)
|
|
"Cannot resolve type of byte array in\n"
|
|
" the first argument of a call to Bytes.to_str">>])
|
|
, ?TYPE_ERROR(bad_bytes_split,
|
|
[<<?Pos(13, 5)
|
|
"Failed to resolve byte array lengths in call to Bytes.split with argument of type\n"
|
|
" - 'f (at line 12, column 20)\n"
|
|
"and result types\n"
|
|
" - 'e (at line 12, column 25)\n"
|
|
" - bytes(20) (at line 12, column 29)">>,
|
|
<<?Pos(16, 5)
|
|
"Failed to resolve byte array lengths in call to Bytes.split with argument of type\n"
|
|
" - bytes(15) (at line 15, column 24)\n"
|
|
"and result types\n"
|
|
" - 'c (at line 16, column 5)\n"
|
|
" - 'd (at line 16, column 5)">>,
|
|
<<?Pos(19, 5)
|
|
"Failed to resolve byte array lengths in call to Bytes.split with argument of type\n"
|
|
" - 'b (at line 18, column 20)\n"
|
|
"and result types\n"
|
|
" - bytes(20) (at line 18, column 25)\n"
|
|
" - 'a (at line 18, column 37)">>])
|
|
, ?TYPE_ERROR(wrong_compiler_version,
|
|
[<<?Pos(1, 1)
|
|
"Cannot compile with this version of the compiler, "
|
|
"because it does not satisfy the constraint ", Version/binary, " < 1.0">>,
|
|
<<?Pos(2, 1)
|
|
"Cannot compile with this version of the compiler, "
|
|
"because it does not satisfy the constraint ", Version/binary, " == 9.9.9">>])
|
|
, ?TYPE_ERROR(interface_with_defs,
|
|
[<<?Pos(2, 3)
|
|
"Contract interfaces cannot contain defined functions or entrypoints.\n"
|
|
"Fix: replace the definition of `foo` by a type signature.">>])
|
|
, ?TYPE_ERROR(contract_as_namespace,
|
|
[<<?Pos(5, 28)
|
|
"Invalid call to contract entrypoint `Foo.foo`.\n"
|
|
"It must be called as `c.foo` for some `c : Foo`.">>])
|
|
, ?TYPE_ERROR(empty_typedecl,
|
|
[<<?Pos(2, 8)
|
|
"Empty type declarations are not supported. "
|
|
"Type `t` lacks a definition">>])
|
|
, ?TYPE_ERROR(higher_kinded_type,
|
|
[<<?Pos(2, 35)
|
|
"Type `'m` is a higher kinded type variable "
|
|
"(takes another type as an argument)">>])
|
|
, ?TYPE_ERROR(bad_arity,
|
|
[<<?Pos(3, 20)
|
|
"Arity for id doesn't match. Expected 1, got 0">>,
|
|
<<?Pos(3, 25)
|
|
"Cannot unify `int` and `id`\n"
|
|
"when checking the type of the expression `123 : int` "
|
|
"against the expected type `id`">>,
|
|
<<?Pos(4, 20)
|
|
"Arity for id doesn't match. Expected 1, got 2">>,
|
|
<<?Pos(4, 35)
|
|
"Cannot unify `int` and `id(int, int)`\n"
|
|
"when checking the type of the expression `123 : int` "
|
|
"against the expected type `id(int, int)`">>])
|
|
, ?TYPE_ERROR(bad_unnamed_map_update_default,
|
|
[<<?Pos(4, 17)
|
|
"Invalid map update with default">>])
|
|
, ?TYPE_ERROR(non_functional_entrypoint,
|
|
[<<?Pos(2, 14)
|
|
"`f` was declared with an invalid type `int`. "
|
|
"Entrypoints and functions must have functional types">>])
|
|
, ?TYPE_ERROR(bad_records,
|
|
[<<?Pos(3, 16)
|
|
"Mixed record fields and map keys in `{x = 0, [0] = 1}`">>,
|
|
<<?Pos(4, 6)
|
|
"Mixed record fields and map keys in `r {x = 0, [0] = 1}`">>,
|
|
<<?Pos(5, 6)
|
|
"Empty record/map update `r {}`">>
|
|
])
|
|
, ?TYPE_ERROR(bad_protected_call,
|
|
[<<?Pos(6, 22)
|
|
"Invalid `protected` argument `(0 : int) == (1 : int) : bool`. "
|
|
"It must be either `true` or `false`.">>
|
|
])
|
|
, ?TYPE_ERROR(bad_function_block,
|
|
[<<?Pos(4, 5)
|
|
"Mismatch in the function block. Expected implementation/type declaration of g function">>,
|
|
<<?Pos(5, 5)
|
|
"Mismatch in the function block. Expected implementation/type declaration of g function">>
|
|
])
|
|
, ?TYPE_ERROR(just_an_empty_file,
|
|
[<<?Pos(0, 0)
|
|
"Empty contract">>
|
|
])
|
|
, ?TYPE_ERROR(bad_number_of_args,
|
|
[<<?Pos(3, 39)
|
|
"Cannot unify `() => unit` and `(int) => 'a`\n",
|
|
"when checking the application of\n"
|
|
" `f : () => unit`\n"
|
|
"to arguments\n"
|
|
" `1 : int`">>,
|
|
<<?Pos(4, 20)
|
|
"Cannot unify `(int, string) => 'e` and `(int) => 'd`\n"
|
|
"when checking the application of\n"
|
|
" `g : (int, string) => 'e`\n"
|
|
"to arguments\n"
|
|
" `1 : int`">>,
|
|
<<?Pos(5, 20)
|
|
"Cannot unify `(int, string) => 'c` and `(string) => 'b`\n"
|
|
"when checking the application of\n"
|
|
" `g : (int, string) => 'c`\n"
|
|
"to arguments\n"
|
|
" `\"Litwo, ojczyzno moja\" : string`">>
|
|
])
|
|
, ?TYPE_ERROR(bad_state,
|
|
[<<?Pos(4, 16)
|
|
"Conflicting updates for field 'foo'">>])
|
|
, ?TYPE_ERROR(factories_type_errors,
|
|
[<<?Pos(10,18)
|
|
"Chain.clone requires `ref` named argument of contract type.">>,
|
|
<<?Pos(11,18)
|
|
"Cannot unify `(gas : int, value : int, protected : bool) => if(protected, option(void), void)` and `(gas : int, value : int, protected : bool, int, bool) => if(protected, option(void), void)`\n"
|
|
"when checking contract construction of type\n"
|
|
" (gas : int, value : int, protected : bool) =>\n"
|
|
" if(protected, option(void), void) (at line 11, column 18)\n"
|
|
"against the expected type\n"
|
|
" (gas : int, value : int, protected : bool, int, bool) =>\n"
|
|
" if(protected, option(void), void)">>,
|
|
<<?Pos(11,18)
|
|
"Cannot unify `Bakoom` and `Kaboom`\n"
|
|
"when checking that contract construction of type\n"
|
|
" Bakoom\n"
|
|
"arising from resolution of variadic function `Chain.clone`\n"
|
|
"matches the expected type\n"
|
|
" Kaboom">>,
|
|
<<?Pos(12,37)
|
|
"Cannot unify `int` and `bool`\n"
|
|
"when checking named argument `gas : int` against inferred type `bool`">>,
|
|
<<?Pos(13,18),
|
|
"Kaboom is not implemented.\n"
|
|
"when resolving arguments of variadic function `Chain.create`">>,
|
|
<<?Pos(18,18)
|
|
"Cannot unify `(gas : int, value : int, protected : bool, int, bool) => if(protected, option(void), void)` and `(gas : int, value : int, protected : bool) => 'a`\n"
|
|
"when checking contract construction of type\n (gas : int, value : int, protected : bool, int, bool) =>\n if(protected, option(void), void) (at line 18, column 18)\nagainst the expected type\n (gas : int, value : int, protected : bool) => 'a">>,
|
|
<<?Pos(19,42),
|
|
"Named argument `protected` is not one of the expected named arguments\n - `value : int`">>,
|
|
<<?Pos(20,42),
|
|
"Cannot unify `int` and `bool`\n"
|
|
"when checking named argument `value : int` against inferred type `bool`">>
|
|
])
|
|
, ?TYPE_ERROR(ambiguous_main,
|
|
[<<?Pos(1,1)
|
|
"Could not deduce the main contract. You can point it out manually with the `main` keyword.">>
|
|
])
|
|
, ?TYPE_ERROR(no_main_contract,
|
|
[<<?Pos(0,0)
|
|
"No contract defined.">>
|
|
])
|
|
, ?TYPE_ERROR(multiple_main_contracts,
|
|
[<<?Pos(1,6)
|
|
"Only one main contract can be defined.">>
|
|
])
|
|
, ?TYPE_ERROR(using_namespace_ambiguous_name,
|
|
[ <<?Pos(13,23)
|
|
"Ambiguous name `A.f` could be one of\n"
|
|
" - `Xa.f` (at line 2, column 3)\n"
|
|
" - `Xb.f` (at line 5, column 3)">>
|
|
, <<?Pos(13,23)
|
|
"Unbound variable `A.f`">>
|
|
])
|
|
, ?TYPE_ERROR(using_namespace_wrong_scope,
|
|
[ <<?Pos(19,5)
|
|
"Unbound variable `f`">>
|
|
, <<?Pos(21,23)
|
|
"Unbound variable `f`">>
|
|
])
|
|
, ?TYPE_ERROR(using_namespace_undefined,
|
|
[<<?Pos(2,3)
|
|
"Cannot use undefined namespace MyUndefinedNamespace">>
|
|
])
|
|
, ?TYPE_ERROR(using_namespace_undefined_parts,
|
|
[<<?Pos(5,3)
|
|
"The namespace Nsp does not define the following names: a">>
|
|
])
|
|
, ?TYPE_ERROR(using_namespace_hidden_parts,
|
|
[<<?Pos(8,23)
|
|
"Unbound variable `g`">>
|
|
])
|
|
, ?TYPE_ERROR(stateful_pattern_guard,
|
|
[<<?Pos(8,12)
|
|
"Cannot reference stateful function `g` in a pattern guard.">>
|
|
])
|
|
, ?TYPE_ERROR(non_boolean_pattern_guard,
|
|
[<<?Pos(4,24)
|
|
"Cannot unify `string` and `bool`\n"
|
|
"when checking the type of the expression `\"y\" : string` "
|
|
"against the expected type `bool`">>
|
|
])
|
|
, ?TYPE_ERROR(empty_record_definition,
|
|
[<<?Pos(2,5)
|
|
"Empty record definitions are not allowed. Cannot define the record `r`">>
|
|
])
|
|
, ?TYPE_ERROR(operator_lambdas,
|
|
[<<?Pos(9,32)
|
|
"Cannot unify `(int, int) => int` and `(int) => 'a`\n"
|
|
"when checking the application of\n"
|
|
" `(l : _, r : _) => l + r : (int, int) => int`\n"
|
|
"to arguments\n"
|
|
" `1 : int`">>
|
|
])
|
|
, ?TYPE_ERROR(warnings,
|
|
[<<?Pos(0, 0)
|
|
"The file `Triple.aes` is included but not used.">>,
|
|
<<?Pos(13, 3)
|
|
"The function `h` is defined but never used.">>,
|
|
<<?Pos(19, 3)
|
|
"The type `unused_type` is defined but never used.">>,
|
|
<<?Pos(23, 54)
|
|
"Negative spend.">>,
|
|
<<?Pos(27, 9)
|
|
"The definition of `x` shadows an older definition at line 26, column 9.">>,
|
|
<<?Pos(30, 36)
|
|
"Division by zero.">>,
|
|
<<?Pos(32, 3)
|
|
"The function `unused_stateful` is unnecessarily marked as stateful.">>,
|
|
<<?Pos(35, 31)
|
|
"The variable `unused_arg` is defined but never used.">>,
|
|
<<?Pos(36, 9)
|
|
"The variable `unused_var` is defined but never used.">>,
|
|
<<?Pos(41, 3)
|
|
"The function `unused_function` is defined but never used.">>,
|
|
<<?Pos(42, 3)
|
|
"The function `recursive_unused_function` is defined but never used.">>,
|
|
<<?Pos(43, 3)
|
|
"The function `called_unused_function1` is defined but never used.">>,
|
|
<<?Pos(44, 3)
|
|
"The function `called_unused_function2` is defined but never used.">>,
|
|
<<?Pos(48, 5)
|
|
"Unused return value.">>,
|
|
<<?Pos(60, 5)
|
|
"The function `dec` is defined but never used.">>,
|
|
<<?Pos(73, 9)
|
|
"The definition of `const` shadows an older definition at line 70, column 3.">>,
|
|
<<?Pos(84, 7)
|
|
"The constant `c` is defined but never used.">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_contract_interface_recursive,
|
|
[<<?Pos(1,24)
|
|
"Trying to implement or extend an undefined interface `Z`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_contract_interface_same_name_different_type,
|
|
[<<?Pos(5,5)
|
|
"Cannot unify `char` and `int`\n"
|
|
"when implementing the entrypoint `f` from the interface `I1`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_contract_missing_implementation,
|
|
[<<?Pos(4,20)
|
|
"Unimplemented entrypoint `f` from the interface `I1` in the contract `I2`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_contract_same_decl_multi_interface,
|
|
[<<?Pos(7,10)
|
|
"Both interfaces `I` and `J` implemented by the contract `C` have a function called `f`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_contract_undefined_interface,
|
|
[<<?Pos(1,14)
|
|
"Trying to implement or extend an undefined interface `I`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_contract_same_name_different_type_multi_interface,
|
|
[<<?Pos(7,10)
|
|
"Both interfaces `I` and `J` implemented by the contract `C` have a function called `f`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_contract_interface_undefined_interface,
|
|
[<<?Pos(1,24)
|
|
"Trying to implement or extend an undefined interface `H`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_variance_switching,
|
|
[<<?Pos(36,49)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the application of\n"
|
|
" `g2 : (Cat) => Cat`\n"
|
|
"to arguments\n"
|
|
" `x : Animal`">>,
|
|
<<?Pos(39,43)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the type of the expression `g3(x) : Animal` against the expected type `Cat`">>,
|
|
<<?Pos(48,55)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the application of\n"
|
|
" `g5 : ((Animal) => Animal) => Cat`\n"
|
|
"to arguments\n"
|
|
" `x : (Cat) => Cat`">>,
|
|
<<?Pos(52,44)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the type of the expression `f6() : option(Animal)` against the expected type `option(Cat)`">>,
|
|
<<?Pos(73,43)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the type of the expression `some_animal : Animal` against the expected type `Cat`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_variance_switching_custom_types,
|
|
[<<?Pos(56,39)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_CONTRA(f_c_to_u) : dt_contra(Cat)` against the expected type `dt_contra(Animal)`">>,
|
|
<<?Pos(62,35)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the type of the expression `DT_CO(f_u_to_a) : dt_co(Animal)` against the expected type `dt_co(Cat)`">>,
|
|
<<?Pos(67,36)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the application of\n `DT_INV : ((Cat) => Cat) => dt_inv(Cat)`\nto arguments\n `f_c_to_a : (Cat) => Animal`">>,
|
|
<<?Pos(67,36)
|
|
"Cannot unify `Cat` and `Animal` in a invariant context\n"
|
|
"when checking the type of the expression `DT_INV(f_c_to_a) : dt_inv(Cat)` against the expected type `dt_inv(Animal)`">>,
|
|
<<?Pos(68,36)
|
|
"Cannot unify `Cat` and `Animal` in a invariant context\n"
|
|
"when checking the type of the expression `DT_INV(f_c_to_c) : dt_inv(Cat)` against the expected type `dt_inv(Animal)`">>,
|
|
<<?Pos(69,36)
|
|
"Cannot unify `Animal` and `Cat` in a invariant context\n"
|
|
"when checking the type of the expression `DT_INV(f_a_to_a) : dt_inv(Animal)` against the expected type `dt_inv(Cat)`">>,
|
|
<<?Pos(70,36)
|
|
"Cannot unify `Animal` and `Cat` in a invariant context\n"
|
|
"when checking the type of the expression `DT_INV(f_a_to_c) : dt_inv(Animal)` against the expected type `dt_inv(Cat)`">>,
|
|
<<?Pos(71,36)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the application of\n `DT_INV : ((Cat) => Cat) => dt_inv(Cat)`\nto arguments\n `f_c_to_a : (Cat) => Animal`">>,
|
|
<<?Pos(80,40)
|
|
"Cannot unify `Cat` and `Animal` in a invariant context\n"
|
|
"when checking the type of the expression `DT_INV_SEP_A(f_c_to_u) : dt_inv_sep(Cat)` against the expected type `dt_inv_sep(Animal)`">>,
|
|
<<?Pos(82,40)
|
|
"Cannot unify `Cat` and `Animal` in a invariant context\n"
|
|
"when checking the type of the expression `DT_INV_SEP_B(f_u_to_c) : dt_inv_sep(Cat)` against the expected type `dt_inv_sep(Animal)`">>,
|
|
<<?Pos(83,40)
|
|
"Cannot unify `Animal` and `Cat` in a invariant context\n"
|
|
"when checking the type of the expression `DT_INV_SEP_A(f_a_to_u) : dt_inv_sep(Animal)` against the expected type `dt_inv_sep(Cat)`">>,
|
|
<<?Pos(85,40)
|
|
"Cannot unify `Animal` and `Cat` in a invariant context\n"
|
|
"when checking the type of the expression `DT_INV_SEP_B(f_u_to_a) : dt_inv_sep(Animal)` against the expected type `dt_inv_sep(Cat)`">>,
|
|
<<?Pos(90,42)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the type of the expression `DT_CO_NEST_A(f_dt_contra_a_to_u) : dt_co_nest_a(Animal)` against the expected type `dt_co_nest_a(Cat)`">>,
|
|
<<?Pos(94,46)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_CONTRA_NEST_A(f_dt_co_c_to_u) : dt_contra_nest_a(Cat)` against the expected type `dt_contra_nest_a(Animal)`">>,
|
|
<<?Pos(99,46)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_CONTRA_NEST_B(f_u_to_dt_contra_c) : dt_contra_nest_b(Cat)` against the expected type `dt_contra_nest_b(Animal)`">>,
|
|
<<?Pos(105,42)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the type of the expression `DT_CO_NEST_B(f_u_to_dt_co_a) : dt_co_nest_b(Animal)` against the expected type `dt_co_nest_b(Cat)`">>,
|
|
<<?Pos(110,13)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the type of the pattern `vj3 : dt_co_twice(Cat)` against the expected type `dt_co_twice(Animal)`">>,
|
|
<<?Pos(114,59)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_A_CONTRA_B_CONTRA(f_a_to_c_to_u) : dt_a_contra_b_contra(Animal, Cat)` against the expected type `dt_a_contra_b_contra(Animal, Animal)`">>,
|
|
<<?Pos(115,59)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_A_CONTRA_B_CONTRA(f_c_to_a_to_u) : dt_a_contra_b_contra(Cat, Animal)` against the expected type `dt_a_contra_b_contra(Animal, Animal)`">>,
|
|
<<?Pos(116,59)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_A_CONTRA_B_CONTRA(f_c_to_c_to_u) : dt_a_contra_b_contra(Cat, Cat)` against the expected type `dt_a_contra_b_contra(Animal, Animal)`">>,
|
|
<<?Pos(116,59)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_A_CONTRA_B_CONTRA(f_c_to_c_to_u) : dt_a_contra_b_contra(Cat, Cat)` against the expected type `dt_a_contra_b_contra(Animal, Animal)`">>,
|
|
<<?Pos(119,59)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_A_CONTRA_B_CONTRA(f_c_to_a_to_u) : dt_a_contra_b_contra(Cat, Animal)` against the expected type `dt_a_contra_b_contra(Animal, Cat)`">>,
|
|
<<?Pos(120,59)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_A_CONTRA_B_CONTRA(f_c_to_c_to_u) : dt_a_contra_b_contra(Cat, Cat)` against the expected type `dt_a_contra_b_contra(Animal, Cat)`">>,
|
|
<<?Pos(122,59)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_A_CONTRA_B_CONTRA(f_a_to_c_to_u) : dt_a_contra_b_contra(Animal, Cat)` against the expected type `dt_a_contra_b_contra(Cat, Animal)`">>,
|
|
<<?Pos(124,59)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the expression `DT_A_CONTRA_B_CONTRA(f_c_to_c_to_u) : dt_a_contra_b_contra(Cat, Cat)` against the expected type `dt_a_contra_b_contra(Cat, Animal)`">>,
|
|
<<?Pos(131,13)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the pattern `vl2 : dt_contra_twice(Animal)` against the expected type `dt_contra_twice(Cat)`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_variance_switching_records,
|
|
[<<?Pos(27,13)
|
|
"Cannot unify `Animal` and `Cat` in a covariant context\n"
|
|
"when checking the type of the pattern `r03 : rec_co(Cat)` against the expected type `Main.rec_co(Animal)`">>,
|
|
<<?Pos(33,13)
|
|
"Cannot unify `Cat` and `Animal` in a contravariant context\n"
|
|
"when checking the type of the pattern `r06 : rec_contra(Animal)` against the expected type `Main.rec_contra(Cat)`">>,
|
|
<<?Pos(40,13)
|
|
"Cannot unify `Cat` and `Animal` in a invariant context\n"
|
|
"when checking the type of the pattern `r10 : rec_inv(Animal)` against the expected type `Main.rec_inv(Cat)`">>,
|
|
<<?Pos(41,13)
|
|
"Cannot unify `Animal` and `Cat` in a invariant context\n"
|
|
"when checking the type of the pattern `r11 : rec_inv(Cat)` against the expected type `Main.rec_inv(Animal)`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_variance_switching_chain_create_fail,
|
|
[<<?Pos(9,22)
|
|
"I is not implemented.\n"
|
|
"when resolving arguments of variadic function `Chain.create`">>,
|
|
<<?Pos(10,13)
|
|
"Cannot unify `I` and `C` in a covariant context\n"
|
|
"when checking the type of the pattern `c2 : C` against the expected type `I`">>,
|
|
<<?Pos(10,22)
|
|
"I is not implemented.\n"
|
|
"when resolving arguments of variadic function `Chain.create`">>,
|
|
<<?Pos(11,22)
|
|
"I is not implemented.\n"
|
|
"when resolving arguments of variadic function `Chain.create`">>
|
|
])
|
|
, ?TYPE_ERROR(missing_definition,
|
|
[<<?Pos(2,14)
|
|
"Missing definition of function `foo`">>
|
|
])
|
|
, ?TYPE_ERROR(child_with_decls,
|
|
[<<?Pos(2,14)
|
|
"Missing definition of function `f`">>
|
|
])
|
|
, ?TYPE_ERROR(parameterised_state,
|
|
[<<?Pos(3,8)
|
|
"The state type cannot be parameterized">>
|
|
])
|
|
, ?TYPE_ERROR(parameterised_event,
|
|
[<<?Pos(3,12)
|
|
"The event type cannot be parameterized">>
|
|
])
|
|
, ?TYPE_ERROR(missing_init_fun_alias_to_type,
|
|
[<<?Pos(1,10)
|
|
"Missing `init` function for the contract `AliasToType`.\n"
|
|
"The `init` function can only be omitted if the state type is `unit`">>
|
|
])
|
|
, ?TYPE_ERROR(missing_init_fun_alias_to_alias_to_type,
|
|
[<<?Pos(1,10)
|
|
"Missing `init` function for the contract `AliasToAliasToType`.\n"
|
|
"The `init` function can only be omitted if the state type is `unit`">>
|
|
])
|
|
, ?TYPE_ERROR(higher_order_entrypoint,
|
|
[<<?Pos(2,20)
|
|
"The argument\n"
|
|
" `f : (int) => int`\n"
|
|
"of entrypoint `apply` has a higher-order (contains function types) type">>
|
|
])
|
|
, ?TYPE_ERROR(higher_order_entrypoint_return,
|
|
[<<?Pos(2,3)
|
|
"The return type\n"
|
|
" `(int) => int`\n"
|
|
"of entrypoint `add` is higher-order (contains function types)">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphic_aens_resolve,
|
|
[<<?Pos(4,5)
|
|
"Invalid return type of `AENSv2.resolve`:\n"
|
|
" `'a`\n"
|
|
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
|
|
])
|
|
, ?TYPE_ERROR(bad_aens_resolve,
|
|
[<<?Pos(6,5)
|
|
"Invalid return type of `AENSv2.resolve`:\n"
|
|
" `list(int)`\n"
|
|
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
|
|
])
|
|
, ?TYPE_ERROR(bad_aens_resolve_using,
|
|
[<<?Pos(7,5)
|
|
"Invalid return type of `AENSv2.resolve`:\n"
|
|
" `list(int)`\n"
|
|
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
|
|
])
|
|
, ?TYPE_ERROR(var_args_unify_let,
|
|
[<<?Pos(3,9)
|
|
"Cannot infer types for variable argument list.\n"
|
|
"when checking the type of the pattern `x : 'a` against the expected type `(gas : int, value : int, protected : bool, ref : 'b, var_args) => 'b`">>
|
|
])
|
|
, ?TYPE_ERROR(var_args_unify_fun_call,
|
|
[<<?Pos(6,5)
|
|
"Cannot infer types for variable argument list.\n"
|
|
"when checking the application of\n"
|
|
" `g : (() => 'b) => 'b`\n"
|
|
"to arguments\n"
|
|
" `Chain.create : (value : int, var_args) => 'c`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_add_stateful_entrypoint,
|
|
[<<?Pos(5,25)
|
|
"`f` cannot be stateful because the entrypoint `f` in the interface `I` is not stateful">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_change_entrypoint_to_function,
|
|
[<<?Pos(6,14)
|
|
"`f` must be declared as an entrypoint instead of a function in order to implement the entrypoint `f` from the interface `I`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_non_payable_contract_implement_payable,
|
|
[<<?Pos(4,10)
|
|
"Non-payable contract `C` cannot implement payable interface `I`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_non_payable_interface_implement_payable,
|
|
[<<?Pos(4,20)
|
|
"Non-payable interface `H` cannot implement payable interface `I`">>
|
|
])
|
|
, ?TYPE_ERROR(polymorphism_remove_payable_entrypoint,
|
|
[<<?Pos(5,16)
|
|
"`f` must be payable because the entrypoint `f` in the interface `I` is payable">>
|
|
])
|
|
, ?TYPE_ERROR(calling_child_contract_entrypoint,
|
|
[<<?Pos(5,20)
|
|
"Invalid call to contract entrypoint `F.g`.\n"
|
|
"It must be called as `c.g` for some `c : F`.">>])
|
|
, ?TYPE_ERROR(using_contract_as_namespace,
|
|
[<<?Pos(5,3)
|
|
"Cannot use undefined namespace F">>])
|
|
, ?TYPE_ERROR(hole_expression,
|
|
[<<?Pos(5,13)
|
|
"Found a hole of type `bool`">>,
|
|
<<?Pos(6,17)
|
|
"Found a hole of type `string`">>,
|
|
<<?Pos(9,37)
|
|
"Found a hole of type `(int) => int`">>,
|
|
<<?Pos(13,20)
|
|
"Found a hole of type `'a`">>
|
|
])
|
|
, ?TYPE_ERROR(toplevel_constants_contract_as_namespace,
|
|
[<<?Pos(5,13)
|
|
"Invalid use of the contract constant `G.const`.\n"
|
|
"Toplevel contract constants can only be used in the contracts where they are defined.">>,
|
|
<<?Pos(10,11)
|
|
"Record type `G` does not have field `const`">>,
|
|
<<?Pos(10,11)
|
|
"Unbound field const">>,
|
|
<<?Pos(11,11)
|
|
"Record type `G` does not have field `const`">>,
|
|
<<?Pos(11,11)
|
|
"Unbound field const">>
|
|
])
|
|
, ?TYPE_ERROR(toplevel_constants_cycles,
|
|
[<<?Pos(2,21)
|
|
"Unbound variable `selfcycle`">>,
|
|
<<?Pos(4,5)
|
|
"Mutual recursion detected between the constants\n"
|
|
" - `cycle1` at line 4, column 5\n"
|
|
" - `cycle2` at line 5, column 5\n"
|
|
" - `cycle3` at line 6, column 5">>
|
|
])
|
|
, ?TYPE_ERROR(toplevel_constants_in_interface,
|
|
[<<?Pos(2,10)
|
|
"The name of the compile-time constant cannot have pattern matching">>,
|
|
<<?Pos(3,5)
|
|
"Cannot define toplevel constants inside a contract interface">>,
|
|
<<?Pos(4,5)
|
|
"Cannot define toplevel constants inside a contract interface">>
|
|
])
|
|
, ?TYPE_ERROR(toplevel_constants_invalid_expr,
|
|
[<<?Pos(10,9)
|
|
"Invalid expression in the definition of the constant `c01`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(11,9)
|
|
"Invalid expression in the definition of the constant `c02`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(12,9)
|
|
"Invalid expression in the definition of the constant `c03`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(13,9)
|
|
"Invalid expression in the definition of the constant `c04`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(14,9)
|
|
"Invalid expression in the definition of the constant `c05`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(17,9)
|
|
"Invalid expression in the definition of the constant `c07`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(18,9)
|
|
"Invalid expression in the definition of the constant `c08`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(19,9)
|
|
"Invalid expression in the definition of the constant `c09`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(20,9)
|
|
"Invalid expression in the definition of the constant `c10`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>,
|
|
<<?Pos(21,9)
|
|
"Invalid expression in the definition of the constant `c11`\n"
|
|
"You can only use the following expressions as constants: literals, lists, tuples, maps, and other constants">>
|
|
])
|
|
, ?TYPE_ERROR(toplevel_constants_invalid_id,
|
|
[<<?Pos(2,9)
|
|
"The name of the compile-time constant cannot have pattern matching">>,
|
|
<<?Pos(3,9)
|
|
"The name of the compile-time constant cannot have pattern matching">>
|
|
])
|
|
, ?TYPE_ERROR(too_many_tvars,
|
|
[<<?Pos(2,3)
|
|
"Too many type variables (max 256) in definition of `too_many`">>
|
|
])
|
|
].
|
|
|
|
validation_test_() ->
|
|
[{"Validation fail: " ++ C1 ++ " /= " ++ C2,
|
|
fun() ->
|
|
Actual = case validate(C1, C2) of
|
|
{error, Errs} -> Errs;
|
|
ok -> #{}
|
|
end,
|
|
check_errors(Expect, Actual)
|
|
end} || {C1, C2, Expect} <- validation_fails()] ++
|
|
[{"Validation of " ++ C,
|
|
fun() ->
|
|
?assertEqual(ok, validate(C, C))
|
|
end} || C <- compilable_contracts()].
|
|
|
|
validation_fails() ->
|
|
[{"deadcode", "nodeadcode",
|
|
[<<"Data error:\n"
|
|
"Byte code does not match source code.\n"
|
|
"- Functions in the source code but not in the byte code:\n"
|
|
" .MyList.map2">>]},
|
|
{"validation_test1", "validation_test2",
|
|
[<<"Data error:\n"
|
|
"Byte code does not match source code.\n"
|
|
"- The implementation of the function code_fail is different.\n"
|
|
"- The attributes of the function attr_fail differ:\n"
|
|
" Byte code: payable\n"
|
|
" Source code: \n"
|
|
"- The type of the function type_fail differs:\n"
|
|
" Byte code: integer => integer\n"
|
|
" Source code: {tvar,0} => {tvar,0}">>]},
|
|
{"validation_test1", "validation_test3",
|
|
[<<"Data error:\n"
|
|
"Byte code contract is not payable, but source code contract is.">>]}].
|
|
|
|
validate(Contract1, Contract2) ->
|
|
case compile(Contract1) of
|
|
ByteCode = #{ fate_code := FCode } ->
|
|
FCode1 = gmb_fate_code:serialize(gmb_fate_code:strip_init_function(FCode)),
|
|
Source = so_test_utils:read_contract(Contract2),
|
|
so_compiler:validate_byte_code(
|
|
ByteCode#{ byte_code := FCode1 }, Source,
|
|
case lists:member(Contract2, debug_mode_contracts()) of
|
|
true -> [debug_mode];
|
|
false -> []
|
|
end ++
|
|
[ {src_file, lists:concat([Contract2, ".aes"])}
|
|
, {include, {file_system, [so_test_utils:contract_path()]}}
|
|
]);
|
|
Error -> print_and_throw(Error)
|
|
end.
|
|
|
|
print_and_throw(Err) ->
|
|
case Err of
|
|
ErrBin when is_binary(ErrBin) ->
|
|
io:format("\n~s", [ErrBin]),
|
|
error(ErrBin);
|
|
Errors ->
|
|
io:format("Compilation error:\n~s", [string:join([so_errors:pp(E) || E <- Errors], "\n\n")]),
|
|
error(compilation_error)
|
|
end.
|