From f347eaee9059fdda18cb8401bac1d72129b51d22 Mon Sep 17 00:00:00 2001 From: Ulf Norell Date: Fri, 10 May 2019 14:04:01 +0200 Subject: [PATCH] Check for repeated argument names to functions (PT-159592825) --- src/aeso_ast_infer_types.erl | 13 ++++++++++++- test/aeso_compiler_tests.erl | 2 ++ test/contracts/type_errors.aes | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index f4eaf63..3f65c9b 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -862,7 +862,8 @@ infer_letrec(Env, Defs) -> [print_typesig(S) || S <- TypeSigs], {TypeSigs, NewDefs}. -infer_letfun(Env, {letfun, Attrib, {id, NameAttrib, Name}, Args, What, Body}) -> +infer_letfun(Env, {letfun, Attrib, Fun = {id, NameAttrib, Name}, Args, What, Body}) -> + check_unique_arg_names(Fun, Args), ArgTypes = [{ArgName, check_type(Env, arg_type(T))} || {arg, _, ArgName, T} <- Args], ExpectedType = check_type(Env, arg_type(What)), NewBody={typed, _, _, ResultType} = check_expr(bind_vars(ArgTypes, Env), Body, ExpectedType), @@ -873,6 +874,13 @@ infer_letfun(Env, {letfun, Attrib, {id, NameAttrib, Name}, Args, What, Body}) -> {{Name, TypeSig}, {letfun, Attrib, {id, NameAttrib, Name}, NewArgs, ResultType, NewBody}}. +check_unique_arg_names(Fun, Args) -> + Name = fun({arg, _, {id, _, X}, _}) -> X end, + Names = lists:map(Name, Args), + Dups = lists:usort(Names -- lists:usort(Names)), + [ type_error({repeated_arg, Fun, Arg}) || Arg <- Dups ], + ok. + print_typesig({Name, TypeSig}) -> ?PRINT_TYPES("Inferred ~s : ~s\n", [Name, pp(TypeSig)]). @@ -1929,6 +1937,9 @@ pp_error({include, {string, Pos, Name}}) -> pp_error({namespace, _Pos, {con, Pos, Name}, _Def}) -> io_lib:format("Nested namespace not allowed\nNamespace '~s' at ~s not defined at top level.\n", [Name, pp_loc(Pos)]); +pp_error({repeated_arg, Fun, Arg}) -> + io_lib:format("Repeated argument ~s to function ~s (at ~s).\n", + [Arg, pp(Fun), pp_loc(Fun)]); pp_error(Err) -> io_lib:format("Unknown error: ~p\n", [Err]). diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index dffb324..485793d 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -191,6 +191,8 @@ failing_contracts() -> " - r' (at line 5, column 10)">>, <<"Repeated name x in pattern\n" " x :: x (at line 26, column 7)">>, + <<"Repeated argument x to function repeated_arg (at line 44, column 12).">>, + <<"Repeated argument y to function repeated_arg (at line 44, column 12).">>, <<"No record type with fields y, z (at line 14, column 22)">>, <<"The field z is missing when constructing an element of type r2 (at line 15, column 24)">>, <<"Record type r2 does not have field y (at line 15, column 22)">>]} diff --git a/test/contracts/type_errors.aes b/test/contracts/type_errors.aes index d106686..ef4718e 100644 --- a/test/contracts/type_errors.aes +++ b/test/contracts/type_errors.aes @@ -40,3 +40,5 @@ contract Test = function type_error(r, x) = set_x(set_x(x, r), x) + + function repeated_arg(x : int, y, x : string, y : bool) : string = x