From b7b09745fefe5760d7783b68653a1aa66b1385fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 24 Mar 2014 17:48:11 +0100 Subject: compiler: Remove redundant clause in v3_codegen Multiple 'nil' cannot happen on instruction level. Map keys are always unique with literals. --- lib/compiler/src/v3_codegen.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index f1331d1fe7..3d25c6b764 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -1553,8 +1553,7 @@ map_pair_strip_and_termsort(Es) -> Ls = [{K,V}||{_,K,V}<-Es], lists:sort(fun ({{_,A},_}, {{_,B},_}) -> erts_internal:cmp_term(A,B) =< 0; ({nil,_}, {{_,B},_}) -> [] =< B; - ({{_,A},_}, {nil,_}) -> A =< []; - ({nil,_}, {nil,_}) -> true + ({{_,A},_}, {nil,_}) -> A =< [] end, Ls). %%% -- cgit v1.2.3 From b045e161da383cdba28a3c0cc184a900160e565c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 24 Mar 2014 18:42:47 +0100 Subject: compiler: Remove redudant code in v3_codegen --- lib/compiler/src/v3_codegen.erl | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index 3d25c6b764..47a357c23d 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -960,7 +960,6 @@ select_extract_map(Src, Vs, Fail, I, Vdb, Bef, St) -> end, {{[],[]},Bef}, Vs), Code = case {HasKs,GetVs} of - {[],[]} -> {[],Aft,St}; {HasKs,[]} -> [{test,has_map_fields,{f,Fail},Rsrc,{list,HasKs}}]; {[],GetVs} -> -- cgit v1.2.3 From df6c03de9f692489d757ae1437b8fb2dc6200c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 25 Mar 2014 16:07:39 +0100 Subject: compiler: map_pair cannot be a type clause in v3_life Map pairs are encapsulated in a map. --- lib/compiler/src/v3_life.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl index c4f54a7970..cd4b5fd674 100644 --- a/lib/compiler/src/v3_life.erl +++ b/lib/compiler/src/v3_life.erl @@ -324,8 +324,7 @@ type(k_binary) -> binary; type(k_bin_seg) -> bin_seg; type(k_bin_int) -> bin_int; type(k_bin_end) -> bin_end; -type(k_map) -> map; -type(k_map_pair) -> map_pair. +type(k_map) -> map. %% variable(Klit) -> Lit. %% var_list([Klit]) -> [Lit]. -- cgit v1.2.3 From 9e01993aac2cc35c77e5e246ed6e160c3485a456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 25 Mar 2014 18:01:07 +0100 Subject: compiler: Variable keys are not allowed in Maps No need to check for variables in Map keys. --- lib/compiler/src/v3_kernel.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index d3b785aa14..40d2f72b4c 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -581,8 +581,7 @@ map_key_clean(#k_literal{val=V}) -> {k_literal,V}; map_key_clean(#k_int{val=V}) -> {k_int,V}; map_key_clean(#k_float{val=V}) -> {k_float,V}; map_key_clean(#k_atom{val=V}) -> {k_atom,V}; -map_key_clean(#k_nil{}) -> k_nil; -map_key_clean(#k_var{name=V}) -> {k_var,V}. +map_key_clean(#k_nil{}) -> k_nil. %% call_type(Module, Function, Arity) -> call | bif | apply | error. -- cgit v1.2.3 From 71df02b2ead5c68eb9c4dff00d91a1d0e94659fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 25 Mar 2014 18:37:56 +0100 Subject: compiler: Throw 'nomatch' on matching with bad binary keys Even if a binary key is written as a literal the compiler may choose to make an expression. Emit a warning in those cases and saying the case will not match. This is a limitation in current implementation. --- lib/compiler/src/v3_core.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 04210ae243..46db9139c4 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -1595,7 +1595,9 @@ pattern_map_pair({map_field_exact,L,K,V}, St) -> {bin,L,Es0} -> case constant_bin(Es0) of error -> - throw(badmatch); + %% this will throw a cryptic error message + %% but it is better than nothing + throw(nomatch); Bin -> #c_literal{anno=lineno_anno(L,St),val=Bin} end; -- cgit v1.2.3 From 2d95280094fa6429081a9b9df3c73705819e2461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 25 Mar 2014 19:06:22 +0100 Subject: compiler: Do not evaluate map expressions with bad keys Map keys with large (non literal) binary keys must fail. --- lib/compiler/src/v3_core.erl | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'lib/compiler/src') diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 46db9139c4..a548ba2f7c 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -514,15 +514,26 @@ expr({tuple,L,Es0}, St0) -> expr({map,L,Es0}, St0) -> % erl_lint should make sure only #{ K => V } are allowed % in map construction. - {Es1,Eps,St1} = map_pair_list(Es0, St0), - A = lineno_anno(L, St1), - {ann_c_map(A,Es1),Eps,St1}; + try map_pair_list(Es0, St0) of + {Es1,Eps,St1} -> + A = lineno_anno(L, St1), + {ann_c_map(A,Es1),Eps,St1} + catch + throw:{bad_map,Warning} -> + St = add_warning(L, Warning, St0), + LineAnno = lineno_anno(L, St), + As = [#c_literal{anno=LineAnno,val=badarg}], + {#icall{anno=#a{anno=LineAnno}, %Must have an #a{} + module=#c_literal{anno=LineAnno,val=erlang}, + name=#c_literal{anno=LineAnno,val=error}, + args=As},[],St} + end; expr({map,L,M0,Es0}, St0) -> try expr_map(M0,Es0,lineno_anno(L, St0),St0) of {_,_,_}=Res -> Res catch - throw:bad_map -> - St = add_warning(L, bad_map, St0), + throw:{bad_map,Warning} -> + St = add_warning(L, Warning, St0), LineAnno = lineno_anno(L, St), As = [#c_literal{anno=LineAnno,val=badarg}], {#icall{anno=#a{anno=LineAnno}, %Must have an #a{} @@ -762,7 +773,7 @@ expr_map(M0,Es0,A,St0) -> {Es1,Eps,St2} = map_pair_list(Es0, St1), {ann_c_map(A,M1,Es1),Mps++Eps,St2} end; - false -> throw(bad_map) + false -> throw({bad_map,bad_map}) end. is_valid_map_src(#c_literal{val = M}) when is_map(M) -> true; @@ -774,18 +785,23 @@ 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), {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), {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}). + %% try_exception([ExcpClause], St) -> {[ExcpVar],Handler,St}. try_exception(Ecs0, St0) -> @@ -2301,6 +2317,8 @@ format_error(nomatch) -> "pattern cannot possibly match"; format_error(bad_binary) -> "binary construction will fail because of a type mismatch"; +format_error(bad_map_key) -> + "map construction will fail because of none literal key (large binaries are not literals)"; format_error(bad_map) -> "map construction will fail because of a type mismatch". -- cgit v1.2.3