diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f929b6..a926a1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Type definitions serialised to ACI as `typedefs` field instead of `type_defs` to increase compatibility. - Check contracts and entrypoints modifiers when implementing interfaces. +- Contracts can no longer be used as namespaces. ### Removed ### Fixed - Typechecker crashes if Chain.create or Chain.clone are used without arguments. diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 7b2a399..db8e4e3 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -229,7 +229,7 @@ force_bind_fun(X, Type, Env = #env{ what = What }) -> NoCode = get_option(no_code, false), Entry = if X == "init", What == contract, not NoCode -> {reserved_init, Ann, Type}; - What == contract_interface -> {contract_fun, Ann, Type}; + What == contract; What == contract_interface -> {contract_fun, Ann, Type}; true -> {Ann, Type} end, on_current_scope(Env, fun(Scope = #scope{ funs = Funs }) -> @@ -426,6 +426,7 @@ lookup_env(Env, Kind, Ann, Name) -> lookup_env1(#env{ namespace = Current, used_namespaces = UsedNamespaces, scopes = Scopes }, Kind, Ann, QName) -> Qual = lists:droplast(QName), Name = lists:last(QName), + QNameIsEvent = lists:suffix(["Chain", "event"], QName), AllowPrivate = lists:prefix(Qual, Current), %% Get the scope case maps:get(Qual, Scopes, false) of @@ -441,6 +442,8 @@ lookup_env1(#env{ namespace = Current, used_namespaces = UsedNamespaces, scopes {reserved_init, Ann1, Type} -> type_error({cannot_call_init_function, Ann}), {QName, {Ann1, Type}}; %% Return the type to avoid an extra not-in-scope error + {contract_fun, Ann1, Type} when AllowPrivate orelse QNameIsEvent -> + {QName, {Ann1, Type}}; {contract_fun, Ann1, Type} -> type_error({contract_treated_as_namespace, Ann, QName}), {QName, {Ann1, Type}}; @@ -1254,6 +1257,10 @@ check_usings(Env = #env{ used_namespaces = UsedNamespaces }, [{using, Ann, Con, create_type_errors(), type_error({using_undefined_namespace, Ann, qname(Con)}), destroy_and_report_type_errors(Env); + #scope{kind = contract} -> + create_type_errors(), + type_error({using_undefined_namespace, Ann, qname(Con)}), + destroy_and_report_type_errors(Env); Scope -> Nsp = case Parts of none -> diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index 81f2cef..1c724a5 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -1175,6 +1175,13 @@ failing_contracts() -> [<> ]) + , ?TYPE_ERROR(calling_child_contract_entrypoint, + [<>]) + , ?TYPE_ERROR(using_contract_as_namespace, + [<>]) ]. validation_test_() -> diff --git a/test/contracts/calling_child_contract_entrypoint.aes b/test/contracts/calling_child_contract_entrypoint.aes new file mode 100644 index 0000000..3e9f4c0 --- /dev/null +++ b/test/contracts/calling_child_contract_entrypoint.aes @@ -0,0 +1,5 @@ +contract F = + entrypoint g() = 1 + +main contract C = + entrypoint f() = F.g() diff --git a/test/contracts/using_contract_as_namespace.aes b/test/contracts/using_contract_as_namespace.aes new file mode 100644 index 0000000..61c1390 --- /dev/null +++ b/test/contracts/using_contract_as_namespace.aes @@ -0,0 +1,7 @@ +contract F = + entrypoint g() = 1 + +main contract C = + using F for [g] + + entrypoint f() = g() \ No newline at end of file