1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2004-2019. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(match_SUITE).
21
22-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
23	 init_per_group/2,end_per_group/2,
24	 pmatch/1,mixed/1,aliases/1,non_matching_aliases/1,
25	 match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1,
26	 selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1,
27	 coverage/1,grab_bag/1,literal_binary/1,
28         unary_op/1,eq_types/1,match_after_return/1,match_right_tuple/1,
29         tuple_size_in_try/1]).
30
31-include_lib("common_test/include/ct.hrl").
32
33suite() -> [{ct_hooks,[ts_install_cth]}].
34
35all() ->
36    [{group,p}].
37
38groups() ->
39    [{p,[parallel],
40      [pmatch,mixed,aliases,non_matching_aliases,
41       match_in_call,untuplify,
42       shortcut_boolean,letify_guard,selectify,deselectify,
43       underscore,match_map,map_vars_used,coverage,
44       grab_bag,literal_binary,unary_op,eq_types,
45       match_after_return,match_right_tuple,
46       tuple_size_in_try]}].
47
48
49init_per_suite(Config) ->
50    test_lib:recompile(?MODULE),
51    Config.
52
53end_per_suite(_Config) ->
54    ok.
55
56init_per_group(_GroupName, Config) ->
57    Config.
58
59end_per_group(_GroupName, Config) ->
60    Config.
61
62
63pmatch(Config) when is_list(Config) ->
64    ok = doit(1),
65    ok = doit(2),
66    {error,baz} = doit(3),
67    {error,foobar} = doit(4),
68    ok.
69
70%% Thanks to Tobias Lindahl (HiPE).
71-define(FOO(X),
72	case X of
73	    1 -> foo;
74	    2 -> bar;
75	    3 -> baz;
76	    4 -> foobar
77	end).
78
79doit(X) ->
80    case ?FOO(X) of
81	foo -> ok;
82	bar -> ok;
83	Other -> {error, Other}
84    end.
85
86mixed(Config) when is_list(Config) ->
87    glufs = mixit(1),
88    klafs = mixit(2),
89    fnurra = mixit(3),
90    usch = mixit(4),
91    {error,blurf} = mixit(5),
92    {error,87987987} = mixit(6),
93    {error,{a,b,c}} = mixit(7),
94    ok.
95
96mixit(X) ->
97    case case X of
98	     1 -> a;
99	     2 -> b;
100	     3 -> 42;
101	     4 -> 77;
102	     4+1 -> blurf;
103	     5+1 -> 87987987;
104	     6+1 -> {a,b,c}
105	 end of
106	a -> glufs;
107	b -> klafs;
108	42 -> fnurra;
109	77 -> usch;
110	Other -> {error,Other}
111    end.
112
113aliases(Config) when is_list(Config) ->
114    %% Lists/strings.
115    ok = str_alias("abc"),
116    ok = str_alias("def"),
117    ok = str_alias("ghi"),
118    ok = str_alias("klm"),
119    ok = str_alias("qrs"),
120    ok = str_alias("xy"),
121    ok = str_alias(""),
122    ok = str_alias([]),
123    error = str_alias("blurf"),
124
125    %% Characters/integers.
126    ok = char_alias($v),
127    ok = char_alias(118),
128    ok = char_alias($w),
129    ok = char_alias(119),
130    ok = char_alias(42),
131    ok = char_alias(3.0),
132    error = char_alias($_),
133    error = char_alias(0),
134
135    {42,42,42} = three(42),
136
137    {1,42,99,1,42,99} = tuple_alias({1,42,99}),
138    {-10,20,-10,20,-10,20} = tuple_alias({-10,20}),
139    6 = tup_lit_alias({1,2,3}),
140    6 = tup_lit_alias_rev({1,2,3}),
141
142    {42,42,42,42} = multiple_aliases_1(42),
143    {7,7,7} = multiple_aliases_2(7),
144    {{a,b},{a,b},{a,b}} = multiple_aliases_3({a,b}),
145
146    %% Lists/literals.
147    {a,b} = list_alias1([a,b]),
148    {a,b} = list_alias2([a,b]),
149    {a,b} = list_alias3([a,b]),
150
151    ok.
152
153str_alias(V) ->
154    Res = str_alias_1(V),
155    Res = str_alias_2(V).
156
157str_alias_1([$a,$b,$c]="abc"="a"++[$b,$c]=[97,98,99]) -> ok;
158str_alias_1([$d|"ef"]="def") -> ok;
159str_alias_1([$g|"hi"]="g"++"hi"="gh"++"i"="ghi"++"") -> ok;
160str_alias_1("k"++"lm"=[$k|"lm"]) -> ok;
161str_alias_1([113,114,115]="qrs"=[$q,$r,$s]="q"++"r"++"s") -> ok;
162str_alias_1([$x,$y]="xy") -> ok;
163str_alias_1(""=[]) -> ok;
164str_alias_1(_) -> error.
165
166%% Make sure that different line numbers do not matter.
167
168str_alias_2([$a,$b,$c]=
169	    "abc"=
170	    "a"++[$b,$c
171	       ]=
172	    [97,98,99
173	  ]) -> ok;
174str_alias_2([$d|"ef"]=
175	  "def") -> ok;
176str_alias_2([$g|"hi"]=
177	  "g"++"hi"=
178	  "gh"++"i"=
179	  "ghi"++"") -> ok;
180str_alias_2("k"++"lm"=
181	  [$k|"lm"
182	  ]) -> ok;
183str_alias_2([113,114,115]=
184	  "qrs"=[$q,$r,$s
185		]=
186	  "q"++"r"++"s") -> ok;
187str_alias_2([$x,$y]=
188	  "xy") -> ok;
189str_alias_2(""=
190	  []) -> ok;
191str_alias_2(_) -> error.
192
193char_alias(V) ->
194    Res = char_alias_1(V),
195    Res = char_alias_2(V).
196
197char_alias_1(118=$v) -> ok;
198char_alias_1($w=119) -> ok;
199char_alias_1(42=42) -> ok;
200char_alias_1(3.0=3.0) -> ok;
201char_alias_1(_) -> error.
202
203char_alias_2(118=
204	     $v) -> ok;
205char_alias_2($w=
206	     119) -> ok;
207char_alias_2(42=
208	     42) -> ok;
209char_alias_2(3.0=
210	     3.0) -> ok;
211char_alias_2(_) -> error.
212
213three(V) ->
214    Res = three_1(V),
215    Res = three_2(V).
216
217three_1(A=B=C) ->
218    {A,B,C}.
219
220three_2(A=
221	B=
222	C) ->
223    {A,B,C}.
224
225tuple_alias({A,B,C}={X,Y,Z}) ->
226    {A,B,C,X,Y,Z};
227tuple_alias({A,B}={C,D}={E,F}) ->
228    {A,B,C,D,E,F}.
229
230tup_lit_alias({A,B,C}={1,2,3}) ->
231    A+B+C.
232
233tup_lit_alias_rev({1,2,3}={A,B,C}) ->
234    A+B+C.
235
236multiple_aliases_1((A=B)=(C=D)) ->
237    {A,B,C,D}.
238
239multiple_aliases_2((A=B)=(A=C)) ->
240    {A,B,C}.
241
242multiple_aliases_3((A={_,_}=B)={_,_}=C) ->
243    {A,B,C}.
244
245list_alias1([a,b]=[X,Y]) ->
246    {X,Y}.
247
248list_alias2([X,Y]=[a,b]) ->
249    {X,Y}.
250
251list_alias3([X,b]=[a,Y]) ->
252    {X,Y}.
253
254non_matching_aliases(_Config) ->
255    none = mixed_aliases(<<42>>),
256    none = mixed_aliases([b]),
257    none = mixed_aliases([d]),
258    none = mixed_aliases({a,42}),
259    none = mixed_aliases(42),
260    none = mixed_aliases(<<6789:16>>),
261    none = mixed_aliases(#{key=>value}),
262
263    {'EXIT',{{badmatch,42},_}} = (catch nomatch_alias(42)),
264    {'EXIT',{{badmatch,job},_}} = (catch entirely()),
265    {'EXIT',{{badmatch,associates},_}} = (catch printer()),
266    {'EXIT',{{badmatch,borogoves},_}} = (catch tench()),
267
268    put(perch, 0),
269    {'EXIT',{{badmatch,{spine,42}},_}} = (catch perch(42)),
270    1 = erase(perch),
271
272    put(salmon, 0),
273    {'EXIT',{{badmatch,mimsy},_}} = (catch salmon()),
274    1 = erase(salmon),
275
276    put(shark, 0),
277    {'EXIT',{{badmatch,_},_}} = (catch shark()),
278    1 = erase(shark),
279
280    {'EXIT',{{badmatch,_},_}} = (catch radio(research)),
281    ok.
282
283mixed_aliases(<<X:8>> = x) -> {a,X};
284mixed_aliases([b] = <<X:8>>) -> {b,X};
285mixed_aliases(<<X:8>> = {a,X}) -> {c,X};
286mixed_aliases([X] = <<X:8>>) -> {d,X};
287mixed_aliases(<<X:16>> = X) -> {e,X};
288mixed_aliases(X = <<X:16>>) -> {f,X};
289mixed_aliases(<<X:16,_/binary>> = X) -> {g,X};
290mixed_aliases(X = <<X:16,_/binary>>) -> {h,X};
291mixed_aliases(X = #{key:=X}) -> {i,X};
292mixed_aliases(#{key:=X} = X) -> {j,X};
293mixed_aliases([X] = #{key:=X}) -> {k,X};
294mixed_aliases(#{key:=X} = [X]) -> {l,X};
295mixed_aliases({a,X} = #{key:=X}) -> {m,X};
296mixed_aliases(#{key:=X} = {a,X}) -> {n,X};
297mixed_aliases(_) -> none.
298
299nomatch_alias(I) ->
300    {ok={A,B}} = id(I),
301    {A,B}.
302
303entirely() ->
304    0(((Voice = true) = cool) = job),
305    [receive _ -> Voice end || banking <- printer].
306
307printer() ->
308    {[Indoor] = [] = associates},
309    [ireland || Indoor <- Indoor].
310
311tench() ->
312    E = begin
313	    [A] = [] = borogoves,
314	    A + 1
315	end,
316    E + 7 * A.
317
318perch(X) ->
319    begin
320	put(perch, get(perch)+1),
321	[A] = [] = {spine,X}
322    end.
323
324salmon() ->
325    {put(salmon, get(salmon)+1),#{key:=([A]=[])}=mimsy,exit(fail)},
326    A + 10.
327
328shark() ->
329    (hello = there) = (catch shark(put(shark, get(shark)+1), a = b)).
330
331shark(_, _) ->
332    ok.
333
334radio(research) ->
335    (connection = proof) =
336	(catch erlang:trace_pattern(catch mechanisms + assist,
337				    summary = mechanisms)).
338
339%% OTP-7018.
340
341match_in_call(Config) when is_list(Config) ->
342    mac_a(0),
343    mac_b(1),
344    mac_c(42),
345    mac_d(42),
346    mac_e({gurka,42}),
347
348    [{2,2},{2,2}] = mac_lc([{2,any},{2,2}]),
349    {'EXIT',_} = (catch mac_lc([{1,1}])),
350
351    ok.
352
353mac_a(X) ->
354    id(_Gurka = {gurka,X}),
355    ok.
356
357mac_b(X) ->
358    id(Gurka = {gurka,X}),
359    gurka(Gurka, X),
360    ok.
361
362mac_c(X) ->
363    id(Gurka = Yxa = {gurka,X}),
364    id({Gurka,Yxa}),
365    ok.
366
367mac_d(X) ->
368    id({gurka,42} = {gurka,X}),
369    ok.
370
371mac_e(X) ->
372    id({gurka,42} = X),
373    ok.
374
375mac_lc(E) ->
376    Res = mac_lc1(E),
377    Res = mac_lc2(E).
378
379mac_lc1(E) ->
380    [{X,Y} ||
381	{X,_} <- E,
382	(Y = X) =:= (Y = 1 + 1)].
383
384mac_lc2(E) ->
385    [{X,Y} ||
386	{X,_} <- E,
387	(Y = X) =:= (Y = 2)].
388
389gurka({gurka,X}, X) -> ok.
390
391
392untuplify(Config) when is_list(Config) ->
393    %% We do this to cover sys_core_fold:unalias_pat/1.
394    {1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias),
395    error = untuplify_1([1,2], {3,4}, 42),
396
397    %% Test that a previous bug in v3_codegen is gone. (The sinking of
398    %% stack frames into only the case arms that needed them was not always
399    %% safe.)
400    [33, -1, -33, 1] = untuplify_2(32, 65),
401    {33, 1, -33, -1} = untuplify_2(65, 32),
402
403    ok.
404
405untuplify_1(A, B, C) ->
406    case {A,B,C} of
407	{[X,Y],{Z,W},alias=Alias}=Top ->
408	    {X,Y,Z,W,Alias,Top};
409	[_,_]=CantMatch ->
410	    CantMatch;
411	_ ->
412	    error
413    end.
414
415untuplify_2(V1, V2) ->
416    {D1,D2,D3,D4} =
417        if V1 > V2 ->
418                %% The 1 value was overwritten by the value of V2-V1.
419                {V1-V2,  1,  V2-V1, -1};
420           true ->
421                {V2-V1, -1, V1-V2,  1}
422        end,
423    if
424        D2 > D4 ->
425            {D1, D2, D3, D4};
426        true ->
427            [D1, D2, D3, D4]
428    end.
429
430%% Coverage of beam_dead:shortcut_boolean_label/4.
431shortcut_boolean(Config) when is_list(Config) ->
432    false = shortcut_boolean_1([0]),
433    true = shortcut_boolean_1({42}),
434    maybe = shortcut_boolean_1(self()),
435    {'EXIT',_} = (catch shortcut_boolean_1([a,b])),
436    {'EXIT',_} = (catch shortcut_boolean_1({a,b})),
437    ok.
438
439shortcut_boolean_1(X) ->
440    Outer = case not is_pid(X) of
441		true ->
442		    V = case X of
443			    [_] -> true;
444			    {_} -> false
445			end,
446		    not V;
447		false ->
448		    maybe
449	    end,
450    id(Outer).
451
452
453%% Test sys_core_fold:letify_guard/3.
454letify_guard(Config) when is_list(Config) ->
455    {-15,a} = letify_guard(-15, a),
456    5 = letify_guard(2, 3),
457    ok.
458
459letify_guard(A, B) ->
460    case {A,B} of
461	%% The tuple will be built in the guard...
462	Z when tuple_size(Z) =:= 2, element(1, Z) < 0 ->
463	    %% ... and again here.
464	    Z;
465	{X,Y} -> X+Y
466    end.
467
468%% Test combining of is_eq_exact instructions to select_val
469%% instructions in beam_dead and beam_peep.
470
471selectify(Config) when is_list(Config) ->
472    integer = sel_different_types({r,42}),
473    atom = sel_different_types({r,forty_two}),
474    float = sel_different_types({r,100.0}),
475    none = sel_different_types({r,18}),
476    {'EXIT',_} = (catch sel_different_types([a,b,c])),
477
478    integer = sel_same_value({r,42}),
479    error = sel_same_value({r,100}),
480    error = sel_same_value(a),
481
482    integer42 = sel_same_value2(42),
483    integer43 = sel_same_value2(43),
484    error = sel_same_value2(44),
485
486    ok.
487
488sel_different_types({r,_}=T) when element(2, T) =:= forty_two ->
489    atom;
490sel_different_types({r,_}=T) when element(2, T) =:= 42 ->
491    integer;
492sel_different_types({r,_}=T) when element(2, T) =:= 100.0 ->
493    float;
494sel_different_types({r,_}) ->
495    none.
496
497sel_same_value({r,V}) when V =:= 42 ->
498    integer;
499sel_same_value({r,V}) when V =:= 42 ->
500    integer42;
501sel_same_value(_) ->
502    error.
503
504sel_same_value2(V) when V =:= 42 ->
505    integer42;
506sel_same_value2(V) when V =:= 42; V =:= 43 ->
507    integer43;
508sel_same_value2(_) ->
509    error.
510
511%% Test deconstruction of select_val instructions to regular tests
512%% with zero or one values left.
513
514deselectify(Config) when is_list(Config) ->
515    one_or_other = desel_tuple_arity({1}),
516    two = desel_tuple_arity({1,1}),
517    one_or_other = desel_tuple_arity({1,1,1}),
518
519    one_or_other = dsel_integer(1),
520    two = dsel_integer(2),
521    one_or_other = dsel_integer(3),
522
523    one_or_other = dsel_integer_typecheck(1),
524    two = dsel_integer_typecheck(2),
525    one_or_other = dsel_integer_typecheck(3),
526
527    one_or_other = dsel_atom(one),
528    two = dsel_atom(two),
529    one_or_other = dsel_atom(three),
530
531    one_or_other = dsel_atom_typecheck(one),
532    two = dsel_atom_typecheck(two),
533    one_or_other = dsel_atom_typecheck(three),
534
535    %% Cover deconstruction of select_val instructions in
536    %% beam_peep.
537
538    stop = dsel_peek_0(stop),
539    ignore = dsel_peek_0(ignore),
540    Config = dsel_peek_0(Config),
541
542    stop = dsel_peek_1(stop, any),
543    Config = dsel_peek_1(ignore, Config),
544    other = dsel_peek_1(other, ignored),
545
546    0 = dsel_peek_2(0, any),
547    Config = dsel_peek_2(1, Config),
548    2 = dsel_peek_2(2, ignored),
549
550    true = dsel_peek_3(true),
551    false = dsel_peek_3(false),
552    {error,Config} = dsel_peek_3(Config),
553
554    ok.
555
556%% The following will be optimized by the sharing optimizations
557%% in beam_ssa_opt.
558
559desel_tuple_arity(Tuple) when is_tuple(Tuple) ->
560    case Tuple of
561        {_} -> one_or_other;
562        {_,_} -> two;
563        _ -> one_or_other
564    end.
565
566dsel_integer(Val) ->
567    case Val of
568        1 -> one_or_other;
569        2 -> two;
570        _ -> one_or_other
571    end.
572
573dsel_integer_typecheck(Val) when is_integer(Val) ->
574    case Val of
575        1 -> one_or_other;
576        2 -> two;
577        _ -> one_or_other
578    end.
579
580dsel_atom(Val) ->
581    case Val of
582        one -> one_or_other;
583        two -> two;
584        _ -> one_or_other
585    end.
586
587dsel_atom_typecheck(Val) when is_atom(Val) ->
588    case Val of
589        one -> one_or_other;
590        two -> two;
591        _ -> one_or_other
592    end.
593
594%% The following functions are carefully crafted so that the sharing
595%% optimizations in beam_ssa_opt can't be applied. After applying the
596%% beam_jump:eliminate_moves/1 optimization and beam_clean:clean_labels/1
597%% has unified labels, beam_peep is able to optimize these functions.
598
599dsel_peek_0(A0) ->
600    case id(A0) of
601        stop ->   stop;
602        ignore -> ignore;
603        A ->      A
604    end.
605
606dsel_peek_1(A0, B) ->
607    case id(A0) of
608        stop ->   stop;
609        ignore -> B;
610        A ->      A
611    end.
612
613dsel_peek_2(A0, B) ->
614    case id(A0) of
615        0 -> 0;
616        1 -> B;
617        A -> A
618    end.
619
620dsel_peek_3(A0) ->
621    case id(A0) of
622        true ->  true;
623        false -> false;
624        Other -> {error,Other}
625    end.
626
627underscore(Config) when is_list(Config) ->
628    case Config of
629	[] ->
630	    %% Assignment to _ at the end of a construct.
631	    _ = length(Config);
632	[_|_] ->
633	    %% Assignment to _ at the end of a construct.
634	    _ = list_to_tuple(Config)
635    end,
636    _ = is_list(Config),
637    ok.
638
639-record(s, {map,t}).
640
641match_map(Config) when is_list(Config) ->
642    Map = #{key=>{x,y},ignore=>anything},
643    #s{map=Map,t={x,y}} = do_match_map(#s{map=Map}),
644    {a,#{k:={a,b,c}}} = do_match_map_2(#{k=>{a,b,c}}),
645    ok.
646
647do_match_map(#s{map=#{key:=Val}}=S) ->
648    %% Would crash with a 'badarg' exception.
649    S#s{t=Val}.
650
651do_match_map_2(Map) ->
652    case {a,Map} of
653	{a,#{k:=_}}=Tuple ->
654	    Tuple
655    end.
656
657map_vars_used(Config) when is_list(Config) ->
658    {some,value} = do_map_vars_used(a, b, #{{a,b}=>42,v=>{some,value}}),
659    ok.
660
661do_map_vars_used(X, Y, Map) ->
662    case {X,Y} of
663	T ->
664	    %% core_lib:is_var_used/2 would not consider T used.
665	    #{T:=42,v:=Val} = Map,
666	    Val
667    end.
668
669-record(coverage_id, {bool=false,id}).
670coverage(Config) when is_list(Config) ->
671    %% Cover beam_dead.
672    ok = coverage_1(x, a),
673    ok = coverage_1(x, b),
674
675    %% Cover sys_pre_expand.
676    ok = coverage_3("abc"),
677
678    %% Cover beam_ssa_dead.
679    {expr,key} = coverage_4([literal,get], [[expr,key]]),
680    {expr,key} = coverage_4([expr,key], []),
681
682    a = coverage_5([8,8,8], #coverage_id{bool=true}),
683    b = coverage_5([], #coverage_id{bool=true}),
684
685    %% Cover beam_ssa_opt.
686    ok = coverage_6(),
687
688    ok.
689
690coverage_1(B, Tag) ->
691    case Tag of
692	a -> coverage_2(1, a, B);
693	b -> coverage_2(2, b, B)
694    end.
695
696coverage_2(1, a, x) -> ok;
697coverage_2(2, b, x) -> ok.
698
699coverage_3([$a]++[]++"bc") -> ok.
700
701%% Cover beam_ssa_dead:eval_type_test_1(is_nonempty_list, Arg).
702coverage_4([literal,get], [Expr]) ->
703    coverage_4(Expr, []);
704coverage_4([Expr,Key], []) ->
705    {Expr,Key}.
706
707%% Cover beam_ssa_dead:eval_type_test_1(is_tagged_tuple, Arg).
708coverage_5(Config, TermId)
709  when TermId =:= #coverage_id{bool=true},
710       Config =:= [8,8,8] ->
711    a;
712coverage_5(_Config, #coverage_id{bool=true}) ->
713    b.
714
715coverage_6() ->
716    X = 17,
717    case
718        case id(1) > 0 of
719            true ->
720                17;
721            false ->
722                42
723        end
724    of
725        X ->
726            ok;
727        V ->
728            %% Cover beam_ssa_opt:make_literal/2.
729            error([error,X,V])
730    end.
731
732grab_bag(_Config) ->
733    [_|T] = id([a,b,c]),
734    [b,c] = id(T),
735
736    T1 = fun() ->
737		 [_|_] = x
738	 end,
739    {'EXIT',_} = (catch T1()),
740
741    T2 = fun(A, B) ->
742		 case {{element(1, A),element(2, B)},
743		       {element(2, A),element(2, B)}} of
744		     {Same,Same} -> ok;
745		     {{0,1},{up,X}} -> id(X);
746		     {_,{X,_}} -> id(X)
747		 end
748	 end,
749    ok = T2({a,a,z,z}, {z,a,z}),
750    1 = T2({0,up}, {zzz,1}),
751    y = T2({x,y}, {a,z,z}),
752
753    %% OTP-5244.
754    L = [{stretch,0,0},
755	 {bad,[]},
756	 {bad,atom},
757	 {bad,0},
758	 {bad,16#AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA},
759	 {bad,16#555555555555555555555555555555555555555555555555555}],
760    ok = grab_bag_remove_failure(L, unit, 0),
761
762    {42,<<43,44>>} = grab_bag_single_valued(<<42,43,44>>),
763    empty_list = grab_bag_single_valued([]),
764    empty_tuple = grab_bag_single_valued({}),
765
766    ok.
767
768grab_bag_remove_failure([], _Unit, _MaxFailure) ->
769    ok;
770grab_bag_remove_failure([{bad,Bad}|_], _Unit, _MaxFailure) ->
771    Bad;
772grab_bag_remove_failure([{stretch,_,Mi}=Stretch | Specs], Unit, _MaxFailure) ->
773    {MinMax,NewMaxFailure} = id({min,1}),
774    case {MinMax,grab_bag_remove_failure(Specs, Unit, NewMaxFailure)} of
775	{min,{NewMaxFailure,Rest}} ->
776	    {done,[{fixed,Mi} | Rest]};
777	{min,_} when Specs =/= [] ->
778	    grab_bag_remove_failure([Stretch|tl(Specs)], Unit, NewMaxFailure);
779	{min,_} ->
780	    ok
781    end.
782
783%% Cover a line v3_kernel that places binary matching first.
784grab_bag_single_valued(<<H,T/bytes>>) -> {H,T};
785grab_bag_single_valued([]) -> empty_list;
786grab_bag_single_valued({}) -> empty_tuple.
787
788
789%% Regression in 19.0, reported by Alexei Sholik
790literal_binary(_Config) ->
791    3 = literal_binary_match(bar, <<"y">>),
792
793    %% While we are at it, also test the remaining code paths
794    %% in literal_binary_match/2.
795    1 = literal_binary_match(bar, <<"x">>),
796    2 = literal_binary_match(foo, <<"x">>),
797    3 = literal_binary_match(foo, <<"y">>),
798    fail = literal_binary_match(bar, <<"z">>),
799    fail = literal_binary_match(foo, <<"z">>),
800    ok.
801
802literal_binary_match(bar, <<"x">>) -> 1;
803literal_binary_match(_, <<"x">>) -> 2;
804literal_binary_match(_, <<"y">>) -> 3;
805literal_binary_match(_, _) -> fail.
806
807unary_op(Config) ->
808    %% ERL-514. This test case only verifies that the code
809    %% calculates the correct result, not that the generated
810    %% code is optimial.
811
812    {non_associative,30} = unary_op_1('&'),
813    {non_associative,300} = unary_op_1('^'),
814    {non_associative,300} = unary_op_1('not'),
815    {non_associative,300} = unary_op_1('+'),
816    {non_associative,300} = unary_op_1('-'),
817    {non_associative,300} = unary_op_1('~~~'),
818    {non_associative,300} = unary_op_1('!'),
819    {non_associative,320} = unary_op_1('@'),
820
821    error = unary_op_1(Config),
822    error = unary_op_1(abc),
823    error = unary_op_1(42),
824
825    ok.
826
827unary_op_1(Vop@1) ->
828    %% If all optimizations are working as they should, there should
829    %% be no stack frame and all '=:=' tests should be coalesced into
830    %% a single select_val instruction.
831
832    case Vop@1 =:= '&' of
833        true ->
834            {non_associative,30};
835        false ->
836            case
837                case Vop@1 =:= '^' of
838                    true ->
839                        true;
840                    false ->
841                        case Vop@1 =:= 'not' of
842                            true ->
843                                true;
844                            false ->
845                                case Vop@1 =:= '+' of
846                                    true ->
847                                        true;
848                                    false ->
849                                        case Vop@1 =:= '-' of
850                                            true ->
851                                                true;
852                                            false ->
853                                                case Vop@1 =:= '~~~' of
854                                                    true ->
855                                                        true;
856                                                    false ->
857                                                        Vop@1 =:= '!'
858                                                end
859                                        end
860                                end
861                        end
862                end
863            of
864                true ->
865                    {non_associative,300};
866                false ->
867                    case Vop@1 =:= '@' of
868                        true ->
869                            {non_associative,320};
870                        false ->
871                            error
872                    end
873            end
874    end.
875
876eq_types(_Config) ->
877    Ref = make_ref(),
878    Ref = eq_types(Ref, any),
879    ok.
880
881eq_types(A, B) ->
882    %% {put_tuple2,{y,0},{list,[{x,0},{x,1}]}}.
883    Term0 = {A, B},
884    Term = id(Term0),
885
886    %% {test,is_eq_exact,{f,3},[{y,0},{x,0}]}.
887    %% Here beam_validator must infer that {x,0} has the
888    %% same type as {y,0}.
889    Term = Term0,
890
891    %% {get_tuple_element,{x,0},0,{x,0}}.
892    {Ref22,_} = Term,
893
894    Ref22.
895
896match_after_return(Config) when is_list(Config) ->
897    %% The return type of the following call will never match the 'wont_happen'
898    %% clauses below, and the beam_ssa_type was clever enough to see that but
899    %% didn't remove the blocks, so it crashed when trying to extract A.
900    ok = case mar_test_tuple(erlang:unique_integer()) of
901            {gurka, never_matches, A} -> {wont_happen, A};
902            _ -> ok
903         end.
904
905mar_test_tuple(I) -> {gurka, I}.
906
907match_right_tuple(Config) when is_list(Config) ->
908    %% The loader wrongly coalesced certain get_tuple_element sequences, fusing
909    %% the code below into a single i_get_tuple_element2 operating on {x,0}
910    %% even though the first one overwrites it.
911    %%
912    %%    {get_tuple_element,{x,0},0,{x,0}}.
913    %%    {get_tuple_element,{x,0},1,{x,1}}.
914
915    Inner = {id(wrong_element), id(ok)},
916    Outer = {Inner, id(wrong_tuple)},
917    ok = match_right_tuple_1(Outer).
918
919match_right_tuple_1(T) ->
920    {A, _} = T,
921    {_, B} = A,
922    %% The call ensures that A is in {x,0} and B is in {x,1}
923    id(force_succ_regs(A, B)).
924
925force_succ_regs(_A, B) -> B.
926
927tuple_size_in_try(Config) when is_list(Config) ->
928    %% The tuple_size optimization was applied outside of guards, causing
929    %% either the emulator or compiler to crash.
930    ok = tsit(gurka),
931    ok = tsit(gaffel).
932
933tsit(A) ->
934    try
935        id(ignored),
936        1 = tuple_size(A),
937        error
938    catch
939        _:_ -> ok
940    end.
941
942id(I) -> I.
943