diff options
author | Björn-Egil Dahlberg <[email protected]> | 2016-11-23 10:43:35 +0100 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2016-11-23 15:02:04 +0100 |
commit | 975af37806ff0aa422c54444095d57399b5e0474 (patch) | |
tree | 99747edb2c82455bd1995d23cb82adf1f71cd939 /lib/compiler/src | |
parent | 9491f6727f12e37241863bd5becbd1f336ff7659 (diff) | |
download | otp-975af37806ff0aa422c54444095d57399b5e0474.tar.gz otp-975af37806ff0aa422c54444095d57399b5e0474.tar.bz2 otp-975af37806ff0aa422c54444095d57399b5e0474.zip |
compiler: Warn for repeated identical map keys
A map expression such as,
#{'a' => 1, 'b' => 2, 'a' => 3}
will produce a warning for the repeated key 'a'.
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/v3_core.erl | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index f40cf97f57..14cd41ae27 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -883,19 +883,33 @@ badmap_term(Map, #core{in_guard=false}) -> c_tuple([#c_literal{val=badmap},Map]). map_build_pairs(Map, Es0, Ann, St0) -> - {Es,Pre,St1} = map_build_pairs_1(Es0, St0), + {Es,Pre,_,St1} = map_build_pairs_1(Es0, cerl_sets:new(), St0), {ann_c_map(Ann, Map, Es),Pre,St1}. -map_build_pairs_1([{Op0,L,K0,V0}|Es], St0) -> +map_build_pairs_1([{Op0,L,K0,V0}|Es], Used0, St0) -> {K,Pre0,St1} = safe(K0, St0), {V,Pre1,St2} = safe(V0, St1), - {Pairs,Pre2,St3} = map_build_pairs_1(Es, St2), + {Pairs,Pre2,Used1,St3} = map_build_pairs_1(Es, Used0, St2), As = lineno_anno(L, St3), Op = map_op(Op0), + {Used2,St4} = maybe_warn_repeated_keys(K, L, Used1, St3), Pair = cerl:ann_c_map_pair(As, Op, K, V), - {[Pair|Pairs],Pre0++Pre1++Pre2,St3}; -map_build_pairs_1([], St) -> - {[],[],St}. + {[Pair|Pairs],Pre0++Pre1++Pre2,Used2,St4}; +map_build_pairs_1([], Used, St) -> + {[],[],Used,St}. + +maybe_warn_repeated_keys(Ck,Line,Used,St) -> + case cerl:is_literal(Ck) of + false -> {Used,St}; + true -> + K = cerl:concrete(Ck), + case cerl_sets:is_element(K,Used) of + true -> + {Used, add_warning(Line, {map_key_repeated,K}, St)}; + false -> + {cerl_sets:add_element(K,Used), St} + end + end. map_op(map_field_assoc) -> #c_literal{val=assoc}; map_op(map_field_exact) -> #c_literal{val=exact}. @@ -2603,7 +2617,11 @@ format_error(nomatch) -> format_error(bad_binary) -> "binary construction will fail because of a type mismatch"; format_error(badmap) -> - "map construction will fail because of a type mismatch". + "map construction will fail because of a type mismatch"; +format_error({map_key_repeated,Key}) when is_atom(Key) -> + io_lib:format("key '~w' will be overridden in expression", [Key]); +format_error({map_key_repeated,Key}) -> + io_lib:format("key ~p will be overridden in expression", [Key]). add_warning(Anno, Term, #core{ws=Ws,file=[{file,File}]}=St) -> case erl_anno:generated(Anno) of |