From 6d7a1f9fe2029e1bc507d27413274284ac06d582 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 4 Dec 2021 18:14:05 +0200 Subject: [PATCH] Solve named argument constraints when record type dereferencing fails --- src/aeso_ast_infer_types.erl | 24 +++++++++++++++---- test/aeso_compiler_tests.erl | 1 + .../remote_call_ambiguous_record.aes | 11 +++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 test/contracts/remote_call_ambiguous_record.aes diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 11d970e..b34d005 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -2322,7 +2322,8 @@ solve_field_constraints(Env, Constraints) -> -spec solve_ambiguous_field_constraints(env(), [field_constraint()]) -> ok. solve_ambiguous_field_constraints(Env, Constraints) -> - Unknown = solve_known_record_types(Env, Constraints), + NamedArgConstraints = get_named_argument_constraints(), + Unknown = solve_known_record_types(Env, Constraints, NamedArgConstraints), if Unknown == [] -> ok; length(Unknown) < length(Constraints) -> %% progress! Keep trying. @@ -2347,10 +2348,23 @@ solve_unknown_record_types(Env, Unknown) -> false -> Solutions end. --spec solve_known_record_types(env(), [field_constraint()]) -> [field_constraint()]. -solve_known_record_types(Env, Constraints) -> +%% Since named argument constraints solving happens after field +%% constraints solving, try to find if dereferencing a record type +%% is failing due to unsolved named argument constraint +dereference_or_solve_named_argument_constraints(Env, RecType, Cs) -> + case dereference(RecType) of + UVar = {uvar, _, R} -> + L = [DT || DT = #dependent_type_constraint{specialized_type = {uvar, _, STR}} <- Cs, STR == R], + solve_named_argument_constraints(Env, L), + dereference(UVar); + Type -> + Type + end. + +-spec solve_known_record_types(env(), [field_constraint()], [named_argument_constraint()]) -> [field_constraint()]. +solve_known_record_types(Env, Constraints, NamedArgConstraints) -> DerefConstraints = - [ C#field_constraint{record_t = dereference(RecordType)} + [ C#field_constraint{record_t = dereference_or_solve_named_argument_constraints(Env, RecordType, NamedArgConstraints)} || C = #field_constraint{record_t = RecordType} <- Constraints ], SolvedConstraints = [begin @@ -2398,7 +2412,7 @@ destroy_and_report_unsolved_field_constraints(Env) -> OtherCs), {ContractCs, []} = lists:partition(fun(#is_contract_constraint{}) -> true; (_) -> false end, OtherCs1), - Unknown = solve_known_record_types(Env, FieldCs), + Unknown = solve_known_record_types(Env, FieldCs, []), if Unknown == [] -> ok; true -> case solve_unknown_record_types(Env, Unknown) of diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index 26a0c74..e5e646f 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -168,6 +168,7 @@ compilable_contracts() -> "maps", "oracles", "remote_call", + "remote_call_ambiguous_record", "simple", "simple_storage", "spend_test", diff --git a/test/contracts/remote_call_ambiguous_record.aes b/test/contracts/remote_call_ambiguous_record.aes new file mode 100644 index 0000000..915045f --- /dev/null +++ b/test/contracts/remote_call_ambiguous_record.aes @@ -0,0 +1,11 @@ +contract interface Coin = + entrypoint mint : () => int + +contract interface OtherCoin = + entrypoint mint : () => int + +main contract Main = + function mkCoin() : Coin = ct_11111111111111111111111111111115rHyByZ + entrypoint foo() : int = + let r = mkCoin() + r.mint()