diff options
author | Björn-Egil Dahlberg <[email protected]> | 2014-11-28 02:42:46 +0100 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2014-12-01 16:41:13 +0100 |
commit | 56f9f62b59eda9dcc36bd47efef68b0243e0cfd1 (patch) | |
tree | ba7a8b0674c239fbeb7749377a10c9008aeb2940 | |
parent | aca180838c407296613c944dd6cd4df3fa1fe708 (diff) | |
download | otp-56f9f62b59eda9dcc36bd47efef68b0243e0cfd1.tar.gz otp-56f9f62b59eda9dcc36bd47efef68b0243e0cfd1.tar.bz2 otp-56f9f62b59eda9dcc36bd47efef68b0243e0cfd1.zip |
compiler: Coalesce map keys in dialyzer mode
This fixes a regression introduced in commit 805f9c89fc01220bc1bb0f27e1b68fd4eca688ba
The problem occured with map keys compiled with dialyzer option turned on.
In OTP 17, map keys needs to be literals.
-rw-r--r-- | lib/compiler/src/v3_core.erl | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index caf5298d38..59ec0d4199 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -786,23 +786,42 @@ is_valid_map_src(_) -> false. map_pair_list(Es, St) -> foldr(fun ({map_field_assoc,L,K0,V0}, {Ces,Esp,St0}) -> - {K,Ep0,St1} = safe(K0, St0), - ok = ensure_valid_map_key(K), + {K1,Ep0,St1} = safe(K0, St0), + K = ensure_valid_map_key(K1), {V,Ep1,St2} = safe(V0, St1), A = lineno_anno(L, St2), Pair = #c_map_pair{op=#c_literal{val=assoc},anno=A,key=K,val=V}, {[Pair|Ces],Ep0 ++ Ep1 ++ Esp,St2}; ({map_field_exact,L,K0,V0}, {Ces,Esp,St0}) -> - {K,Ep0,St1} = safe(K0, St0), - ok = ensure_valid_map_key(K), + {K1,Ep0,St1} = safe(K0, St0), + K = ensure_valid_map_key(K1), {V,Ep1,St2} = safe(V0, St1), A = lineno_anno(L, St2), Pair = #c_map_pair{op=#c_literal{val=exact},anno=A,key=K,val=V}, {[Pair|Ces],Ep0 ++ Ep1 ++ Esp,St2} end, {[],[],St}, Es). -ensure_valid_map_key(#c_literal{}) -> ok; -ensure_valid_map_key(_) -> throw({bad_map,bad_map_key}). +ensure_valid_map_key(K0) -> + case coalesced_map_key(K0) of + {ok,K1} -> K1; + error -> throw({bad_map,bad_map_key}) + end. + +coalesced_map_key(#c_literal{}=K) -> {ok,K}; +%% Dialyzer hack redux +%% DO coalesce tuples and list in maps for dialyzer +%% Dialyzer tries to break this apart, don't let it +coalesced_map_key(#c_tuple{}=K) -> + case core_lib:is_literal(K) of + true -> {ok,cerl:fold_literal(K)}; + false -> error + end; +coalesced_map_key(#c_cons{}=K) -> + case core_lib:is_literal(K) of + true -> {ok,cerl:fold_literal(K)}; + false -> error + end; +coalesced_map_key(_) -> error. %% try_exception([ExcpClause], St) -> {[ExcpVar],Handler,St}. @@ -1606,17 +1625,23 @@ pattern_alias_map_pair_patterns([Cv]) -> Cv; pattern_alias_map_pair_patterns([Cv1,Cv2|Cvs]) -> pattern_alias_map_pair_patterns([pat_alias(Cv1,Cv2)|Cvs]). -pattern_map_pair({map_field_exact,L,K,V}, St) -> +pattern_map_pair({map_field_exact,L,K,V},St) -> + #c_map_pair{anno=lineno_anno(L, St), + op=#c_literal{val=exact}, + key=pattern_map_key(K,St), + val=pattern(V, St)}. + +pattern_map_key(K,St) -> + %% Throws 'nomatch' if the key can't be a literal + %% this will be a cryptic error message but it is better than nothing case expr(K,St) of - {#c_literal{}=Key,_,_} -> - #c_map_pair{anno=lineno_anno(L, St), - op=#c_literal{val=exact}, - key=Key, - val=pattern(V, St)}; - _ -> - %% this will throw a cryptic error message - %% but it is better than nothing - throw(nomatch) + {Key0,[],_} -> + %% Dialyzer hack redux + case coalesced_map_key(Key0) of + {ok,Key1} -> Key1; + error -> throw(nomatch) + end; + _ -> throw(nomatch) end. %% pat_bin([BinElement], State) -> [BinSeg]. |