From c98ea25e8bdaeeacab498d9d376002ea5356562b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 4 Aug 2022 00:24:22 +0400 Subject: [PATCH] Fix: Get the type of Chain.create() from its application (#407) * Get the type of Chain.create() from its application * Add test contract * Update CHANGELOG.md * Update the tests * Update tests again --- CHANGELOG.md | 2 ++ src/aeso_ast_to_fcode.erl | 2 +- test/aeso_compiler_tests.erl | 15 ++++++++++ ...rphism_variance_switching_chain_create.aes | 29 +++++++++++++++++++ ...m_variance_switching_chain_create_fail.aes | 12 ++++++++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 test/contracts/polymorphism_variance_switching_chain_create.aes create mode 100644 test/contracts/polymorphism_variance_switching_chain_create_fail.aes diff --git a/CHANGELOG.md b/CHANGELOG.md index eb15d90..dca4e56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### Changed ### Removed +### Fixed +- [404](https://github.com/aeternity/aesophia/issues/404) Contract polymorphism crashes on non-obvious child contract typing. ## [7.0.0] ### Added diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index a4f7ce6..1cb00fe 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -693,7 +693,7 @@ expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) -> end; %% Function calls -expr_to_fcode(Env, Type, {app, _, Fun = {typed, _, FunE, {fun_t, _, NamedArgsT, ArgsT, _}}, Args}) -> +expr_to_fcode(Env, _, {app, _, Fun = {typed, _, FunE, {fun_t, _, NamedArgsT, ArgsT, Type}}, Args}) -> Args1 = get_named_args(NamedArgsT, Args), FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1], case expr_to_fcode(Env, Fun) of diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index a10c885..57b25b4 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -202,6 +202,7 @@ compilable_contracts() -> "polymorphism_contract_interface_extensions", "polymorphism_contract_interface_same_decl_multi_interface", "polymorphism_contract_interface_same_name_same_type", + "polymorphism_variance_switching_chain_create", "missing_init_fun_state_unit", "complex_compare_leq", "complex_compare", @@ -1025,6 +1026,20 @@ failing_contracts() -> "Cannot unify `Animal` and `Cat` in a covariant context\n" "when checking the type of the pattern `q15 : oracle_query(Cat, Cat)` against the expected type `oracle_query(Cat, Animal)`">> ]) + , ?TYPE_ERROR(polymorphism_variance_switching_chain_create_fail, + [<>, + <>, + <>, + <> + ]) , ?TYPE_ERROR(missing_definition, [<> diff --git a/test/contracts/polymorphism_variance_switching_chain_create.aes b/test/contracts/polymorphism_variance_switching_chain_create.aes new file mode 100644 index 0000000..14c5f0b --- /dev/null +++ b/test/contracts/polymorphism_variance_switching_chain_create.aes @@ -0,0 +1,29 @@ +contract interface I = + entrypoint f : () => int + +contract C1 : I = + entrypoint f() = 123 + +contract C2 : I = + entrypoint f() = 888 + +namespace Make = + stateful function new1() : I = Chain.create() : C1 + stateful function new2() : I = Chain.create() : C2 + + stateful function new(c : I) : int = c.f() + +main contract Main = + stateful entrypoint test1() = + let c = Make.new1() + Make.new(c) + + stateful entrypoint test2() = + let c = Make.new2() + Make.new(c) + + stateful entrypoint test3() = + let c1 = Chain.create() : C1 // succeeds + let c2 : I = Chain.create() : C1 // succeeds + let c3 : C1 = Chain.create() // succeeds + () diff --git a/test/contracts/polymorphism_variance_switching_chain_create_fail.aes b/test/contracts/polymorphism_variance_switching_chain_create_fail.aes new file mode 100644 index 0000000..836c9e1 --- /dev/null +++ b/test/contracts/polymorphism_variance_switching_chain_create_fail.aes @@ -0,0 +1,12 @@ +contract interface I = + entrypoint f : () => int + +contract C : I = + entrypoint f() = 123 + +main contract Main = + stateful entrypoint test() = + let c1 : I = Chain.create() // fails + let c2 : C = Chain.create() : I // fails + let c3 = Chain.create() : I // fails + () \ No newline at end of file