aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-06-27 13:48:21 +0200
committerBjörn Gustavsson <[email protected]>2018-06-27 14:01:52 +0200
commitc221bb38a80f8c3c4263ebdd609ff8ae6e5d117f (patch)
treeae6c51ad3bde8c727a2bd4b533b974550d389f92
parenta0ae44f324576104760a63fe6cf63e0ca31756fc (diff)
downloadotp-c221bb38a80f8c3c4263ebdd609ff8ae6e5d117f.tar.gz
otp-c221bb38a80f8c3c4263ebdd609ff8ae6e5d117f.tar.bz2
otp-c221bb38a80f8c3c4263ebdd609ff8ae6e5d117f.zip
Fix internal compiler error for map_get/2
Code such as that the following: Val = map_get(a, Map), Map#{a:=z} %Could be any map update would incorrectly cause an internal consistency check failure: Internal consistency check failed - please report this bug. Instruction: {put_map_exact,{f,0},{x,0},{x,0},1,{list,[{atom,a},{atom,z}]}} Error: {bad_type,{needed,map},{actual,term}}: Update beam_validator so that it understands that the second argument for map_get/2 is a map.
-rw-r--r--lib/compiler/src/beam_validator.erl6
-rw-r--r--lib/compiler/test/map_SUITE.erl6
2 files changed, 12 insertions, 0 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index b03fadb197..a1b71251b7 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -546,6 +546,12 @@ valfun_4({bif,raise,{f,0},Src,_Dst}, Vst) ->
kill_state(Vst);
valfun_4(raw_raise=I, Vst) ->
call(I, 3, Vst);
+valfun_4({bif,map_get,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) ->
+ validate_src(Src, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ Vst = set_type(map, Map, Vst1),
+ Type = propagate_fragility(term, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
valfun_4({bif,Op,{f,Fail},Src,Dst}, Vst0) ->
validate_src(Src, Vst0),
Vst = branch_state(Fail, Vst0),
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index 6badc7a8b8..494faf299b 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -706,6 +706,12 @@ t_map_get(Config) when is_list(Config) ->
{'EXIT',{{badmap,[]},_}} = (catch map_get(a, [])),
{'EXIT',{{badmap,<<1,2,3>>},_}} = (catch map_get(a, <<1,2,3>>)),
{'EXIT',{{badmap,1},_}} = (catch map_get(a, 1)),
+
+ %% Test that beam_validator understands that NewMap is
+ %% a map after seeing map_get(a, NewMap).
+ NewMap = id(#{a=>b}),
+ b = map_get(a, NewMap),
+ #{a:=z} = NewMap#{a:=z},
ok.
check_map_value(Map, Key, Value) when map_get(Key, Map) =:= Value -> true;