diff options
author | Björn-Egil Dahlberg <[email protected]> | 2013-09-24 15:22:41 +0200 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2014-01-28 15:56:25 +0100 |
commit | be782d05bcd259b229efcac47c0566e4026cf1f6 (patch) | |
tree | c8c6a6979cd1bdc4346e5bd693868bb7796e8b49 | |
parent | 08a9a9a7113d310de2e6511d898a06cb8a559ce8 (diff) | |
download | otp-be782d05bcd259b229efcac47c0566e4026cf1f6.tar.gz otp-be782d05bcd259b229efcac47c0566e4026cf1f6.tar.bz2 otp-be782d05bcd259b229efcac47c0566e4026cf1f6.zip |
compiler: Check for duplicate key literals in Map
If a literal key already is present in a Map update the latter should be used.
Warn for previous duplicates in the Map.
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 672a8b94c0..cdbe2d0753 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -418,8 +418,31 @@ expr(#c_try{anno=A,arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=Try, _, Sub0) expr_list(Es, Ctxt, Sub) -> [expr(E, Ctxt, Sub) || E <- Es]. +%% traverse pairs in reverse +%% - remove later literals since they will be overwritten. + pair_list(Es, Ctxt, Sub) -> - [pair(E, Ctxt, Sub) || E <- Es]. + pair_list_reversed(lists:reverse(Es), Ctxt, Sub, [], gb_sets:empty()). + +pair_list_reversed([],_,_,Es,_) -> Es; +pair_list_reversed([E|Es],Ctxt,Sub,Out,Keys) -> + Pair = pair(E,Ctxt,Sub), + case map_has_key(Pair,Keys) of + {false,Keys1} -> + pair_list_reversed(Es,Ctxt,Sub,[Pair|Out],Keys1); + {true,K} -> + add_warning(E, {map_pair_key_overloaded,K}), + pair_list_reversed(Es,Ctxt,Sub,Out,Keys) + end. + +%% check if key already is present in map, i.e. #{ a=>1, a=>2 } +%% where 'a' is duplicate. Update maps set with the key if not present. + +map_has_key(#c_map_pair{key=#c_literal{val=K}},Ks) -> + case gb_sets:is_element(K,Ks) of + false -> {false, gb_sets:add(K,Ks)}; + true -> {true, K} + end. pair(#c_map_pair{key=K,val=V}, effect, Sub) -> make_effect_seq([K,V], Sub); @@ -697,7 +720,7 @@ useless_call(effect, #c_call{anno=Anno, useless_call(_, _) -> no. %% make_effect_seq([Expr], Sub) -> #c_seq{}|void() -%% Convert a list of epressions evaluated in effect context to a chain of +%% Convert a list of expressions evaluated in effect context to a chain of %% #c_seq{}. The body in the innermost #c_seq{} will be void(). %% Anything that will not have any effect will be thrown away. @@ -3019,6 +3042,9 @@ format_error(result_ignored) -> "(suppress the warning by assigning the expression to the _ variable)"; format_error(useless_building) -> "a term is constructed, but never used"; +format_error({map_pair_key_overloaded,K}) -> + M = io_lib:format("the key ~p is used multiple times in map value association",[K]), + flatten(M); format_error(bin_opt_alias) -> "INFO: the '=' operator will prevent delayed sub binary optimization"; format_error(bin_partition) -> |