diff options
author | Björn Gustavsson <[email protected]> | 2016-05-18 06:21:34 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-05-20 10:07:17 +0200 |
commit | 0f222d55ce46358aa7891ea482655937daaf8b52 (patch) | |
tree | 45bca0d751d744e4c5ec71f2a4ca3574bf7064a3 | |
parent | 6515f262cba9325bef84ce90758f2e74ebfb8c9e (diff) | |
download | otp-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.erl | 23 | ||||
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 11 |
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. |