aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2016-05-18 06:21:34 +0200
committerBjörn Gustavsson <[email protected]>2016-05-20 10:07:17 +0200
commit0f222d55ce46358aa7891ea482655937daaf8b52 (patch)
tree45bca0d751d744e4c5ec71f2a4ca3574bf7064a3
parent6515f262cba9325bef84ce90758f2e74ebfb8c9e (diff)
downloadotp-0f222d55ce46358aa7891ea482655937daaf8b52.tar.gz
otp-0f222d55ce46358aa7891ea482655937daaf8b52.tar.bz2
otp-0f222d55ce46358aa7891ea482655937daaf8b52.zip
beam_type: Correct handling of setelement/3
We must be careful how we treat the type info for the result of: setelement(Index, Tuple, NewValue) If Tuple had type information, the result of setelement/3 (in x(0)) would be assigned the same type information. But that is not safe for: setelement(1, Tuple, NewValue) since the type for the first element will be changed. Therefore, we must take care to remove the type information for the first element of the tuple if might have been modified by setelement/3.
-rw-r--r--lib/compiler/src/beam_type.erl23
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl11
2 files changed, 26 insertions, 8 deletions
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 5076c5eb96..79f93d7548 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -513,12 +513,23 @@ update({call_ext,Ar,{extfunc,math,Math,Ar}}, Ts) ->
false -> tdb_kill_xregs(Ts)
end;
update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
- Op = case tdb_find({x,1}, Ts0) of
- error -> kill;
- Info -> Info
- end,
- Ts1 = tdb_kill_xregs(Ts0),
- tdb_update([{{x,0},Op}], Ts1);
+ Ts = tdb_kill_xregs(Ts0),
+ case tdb_find({x,1}, Ts0) of
+ {tuple,Sz,_}=T0 ->
+ T = case tdb_find({x,0}, Ts0) of
+ {integer,{I,I}} when I > 1 ->
+ %% First element is not changed. The result
+ %% will have the same type.
+ T0;
+ _ ->
+ %% Position is 1 or unknown. May change the
+ %% first element of the tuple.
+ {tuple,Sz,[]}
+ end,
+ tdb_update([{{x,0},T}], Ts);
+ _ ->
+ Ts
+ end;
update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts);
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 8d5c0190ed..063a27ad8d 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -21,7 +21,7 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
- integers/1,coverage/1,booleans/1]).
+ integers/1,coverage/1,booleans/1,setelement/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -33,7 +33,8 @@ groups() ->
[{p,[parallel],
[integers,
coverage,
- booleans
+ booleans,
+ setelement
]}].
init_per_suite(Config) ->
@@ -94,5 +95,11 @@ do_booleans(B) ->
no -> no
end.
+setelement(_Config) ->
+ T0 = id({a,42}),
+ {a,_} = T0,
+ {b,_} = setelement(1, T0, b),
+ ok.
+
id(I) ->
I.