diff options
author | Erlang/OTP <[email protected]> | 2019-05-29 13:24:42 +0200 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2019-05-29 13:24:42 +0200 |
commit | f9b7f0c9202ccfeb8b09844f6ae689acb30447a2 (patch) | |
tree | 0b86da5178d6e8d1cc3c08eda52d8e4f1433760f | |
parent | 9afe8ad5eb15c1a205ca428d84c06d4a1fe888cc (diff) | |
parent | 00dc96a9a0086e829e574b651b4a28155aa826df (diff) | |
download | otp-f9b7f0c9202ccfeb8b09844f6ae689acb30447a2.tar.gz otp-f9b7f0c9202ccfeb8b09844f6ae689acb30447a2.tar.bz2 otp-f9b7f0c9202ccfeb8b09844f6ae689acb30447a2.zip |
Merge branch 'john/compiler/list_append_type/OTP-15841' into maint-22
* john/compiler/list_append_type/OTP-15841:
compiler: Fix broken type for erlang:'++'/2
-rw-r--r-- | lib/compiler/src/beam_ssa_type.erl | 14 | ||||
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 12 | ||||
-rw-r--r-- | lib/compiler/test/beam_type_SUITE.erl | 11 |
3 files changed, 26 insertions, 11 deletions
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 2ea7e89dfa..34cdd0d663 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -896,11 +896,15 @@ type(call, [#b_remote{mod=#b_literal{val=Mod}, {_,_} -> #t_tuple{} end; - {erlang,'++',[List1,List2]} -> - case get_type(List1, Ts) =:= cons orelse - get_type(List2, Ts) =:= cons of - true -> cons; - false -> list + {erlang,'++',[LHS,RHS]} -> + LType = get_type(LHS, Ts), + RType = get_type(RHS, Ts), + case LType =:= cons orelse RType =:= cons of + true -> + cons; + false -> + %% `[] ++ RHS` yields RHS, even if RHS is not a list. + join(list, RType) end; {erlang,'--',[_,_]} -> list; diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 09a5a6c104..ebe9631e09 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -2844,10 +2844,14 @@ call_return_type_1(erlang, setelement, 3, Vst) -> setelement(3, TupleType, #{}) end; call_return_type_1(erlang, '++', 2, Vst) -> - case get_term_type({x,0}, Vst) =:= cons orelse - get_term_type({x,1}, Vst) =:= cons of - true -> cons; - false -> list + LType = get_term_type({x,0}, Vst), + RType = get_term_type({x,1}, Vst), + case LType =:= cons orelse RType =:= cons of + true -> + cons; + false -> + %% `[] ++ RHS` yields RHS, even if RHS is not a list + join(list, RType) end; call_return_type_1(erlang, '--', 2, _Vst) -> list; diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 0d1680fb15..2297c2e0f5 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -24,7 +24,7 @@ integers/1,numbers/1,coverage/1,booleans/1,setelement/1, cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1, arity_checks/1,elixir_binaries/1,find_best/1, - test_size/1,cover_lists_functions/1]). + test_size/1,cover_lists_functions/1,list_append/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -47,7 +47,8 @@ groups() -> elixir_binaries, find_best, test_size, - cover_lists_functions + cover_lists_functions, + list_append ]}]. init_per_suite(Config) -> @@ -501,5 +502,11 @@ cover_lists_functions(Config) -> true = is_list(Zipped), ok. +list_append(_Config) -> + %% '++'/2 has a quirk where it returns the right-hand argument as-is when + %% the left-hand is []. + hello = id([]) ++ id(hello), + ok. + id(I) -> I. |