aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-08-10 07:43:31 +0200
committerBjörn Gustavsson <[email protected]>2018-08-13 09:26:36 +0200
commit7e1eb2ed1f724945884d839bd8a99154e9382849 (patch)
tree42dd357548847ad0197c825157a2b091838a6099 /lib/compiler/src
parent77d307e6c3e705e14843101d4c5348c6c079ace0 (diff)
downloadotp-7e1eb2ed1f724945884d839bd8a99154e9382849.tar.gz
otp-7e1eb2ed1f724945884d839bd8a99154e9382849.tar.bz2
otp-7e1eb2ed1f724945884d839bd8a99154e9382849.zip
Correct error behavior of is_map_key/2 in guards
Consider the following functions: foo() -> bar(not_a_map). bar(M) when not is_map_key(a, M) -> ok; bar(_) -> error. What will `foo/0` return? It depends. If the module is compiled with the default compiler options, the return value will be `ok`. If the module is compiled with the `inline` option, the return value will be `error`. The correct value is `error`, because the call to `is_map_key/2` when the second argument is not a map should fail the entire guard. That is the way other failing guards BIFs are handled. For example: foo() -> bar(not_a_tuple). bar(T) when not element(1, T) -> ok; bar(_) -> error. `foo/0` always returns `error` (whether the code is inlined or not). This bug can be fixed by changing the classification of `is_map_key/2` in the `erl_internal` module. It is now classified as a type test, which is incorrect because type tests should not fail. Reclassifying it as a plain guard BIF corrects the bug. This correction also fixes the internal consistency check failure which was reported in: https://bugs.erlang.org/browse/ERL-699
Diffstat (limited to 'lib/compiler/src')
-rw-r--r--lib/compiler/src/v3_codegen.erl5
1 files changed, 0 insertions, 5 deletions
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 6cd114abf7..e9152ba88f 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -1621,11 +1621,6 @@ test_cg(is_boolean, [#k_atom{val=Val}], Fail, I, Vdb, Bef, St) ->
false -> [{jump,{f,Fail}}]
end,
{Is,Aft,St};
-test_cg(is_map_key, As, Fail, I, Vdb, Bef, St) ->
- [Key,Map] = cg_reg_args(As, Bef),
- Aft = clear_dead(Bef, I, Vdb),
- F = {f,Fail},
- {[{test,is_map,F,[Map]},{test,has_map_fields,F,Map,{list,[Key]}}],Aft,St};
test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
Args = cg_reg_args(As, Bef),
Aft = clear_dead(Bef, I, Vdb),