From 86d7b36ba751002f534479f005ef220963184878 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Mon, 17 Jul 2023 13:32:11 +0300 Subject: [PATCH] Unify typesigs when implementing interface funs (#469) --- CHANGELOG.md | 1 + src/aeso_ast_infer_types.erl | 19 +++++++++++++------ test/aeso_compiler_tests.erl | 8 ++++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 998354f..52bf16f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed ### Removed ### Fixed +- Fixed a bug with polymorphism that allowed functions with the same name but different type to be considered as implementations for their corresponding interface function. ## [7.2.1] ### Fixed diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 6a71813..d74358b 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -1582,7 +1582,7 @@ check_reserved_entrypoints(Funs) -> check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type = {fun_t, _, _, _, _}}) -> Type1 = {fun_t, _, Named, Args, Ret} = check_type(Env, Type), TypeSig = {type_sig, Ann, none, Named, Args, Ret}, - register_implementation(Id, TypeSig), + register_implementation(Env, Id, TypeSig), {{Name, TypeSig}, {fun_decl, Ann, Id, Type1}}; check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) -> type_error({fundecl_must_have_funtype, Ann, Id, Type}), @@ -1590,13 +1590,16 @@ check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) -> %% Register the function FunId as implemented by deleting it from the functions %% to be implemented table if it is included there, or return true otherwise. --spec register_implementation(FunId, FunSig) -> true | no_return() when +-spec register_implementation(env(), FunId, FunSig) -> true | no_return() when FunId :: aeso_syntax:id(), FunSig :: typesig(). -register_implementation(Id, Sig) -> +register_implementation(Env, Id, Sig) -> Name = name(Id), case ets_lookup(functions_to_implement, Name) of - [{Name, Interface, Decl = {fun_decl, _, DeclId, _}}] -> + [{Name, Interface, Decl = {fun_decl, _, DeclId, FunT}}] -> + When = {implement_interface_fun, aeso_syntax:get_ann(Sig), Name, name(Interface)}, + unify(Env, typesig_to_fun_t(Sig), FunT, When), + DeclStateful = aeso_syntax:get_ann(stateful, Decl, false), DeclPayable = aeso_syntax:get_ann(payable, Decl, false), @@ -1624,7 +1627,7 @@ infer_nonrec(Env, LetFun) -> create_constraints(), NewLetFun = {{_, Sig}, _} = infer_letfun(Env, LetFun), check_special_funs(Env, NewLetFun), - register_implementation(get_letfun_id(LetFun), Sig), + register_implementation(Env, get_letfun_id(LetFun), Sig), solve_then_destroy_and_report_unsolved_constraints(Env), Result = {TypeSig, _} = instantiate(NewLetFun), print_typesig(TypeSig), @@ -1654,7 +1657,7 @@ infer_letrec(Env, Defs) -> Inferred = [ begin Res = {{Name, TypeSig}, LetFun} = infer_letfun(ExtendEnv, LF), - register_implementation(get_letfun_id(LetFun), TypeSig), + register_implementation(Env, get_letfun_id(LetFun), TypeSig), Got = proplists:get_value(Name, Funs), Expect = typesig_to_fun_t(TypeSig), unify(Env, Got, Expect, {check_typesig, Name, Got, Expect}), @@ -4165,6 +4168,10 @@ pp_when({var_args, Ann, Fun}) -> {pos(Ann) , io_lib:format("when resolving arguments of variadic function `~s`", [pp_expr(Fun)]) }; +pp_when({implement_interface_fun, Ann, Entrypoint, Interface}) -> + { pos(Ann) + , io_lib:format("when implementing the entrypoint `~s` from the interface `~s`", [Entrypoint, Interface]) + }; pp_when(unknown) -> {pos(0,0), ""}. -spec pp_why_record(why_record()) -> {pos(), iolist()}. diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index ed50821..fc47629 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -871,10 +871,10 @@ failing_contracts() -> "Trying to implement or extend an undefined interface `Z`">> ]) , ?TYPE_ERROR(polymorphism_contract_interface_same_name_different_type, - [<>]) + [<> + ]) , ?TYPE_ERROR(polymorphism_contract_missing_implementation, [<>