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