From 55e5482e8471dfc011bdd907a21cb8131a113dba Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 22 Jun 2022 19:41:36 +0400 Subject: [PATCH] Move invalid_aens_resolve_type error to type checker --- src/aeso_ast_infer_types.erl | 34 +++++++++++++++++-- src/aeso_ast_to_fcode.erl | 11 ------ src/aeso_code_errors.erl | 6 ---- test/aeso_compiler_tests.erl | 22 +++++++----- .../{code_errors => }/bad_aens_resolve.aes | 0 .../polymorphic_aens_resolve.aes | 0 6 files changed, 45 insertions(+), 28 deletions(-) rename test/contracts/{code_errors => }/bad_aens_resolve.aes (100%) rename test/contracts/{code_errors => }/polymorphic_aens_resolve.aes (100%) diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 1ca4fc5..8ba9ad1 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -87,7 +87,9 @@ -type byte_constraint() :: {is_bytes, utype()} | {add_bytes, aeso_syntax:ann(), concat | split, utype(), utype(), utype()}. --type constraint() :: named_argument_constraint() | field_constraint() | byte_constraint(). +-type aens_resolve_constraint() :: {aens_resolve_type, utype()}. + +-type constraint() :: named_argument_constraint() | field_constraint() | byte_constraint() | aens_resolve_constraint(). -record(field_info, { ann :: aeso_syntax:ann() @@ -1818,6 +1820,8 @@ infer_expr(Env, {app, Ann, Fun, Args0} = App) -> ResultType = fresh_uvar(Ann), unify(Env, FunType, {fun_t, [], NamedArgsVar, ArgTypes, GeneralResultType}, When), when_warning(warn_negative_spend, fun() -> warn_potential_negative_spend(Ann, NewFun1, NewArgs) end), + [ add_constraint({aens_resolve_type, GeneralResultType}) + || element(3, Fun) =:= ["AENS", "resolve"] ], add_constraint( #dependent_type_constraint{ named_args_t = NamedArgsVar, named_args = NamedArgs1, @@ -2338,11 +2342,15 @@ destroy_and_report_unsolved_constraints(Env) -> (#named_argument_constraint{}) -> true; (_) -> false end, OtherCs2), - {BytesCs, []} = + {BytesCs, OtherCs4} = lists:partition(fun({is_bytes, _}) -> true; ({add_bytes, _, _, _, _, _}) -> true; (_) -> false end, OtherCs3), + {AensResolveCs, []} = + lists:partition(fun({aens_resolve_type, _}) -> true; + (_) -> false + end, OtherCs4), Unsolved = [ S || S <- [ solve_constraint(Env, dereference_deep(C)) || C <- NamedArgCs ], S == unsolved ], @@ -2360,6 +2368,7 @@ destroy_and_report_unsolved_constraints(Env) -> check_record_create_constraints(Env, CreateCs), check_is_contract_constraints(Env, ContractCs), check_bytes_constraints(Env, BytesCs), + check_aens_resolve_constraints(Env, AensResolveCs), destroy_constraints(). @@ -2489,6 +2498,21 @@ check_bytes_constraint(Env, {add_bytes, Ann, Fun, A0, B0, C0}) -> _ -> type_error({unsolved_bytes_constraint, Ann, Fun, A, B, C}) end. +check_aens_resolve_constraints(_Env, []) -> + ok; +check_aens_resolve_constraints(Env, [{aens_resolve_type, Type} | Rest]) -> + Type1 = unfold_types_in_type(Env, instantiate(Type)), + {app_t, _, {id, _, "option"}, [Type2]} = Type1, + case Type2 of + {id, _, "string"} -> ok; + {id, _, "address"} -> ok; + {con, _, _} -> ok; + {app_t, _, {id, _, "oracle"}, [_, _]} -> ok; + {app_t, _, {id, _, "oracle_query"}, [_, _]} -> ok; + _ -> type_error({invalid_aens_resolve_type, aeso_syntax:get_ann(Type), Type2}) + end, + check_aens_resolve_constraints(Env, Rest). + %% -- Field constraints -- check_record_create_constraints(_, []) -> ok; @@ -3558,6 +3582,12 @@ mk_error({higher_order_entrypoint, Ann, {id, _, Name}, Thing}) -> Msg = io_lib:format("The ~sof entrypoint `~s` ~s", [ThingS, Name, Bad]), mk_t_err(pos(Ann), Msg); +mk_error({invalid_aens_resolve_type, Ann, T}) -> + Msg = io_lib:format("Invalid return type of `AENS.resolve`:\n" + "~s`\n" + "It must be a `string` or a pubkey type (`address`, `oracle`, etc)", + [pp_type(" `", T)]), + mk_t_err(pos(Ann), Msg); mk_error(Err) -> Msg = io_lib:format("Unknown error: ~p", [Err]), mk_t_err(pos(0, 0), Msg). diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 036d976..5adecf2 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -551,7 +551,6 @@ expr_to_fcode(Env, Type, {qid, Ann, X}) -> {builtin_u, B = aens_resolve, Ar} -> {fun_t, _, _, _, ResType} = Type, AensType = type_to_fcode(Env, ResType), - validate_aens_resolve_type(Ann, ResType, AensType), TypeArgs = [{lit, {typerep, AensType}}], {builtin_u, B, Ar, TypeArgs}; {builtin_u, B = bytes_split, Ar} -> @@ -811,16 +810,6 @@ validate_oracle_type(Ann, Type, QType, RType) -> ensure_first_order(RType, {invalid_oracle_type, higher_order, response, Ann, Type}), ok. -validate_aens_resolve_type(Ann, {app_t, _, _, [Type]}, {variant, [[], [FType]]}) -> - case FType of - string -> ok; - address -> ok; - contract -> ok; - {oracle, _, _} -> ok; - oracle_query -> ok; - _ -> fcode_error({invalid_aens_resolve_type, Ann, Type}) - end. - ensure_monomorphic(Type, Err) -> case is_monomorphic(Type) of true -> ok; diff --git a/src/aeso_code_errors.erl b/src/aeso_code_errors.erl index 8418838..a87631f 100644 --- a/src/aeso_code_errors.erl +++ b/src/aeso_code_errors.erl @@ -10,12 +10,6 @@ -export([format/1, pos/1]). -format({invalid_aens_resolve_type, Ann, T}) -> - Msg = io_lib:format("Invalid return type of AENS.resolve:\n" - "~s\n" - "It must be a string or a pubkey type (address, oracle, etc).", - [pp_type(2, T)]), - mk_err(pos(Ann), Msg); format({invalid_oracle_type, Why, What, Ann, Type}) -> WhyS = case Why of higher_order -> "higher-order (contain function types)"; polymorphic -> "polymorphic (contain type variables)" end, diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index e2299cd..352b04c 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -1058,6 +1058,18 @@ failing_contracts() -> " `(int) => int`\n" "of entrypoint `add` is higher-order (contains function types)">> ]) + , ?TYPE_ERROR(polymorphic_aens_resolve, + [<> + ]) + , ?TYPE_ERROR(bad_aens_resolve, + [<> + ]) ]. -define(Path(File), "code_errors/" ??File). @@ -1066,15 +1078,7 @@ failing_contracts() -> -define(FATE_ERR(File, Line, Col, Err), {?Path(File), ?Msg(File, Line, Col, Err)}). failing_code_gen_contracts() -> - [ ?FATE_ERR(polymorphic_aens_resolve, 4, 5, - "Invalid return type of AENS.resolve:\n" - " 'a\n" - "It must be a string or a pubkey type (address, oracle, etc).") - , ?FATE_ERR(bad_aens_resolve, 6, 5, - "Invalid return type of AENS.resolve:\n" - " list(int)\n" - "It must be a string or a pubkey type (address, oracle, etc).") - , ?FATE_ERR(polymorphic_query_type, 3, 5, + [ ?FATE_ERR(polymorphic_query_type, 3, 5, "Invalid oracle type\n" " oracle('a, 'b)\n" "The query type must not be polymorphic (contain type variables).") diff --git a/test/contracts/code_errors/bad_aens_resolve.aes b/test/contracts/bad_aens_resolve.aes similarity index 100% rename from test/contracts/code_errors/bad_aens_resolve.aes rename to test/contracts/bad_aens_resolve.aes diff --git a/test/contracts/code_errors/polymorphic_aens_resolve.aes b/test/contracts/polymorphic_aens_resolve.aes similarity index 100% rename from test/contracts/code_errors/polymorphic_aens_resolve.aes rename to test/contracts/polymorphic_aens_resolve.aes